# CLI Reference

Always add `--json` when another agent needs to parse output.

## Projects

```sh
slate projects list --json
slate projects get <id> --json
slate projects create --data '{"name":"...","brief":"..."}' --yes --json
slate projects update <id> --data '{"name":"..."}' --yes --json
slate projects delete <id> --yes
slate projects search <query> --json
```

## Content Production (AI capabilities)

These run Slate's AI operations server-side (same as the webapp/agent). Slow synchronous calls; the CLI uses no client timeout by default.

```sh
# Ideation
slate ideate --yes --json

# Thumbnails — entity-aware (preferred path)
slate thumbnails entities --json                            # entity ids (creators_face + custom) to reference as att-e-<id>
slate thumbnails brainstorm --project-id <id> --json        # concepts with att-e-* entity tokens embedded
slate thumbnails brainstorm --project-id <id> --json | slate thumbnails add --project-id <id> --file - --yes --json

# Thumbnails — lower-level, entity-blind (include `entities` in --data to composite a face)
slate thumbnails sketch <packaging-id> --thumbnail-id <id> --concept "..." --yes --json
slate thumbnails render <packaging-id> --thumbnail-id <id> --instructions "..." --yes --json

# Script voice + prompt blocks
slate scripts voice-context --json
slate scripts prompt-block --project-id <id> --block-id <id> --yes --json

# Audits (read-only quality gates)
slate audit voice --project-id <id> --json
slate audit packaging --project-id <id> --json
slate audit broll --project-id <id> --json

# Generic
slate capability call <name> --data '<json>' --yes --json
```

`thumbnails add` is the canonical entity-aware path: it runs the same `addThumbnails` executor the webapp/routine use — parsing each concept's `att-e-*`/`att-y-*` tokens, resolving `thumbnail_entities` (with creator-face self-heal), and rendering photorealistic thumbnails with the real creator face. It accepts `thumbnails brainstorm` output directly. The raw `sketch`/`render` commands forward only what you pass, so they are entity-blind unless you include `entities` in `--data`. `thumbnails entities` lists `{ id, entityType, label, imageUrls }` — reference an entity in a description as `[label](attachment:att-e-<id>)`.

## YouTube Research

```sh
slate youtube search "productivity systems" --max-results 20 --json
slate youtube outliers "productivity systems" --top 5 --json
slate videos search "productivity systems" --json
slate videos search "productivity systems" --platform youtube,tiktok --max-results 10 --json
slate videos inspect "https://www.youtube.com/watch?v=<video-id>" --json
slate videos ask "https://www.youtube.com/watch?v=<video-id>" "How does the opening hook work?" --json
slate youtube video get <video-id> --json
slate youtube video transcript <video-id> --json
slate youtube channel get <channel-id> --json
slate youtube channel videos <channel-id> --max-results 20 --json
```

`videos search` uses Slate's agent-facing unified discovery path. It searches `youtube`, `youtube_shorts`, `tiktok`, and `instagram` by default and returns one normalized list with `platform` on every row; YouTube rows retain Breakout Lift fields. `--max-results` applies per platform. `youtube outliers` uses Slate's channel-relative `lift-v1` computation and returns the ranked score, tier, confidence, baseline views, and comparison count. It searches a wider pool than the requested `--top` count so the result is a ranking rather than a re-labeling of the first few search hits. `videos inspect` combines the existing YouTube details, transcript, visual-breakdown, and reconstructed-timeline paths. `videos ask` uses the same grounded video-question operation as Slate's agent.

## Scripts And Annotations

Legacy script rows:

```sh
slate scripts list --project <project-id> --json
slate scripts get <id> --json
slate scripts create --data '{"projectId":"...","content":"..."}' --yes --json
slate scripts update <id> --data '{"content":"..."}' --yes --json
slate scripts delete <id> --yes
```

Canonical script block state:

```sh
slate scripts blocks list --project-id <project-id> --json
slate scripts annotations candidates --project-id <project-id> --linked-folder-id <folder-id> --limit 5 --json
slate scripts annotations apply --file replacements.json --yes --json
```

When run inside a linked folder, script block commands infer project and linked folder context from `.slate/link.json`. `scripts annotations candidates` is the low-level linked-folder scoped candidate surface and builds one query per placeholder annotation from its label/description; for local edit workflows, prefer `slate edit reconcile b-roll`.

