# Push Command

The `push` command builds Supabase migrations from growth loop telemetry definitions and optionally pushes the artifacts to Skene Cloud upstream.

On every run, `push` checks and updates the base schema migration (`skene_growth_schema`). If the schema file already exists, it is overwritten with the current version—no duplicate migrations are created.

## Prerequisites

Before running `push`, you need:

- Growth loop definitions with Supabase telemetry in `skene-context/growth-loops/`. These are generated by the `build` command. See [Build](build.md) for details. (Not required for `--push-only`.)
- For upstream push: authentication via `skene login`. See [Login](login.md).

## Basic usage

Generate a Supabase migration from all growth loops with telemetry:

```bash
uvx skene push
```

Push a specific loop by ID:

```bash
uvx skene push --loop my_activation_loop
```

Push to upstream (Skene Cloud):

```bash
uvx skene push --upstream https://skene.ai/workspace/my-app
```

Build migrations locally without pushing (no upstream required):

```bash
uvx skene push --local
```

Build migrations locally and bake a custom upstream ingest URL into the webhook (for self-hosted or custom ingest):

```bash
uvx skene push --local --ingest-url https://skene.ai --proxy-secret my-secret
```

## Flag reference

| Flag | Short | Description |
|------|-------|-------------|
| `PATH` | | Project root directory (default: `.`) |
| `--context PATH` | `-c` | Path to `skene-context` directory (auto-detected if omitted) |
| `--loop TEXT` | `-l` | Push only this loop by `loop_id`. If omitted, pushes all loops with Supabase telemetry. |
| `--upstream TEXT` | `-u` | Upstream workspace URL (e.g. `https://skene.ai/workspace/my-app`). Resolved from `.skene.config` or this flag. |
| `--push-only` | | Re-push current output without regenerating migrations |
| `--local` | | Build schema + telemetry migrations locally without pushing (uses default Skene Cloud ingest URL). Mutually exclusive with `--upstream` and `--push-only`. |
| `--ingest-url TEXT` | | Custom upstream ingest URL to bake into `notify_event_log()`. Use with `--local`. Default: `https://www.skene.ai/api/v1/cloud/ingest/db-trigger`. |
| `--proxy-secret TEXT` | | Proxy secret for the `x-skene-secret` header in `notify_event_log()`. Use with `--local`. Default: `YOUR_PROXY_SECRET` placeholder. |

## How it works

### Step 1: Check and update base schema (every run)

On every `push` run, the command ensures the base schema migration exists and is up to date:

- Creates `supabase/migrations/20260201000000_skene_growth_schema.sql` if it does not exist
- Overwrites the existing file if it does (no duplicate migrations)

The schema includes:

- `skene_growth.event_log` — universal sink for allowlisted triggers
- `skene_growth.failed_events` — dead-letter queue for events exceeding retry limits
- `skene_growth.enrichment_map` — rules table for metadata enrichment
- `skene_growth.enrich_event()` — BEFORE INSERT trigger for enrichment
- `skene_growth.notify_event_log()` — AFTER INSERT trigger that POSTs to upstream ingest URL via pg_net

You can also run `skene push --init` to create or update the schema without building telemetry migrations.

### Step 2: Load growth loops and generate telemetry migration (unless `--push-only`)

When not using `--push-only`, the command:

- Loads growth loop JSON files from `skene-context/growth-loops/`
- Filters for loops with Supabase telemetry (`type: "supabase"`)
- Generates SQL trigger functions that INSERT into `skene_growth.event_log`
- Writes `supabase/migrations/<timestamp>_skene_telemetry.sql`

Each trigger uses idempotent DDL (DROP TRIGGER IF EXISTS before CREATE).

With `--local --ingest-url https://...`, the custom webhook URL and proxy secret are baked into the telemetry migration.

### Step 3: Push to upstream (optional)

When an upstream URL is configured (via `--upstream` or `.skene.config`), the command packages the growth loops and telemetry SQL and sends them to the upstream API at `POST https://www.skene.ai/api/v1/deploys`.

## Workflow summary

| Command | Schema | Telemetry | Upstream |
|---------|--------|-----------|----------|
| `skene push` | ✓ check/update | ✓ generate | ✓ if configured |
| `skene push --local` | ✓ check/update | ✓ generate | ✗ |
| `skene push --push-only` | ✓ check/update | ✗ | ✓ if configured |
| `skene push --init` | ✓ create/update | ✗ | ✗ |

## Telemetry format

Growth loops include telemetry definitions that describe what events to capture. The Supabase telemetry type looks like:

```json
{
  "type": "supabase",
  "table": "documents",
  "operation": "INSERT",
  "properties": ["id", "name", "created_at"],
  "action_name": "document_insert"
}
```

The `push` command converts these into SQL trigger functions automatically.

## Upstream authentication

To push to upstream, authenticate first:

```bash
uvx skene login --upstream https://skene.ai/workspace/my-app
```

The upstream URL can also be resolved from:

1. `upstream` field in `.skene.config` (saved by `skene login`)
2. `--upstream` CLI flag (highest priority)

## Next steps

- [Login](login.md) -- Authenticate with Skene Cloud upstream
- [Build](build.md) -- Generate growth loop definitions with telemetry
- [Status](status.md) -- Verify growth loop implementation
- [CLI Reference](../reference/cli.md) -- Full reference for all commands and flags