## Clips

```sh
slate clips list --project-id <project-id> --limit 100 --json
slate clips list --linked-folder-id <folder-id> --scope linked --processing-phase completed --type b_roll --json
slate clips search "query" --project-id <project-id> --linked-folder-id <folder-id> --type b_roll --limit 10 --json
slate clips search --data '{"query":"query","projectId":"...","matchCount":10}' --json
slate clips download <clip-id> [clip-id...] --out ./selected-clips --yes --json
slate clips get <id> --json
slate clips set-type <id> a_roll --yes --json
slate clips set-type <id> b_roll --yes --json
slate clips process <id> --yes --json
slate clips cancel <id> --yes --json
slate clips delete <id> --yes
```

For recorded-footage reconciliation in a local edit, prefer `edit reconcile b-roll` plus `clips list --scope linked`. Use `clips set-type` when analysis clearly misclassified A-roll vs B-roll. Use broad `clips search` only when intentionally sourcing outside the linked folder. Use `clips download` when the user has manually chosen specific library clips to materialize; it is not a replacement for `sync b-roll`, which follows the project's external-media plan.

## Media

```sh
slate link
slate link --project-id <project-id> --yes --json
slate status --local --json
slate sync media --proxy --yes --wait --json
slate sync media --proxy --prioritize-a-roll --yes --wait --json
slate sync b-roll --mode reference --yes --json
slate sync b-roll --mode download --yes --json
slate sync script --yes --wait --json
slate media linked-folders list --project <project-id> --json
slate media linked-folders sync <id> --yes --json
slate media generate music --prompt "warm lo-fi piano bed" --duration 30 --yes
slate media generate sfx --prompt "distant city traffic ambience" --duration 6 --yes
slate media generate footage --prompt "aerial establishing shot of a foggy coastline at dawn" --duration 8 --yes
slate media snap --path "Music/track.mp3" --json
slate media snap --path "SFX/whoosh.wav" --min-onset-gap-ms 50 --json
```

`sync media` preflights media processing before mutating clips and preprocesses several local files at once by default. Add `--proxy` for local Slate edits so Slate probes/renders use lightweight local cache media while originals stay canonical. Add `--prioritize-a-roll` when building a local edit so files whose relative path or name looks like A-roll are synced first; this lets A-roll assembly begin while remaining B-roll is still being analyzed. If it fails, read `message` and `safeNextAction`, report those in user language, and stop. Large local recordings may report `geminiSkipped.reason: "large_local_video"`; that is expected and means the worker will use local preprocessed audio/frames instead of raw Gemini video upload.

`media snap` extracts audio snapping points from any audio or video file so transitions can land on the beat and sound effects start exactly where the sound does. It prints `{ backend, duration, snapPoints, onsets, tempo }`: `snapPoints` is the merged, time-sorted list of `{ time, kind: "onset" | "beat", strength }` — the field to read when you want the nearest snap target to a desired time; `onsets` is every detected attack with a strength; `tempo` is `{ bpm, confidence, beats }` (`bpm` is `null` for speech or ambient audio with no clear pulse, which is correct). Times are seconds, `strength` is 0–1. Tuning flags: `--min-onset-gap-ms` (default 30), `--min-bpm`/`--max-bpm` (default 60/200). Works out of the box with no extra install — Slate ships its own onset + beat detector built on ffmpeg.

Optional upgrade: if the [`aubio`](https://aubio.org) CLI is installed (`brew install aubio`), `media snap` uses it automatically. aubio is the established standard for onset and beat tracking; Slate's built-in detector is good for onsets and steady tempo, but its beat grid is a single global fixed-tempo estimate with no drift tracking, so aubio tracks real music — tempo changes, live playing — more accurately. Reach for it when you're snapping cuts to the musical pulse and the built-in grid drifts on the track. Force a backend with `--backend native|aubio|auto` (default `auto` prefers aubio when present); the chosen backend is reported in the `backend` field and logged to stderr.

`media generate` fills missing media on demand: `music` and `sfx` use ElevenLabs, `footage` uses Seedance 2.0 (cinematic clips, good for establishing shots). Footage is generated silent (visual b-roll) — layer in audio with the `music`/`sfx` commands. Run it from a linked project folder. The generated file is downloaded into `<local root>/Generated/`, then registered as a searchable clip with the prompt as its title/description; audio registers as an audio clip and footage is analyzed like any other b-roll. Because the file lands in the linked folder, it backs up to Dropbox/Drive on its own — Slate does not host the media. `--duration` is in seconds and clamped per model (music 3–600s, sfx 0.5–22s, footage 4–15s); omit it for the model default. `footage` also accepts `--standard` (higher-quality, slower tier) and `--aspect-ratio` (default `16:9`). The command waits for generation to finish (footage can take minutes) and prints `{ clipId, filePath, kind }`; pass `--no-wait` to submit and get `{ requestId }` without blocking.

## Local Edit Engine

```sh
slate edit init --json
slate edit make --yes --incremental --json
slate edit hydrate --json
slate edit status --json
slate edit recommend a-roll --json
slate edit assemble a-roll --paragraph-id <paragraph-id> --clip-id <clip-id> --incremental --json
slate edit reconcile b-roll --limit 5 --json
slate edit apply b-roll --file replacements.json --mode reference --yes --json
slate edit apply b-roll --file replacements.json --mode download --yes --json
slate edit catalog --json
slate edit context --format md
slate edit validate --json
slate edit plan --json
slate edit ops --at 12.345s --json
slate edit export --out .slate/editor/export/main.fcpxml --target fcpxml --json
slate edit probe --at 12.345s --out .slate/editor/export/probe.jpg --json
slate edit render --out .slate/editor/export/draft.mp4 --json
slate edit sync fcp --dry-run --json
slate edit sync premiere --dry-run --json
slate edit sync fcp --handoff --json
slate edit sync premiere --handoff --json
slate edit sync fcp --discard-editor-changes --yes --json
slate edit sync premiere --discard-editor-changes --yes --json
```

In standalone editor workspaces, authored edit decisions live in `.slate/editor/main.vml` and `.slate/editor/**/*.vmlt`. `main.vml.json`, compiled plans, probe frames, renders, and native editor artifacts are generated or host-provided facts, not the authored edit language.

The older `.slate/sequences/*.json` engine remains for the existing Go hydrate/render/native-sync path. Treat it as transitional when VML files exist.

`edit make` is the one-command local orchestration surface. Run it from a linked media folder after recording. It initializes the local edit workspace, syncs/analyzes media with likely A-roll first, calls Slate's A-roll assembly engine, materializes B-roll, and hydrates the local timeline. Use `--incremental` to fetch A-roll recommendations on the client, assemble one paragraph at a time, and hydrate after each paragraph so the local editor can hot reload progressively. Use `--b-roll-mode reference` when you only want to inspect the external-media plan.

`edit recommend a-roll` returns each A-roll clip's recommended script-paragraph matches and any paragraphs already assembled from it. `edit assemble a-roll` is the Slate-owned paragraph assembly surface for local agents. Run either from a linked folder, or pass `--project-id` and `--linked-folder-id`; assembly calls the same A-roll assembler used by Slate's project agent. Use `--comment "..."` when retrying a paragraph with a suspicion about the selected take, and `--concurrency <1-16>` only for callers that submit more than one assignment through the API.

`edit reconcile b-roll` returns per-placeholder candidate sets scoped to the linked media folder. It does not choose clips automatically; the calling agent must inspect the candidate sets and prepare an explicit replacement payload. `edit apply b-roll` patches those replacements into the Slate script, runs the B-roll materialization phase (`reference` or `download`), then hydrates the local edit workspace by default.

Editor handoff workflow:

```sh
# agent edits
slate edit status --json
slate edit validate --json

# user takes over in Final Cut or Premiere
slate edit sync fcp --handoff --json
# or: slate edit sync premiere --handoff --json
# open the returned editorProject in the requested desktop editor

# user finishes editor edits; agent resumes before touching Slate JSON
slate edit sync fcp --json
# or: slate edit sync premiere --json
```

If status reports `owner: "editor"`, only `status`, `status --editor`, `catalog`, `sync <same-editor>`, and `unlock` are safe. Resume or discard the handoff before any Slate edit/render command.
