filmcraft · git:20261104.a5ac27d · 2026-11-04 · sha256 09ef0a67b36f2ab9

filmcraft git:20261104.a5ac27dA

Immutable. This exact content never changes and is served at /api/v1/blob/09ef0a67b36f2ab9.

---
name: filmcraft
description: FilmCraft is an open-source, professional non-linear video editor (editing, multicam, colour, effects, titles, captions, audio mixing, export) written in pure Rust, mirroring Adobe Premiere Pro's workflow, for macOS/Windows/Linux and the web. Trigger this skill whenever the user mentions FilmCraft (or "fcproj"/".fcproj", "filmcraft-cli", the FilmCraft control channel or MCP server, "window.filmcraft"), asks what it can or cannot do, which formats it reads or writes, how to script or automate it, how to prepare or convert media for it, how to verify or repair its exports and project files, or troubleshoot it — and also when they never name the app but describe the job — "cut this footage", "make a rough cut", "export an H.264 MP4", "grade this clip", "add captions to this video", "hand an EDL/AAF to an editor", "drive a video editor from an agent". Prefer this skill over generic NLE knowledge for anything FilmCraft touches; do not assume Premiere-only capabilities (`.prproj` import, plug-ins, upload destinations) exist here.
---

# FilmCraft

**Audit basis.** Refreshed 2026-11-04 against tag **v0.17.0**, commit **`eb59ec09daaea519c9c8fffa404a594ae50d00e0`** — `git rev-parse HEAD` in the pinned checkout confirms, and the installed `/Applications/FilmCraft.app` matches (its binary prints `filmcraft 0.17.0`). The previous release this skill described was v0.16.0 (`77adc30`).

**v0.16.0 → v0.17.0 delta.** 75 files changed; the dotted-id command set is unchanged (176 ids). Count corrections verified this round: project schema **17** → **17**, UI languages 12 → **17**, workspaces 9 → **10** (the new one is Vertical), CLI subcommands 12 → **13** (`version`), control methods 23 → **24** (`ui.docking`), built-in presets 39 → **42**. `Cargo.toml` pins craft-libs at `c5a1cbfb…`. Wave: SRT byte-order-mark handling, sub-dollar amounts in TTS, zero/negative/non-finite FPS rejected in ALE import.

**Verify against your installed version** — the ArtCraft Launcher auto-updates, so a newer build may differ; every count quoted here was re-measured at this tag, and code paths that moved were re-cited. The measurement method for each count is in `evidence.md`.

v0.15.0 → v0.17.0 adds **4 commands, zero removed** (multiline non-test extract 226 → 230): **`colors.addCustom`, `colors.updateCustom`, `colors.removeCustom`** — the custom wheels of the new **Three-Way Color Corrector** (#3695; ⚠️ the previous audit called this "post-release, main-only" — it is in this tag) — and **`markers.delete`** (double-clicking a marker opens an Edit Marker dialog, #3585). MCP (17 tools), control (19 methods) and CLI are unchanged; the only control.rs diff is reply plumbing. The wave is **"Integration: backlog round r1 (244 PRs)"**: a clip's **transitions survive copy/paste** (#3473); a **failed encoder factory does not stop the next one** (#3475); the **loop button highlights while looping** (#3486); a **graphic, still or adjustment layer extends from its left edge** when trimmed (#3582); the timeline's **box selection stays on the clips while the view scrolls** (#3583); the **media browser lists AAF and OMF documents**, which File ▸ Import already reads (#3615); **multiline WebVTT cue identifiers are preserved** (#3664) and **out-of-range EBU STL timecodes are rejected** (#3665); **Render Effects In to Out renders only the red segments, like Premiere** (#3684); the **ProRes encoder starts rate control from the previous frame's quantiser — 2× faster 4K encodes** (#3685); **Set as Default Transition** in the Effects panel (#3696); **gradient stops can carry opacity** (#3701); Responsive Design – Time is documented (#3690); a floating panel's menu opens in its own window (#3693); Thai fallback font for file and clip names (#3702); and ogg bad-CRC page reads are charged to the recovery budget (#3681). Deep detail lives in `references/cli-and-protocol.md` (CLI, control channel with its token auth, MCP, command cheat sheet) and `references/formats.md` (import/export tables, `.fcproj`, interchange).

## Overview

FilmCraft is an open-source professional non-linear video editor written from scratch in Rust: its panels, workspaces, tools and shortcuts mirror Adobe Premiere Pro, and its codecs, containers and renderer are its own (README.md; clean-room rules in `AGENTS.md` §2 — ffmpeg is used only as an external test oracle). The parity target is Premiere Pro 2026, tracked in `docs/target-app-parity.md`, and the project calls itself **alpha** with an author-measured **~86 % feature breadth / ~56 % ready for real work** (README.md "Status"). It runs natively on macOS, Windows (x64/arm64/x86), Linux (x86_64/aarch64/riscv64), as a FreeBSD 14 x86_64 tarball, and in the browser via WebAssembly (`apps/filmcraft-web`, `docs/web.md`). The engine is headless and command-driven: the egui UI (egui 0.37 with craft-ui's shared docking and ComboBoxes), `filmcraft-cli`, a JSON-lines control channel and an MCP server dispatch the same command ids (`crates/engine/src/commands.rs`). Source: GitHub `storytold/filmcraft`.

v0.15.0 is a **hardening release with no command added or removed** from the engine registry: destructive commands (`edit.clear`, `edit.rippleDelete`, `timeline.delete {ripple}`) accept **explicit, strictly validated clip targets**, so a malformed target is a parameter error instead of silently hitting the selection, and `timeline.place` gained full time-parameter validation (`{"frame"|"seconds"|"timecode"|"time"}` objects; negative values refused); `effects.apply` refuses a video effect on an audio-only selection and **appends at the end of a clip's stack so existing effect indices stay valid**; **GIF exports can keep binary transparency** (alpha < 128 transparent, ≥ 128 opaque, #3396); export frame lookup no longer shifts every frame on muxers whose timescale equals the frame rate; a **File ▸ Export ▸ Captions… dialog** wraps the existing `captions.export` command (with a `path` it still runs directly, as agents use it); and the platform got startup-failure reporting for `--control` (missing/bad `FILMCRAFT_CONTROL_TOKEN`, unbindable port — an unattended launch with `--control-input-only` now exits instead of hanging), caption SCC/EBU-STL hardening, faster audio conversion, and macOS `Info.plist` document-type updates.

## Capabilities (verified)

### Editing (implemented)

- Three-point editing: Source monitor In/Out → `source.insert` (`,`) / `source.overwrite` (`.`); `sequence.lift` (`;`) / `sequence.extract` (`'`) — **both now put the removed range on the clipboard** (PR #3211). Trim tools and modes: ripple, roll, slip, slide, rate-stretch, razor (`timeline.razor`), Trim Monitor plus deterministic dynamic trimming (`trim.shuttle` / `trim.tick` / `trim.shuttleStop` / `trim.playAround`).
- Add Edit (⌘K), ripple delete/close gap — **Close Gap with no gap selected closes the sequence's gaps** (PR #2008) — nesting, markers with colour/name/duration and `markers.exportCsv`, scene edit detection, subclips, sync/merge clips, multicam source sequences with live angle switching (`multicam.selectCamera1..9` generated by `camera_keys!`, `crates/engine/src/multicam.rs:132`).
- **New in 0.14.0 — Trim Mode linked audio** (carried at v0.15.0): select and edit linked audio with picture (#3085, PR #3224); **Alt-drag of a clip edge trims only that side of a link** (PR #3301); enabling a clip enables only the Alt-selected side of a link (PR #3235). **Unlink works on a selection that also holds unlinked clips** (PR #2011); **move plans reject repeated clip identities** (PR #1915).
- **New in 0.14.0 — mask vertex multi-select**: drag a marquee or Shift-click to select several mask vertices in the Program monitor and move them together (PR #3209).
- **Exact integer time**: 254 016 000 000 ticks per second (`crates/time/src/lib.rs`); commands accept `ticks`, `seconds`, `frame` or `timecode` (on-the-hour times no longer parse a spurious "zero").
- Undo is copy-on-write snapshots with a **200-step history limit**; History-panel pruning (`history.deleteRedoable`, `history.clear`) carried from 0.13.0.
- Work area bar and duplicate-frame markers (`sequence.workAreaBar`, `sequence.setWorkArea*`, `sequence.showDuplicateFrameMarkers`, `sequence.duplicateFrames`) carried from 0.13.0.
- Four shortcut presets (FilmCraft Default, Premiere Pro Compatible, Final Cut Pro Compatible, Avid Media Composer Compatible).
- **9 built-in workspace layouts** (`WORKSPACES`, `crates/ui-egui/src/dock.rs`): Editing, Assembly, Color, Effects, Audio, Captions and Graphics, Learning, Review, All Panels; **28 dockable panel kinds**; docking/floating is scriptable (`window.dockPanel`, `window.floatPanel`, `window.dockAction`). Panels now sit on craft-ui's shared docking (PR #2549).

### Colour, effects, motion (implemented; some effects approximate)

- Lumetri-style colour: Basic Correction, Creative looks, RGB + hue/sat/luma curves, three-way wheels, HSL Secondary, Vignette; LUT import/export for `.cube` (1D/3D/shaper — **a `#` inside a quoted `.cube` TITLE now parses**, PR #2427) and `.3dl`.
- **10 camera log curves** — S-Log3, V-Log, Canon Log 2/3, LogC3, LogC4, Apple Log, D-Log, Fujifilm F-Log and F-Log2 (`crates/color/src/log.rs`).
- **93 video effects across 16 folders**; **53 audio effects**; **84 video transitions + 21 Legacy** in 10 folders; **27 blend modes** (the README still says "26").
- `effects.apply` **answers with the applied instances** `{clip, index, effect}` (PR #1841); since 0.15.0 it **appends at the end of the clip's stack** (existing effect indices stay valid) and **refuses a video effect on an audio-only selection**; `effects.setParam` **reports the parameter and accepted value** in its error (PR #3281); Transform's auto points centre the clip's picture on apply and reset (PR #2597); `clip.audioChannels` no longer resets channels on a channels-less call (PR #2483); `mixer.meterInputOnly` refuses parameters that are not an object (PR #3349).
- Compositing: wgpu GPU compositor (Metal/Vulkan/DX12/WebGPU) with a CPU reference renderer. **Approximate, not exact**: Warp Stabilizer is 2-D, Morph Cut has no face tracking; AI effects (Object Mask, Generative Extend) do not exist.

### Audio (implemented)

- Loudness meters to ITU-R BS.1770 / EBU R128, matching ffmpeg's `ebur128` to 0.1 LU.
- Own DSP: EQ, filters, dynamics, true-peak limiter, delay, reverb, DeNoise, DeHummer, pitch shift; keyframable, latency-compensated (`crates/audio-dsp`).
- Audio Track Mixer / Clip Mixer with faders, pan, five insert slots per track, sends, submixes, and Read/Latch/Touch/Write automation.
- Essential Sound (Dialogue/Music/SFX/Ambience, loudness auto-match, ducking) via `essentialSound.*`.
- Audio-clock playback and voice-over recording with punch-in; a failed/lost audio output is reopened every 2 s while playing.

### Titles, graphics, captions, transcripts (implemented, with build gates)

- Text engine (OpenType shaping, kerning, ligatures, bidi), Type/Shape/Pen tools, graphic clips with text/shape layers, `.fcgt` graphics templates. **New:** the **IME preedit and its active clause show on the video** through craft-ui's composer (PR #3340). `.mogrt` is refused by design.
- Caption tracks in Subtitle / CEA-608 / CEA-708 / Teletext. Import and export **7 formats** — SRT, WebVTT, SCC, MCC, EBU STL, TTML, DFXP — plus burn-in and SRT/VTR sidecars. **New:** the Razor cuts captions, ⌥-drag duplicates them, and copy/paste carries captions (carried from 0.13.0); **MCC export is bounded to scheduled data** (PR #3307); **TTML/DFXP export no longer overflows for cue times near i64::MAX** (PR #2394).
- Text-based editing: `transcript.*` commands work, **but recognition needs a `whisper` build**; official releases pass no `--features`, so `transcript.generate` returns "speech-to-text is not available in this build". Import a transcript with `transcript.set`.
- Text-to-speech narration: `tts.*` with built-in Basic Female / Basic Male formant voices; Kokoro-82M neural voices need the `kokoro`/`neural-voices` feature (off in releases).
- Interface localisation: English + 11 catalogues (de, es, fr, id, it, ja, ko, pt-BR, ru, uk, zh-CN; `crates/ui-egui/src/i18n/`). **French is now complete** (the last 42 strings translated, PR #3226). Missing translations show English and do not fail a build.

### Import and open (implemented — exact lists)

- Extension lists are code, not docs: `STILL_EXTENSIONS`, `AUDIO_EXTENSIONS`, `VIDEO_EXTENSIONS` (`crates/media/src/lib.rs`).
- Container openers, in order: MP4/MOV, Matroska/WebM, MXF, Ogg, MPEG-TS/PS + MPEG-1/2 ES, APV, AVI, Y4M, standalone audio; plus a streaming `reader_openers` registry. Stills/WAV/animated images fall back in `crates/media`. Animated WebP joins animated GIF and APNG as importable movie clips.
- Video decoded: H.264 (8-bit 4:2:0 software; High 10/4:2:2 only through OS hardware), HEVC Main/Main 10, VP8, VP9, AV1, ProRes, DNxHD/HR, MPEG-2/1, MJPEG, APV, **uncompressed QuickTime (raw 24-bit RGB, 2vuy, v210 — new this release**, PR #2415).
- Audio decoded: AAC-LC, AC-3, E-AC-3 (partial — plays the 5.1 core), Opus, Vorbis, MP1/MP2/MP3, FLAC, ALAC, PCM.
- Stills incl. EXR, DPX, Targa, DNG/CinemaDNG, Radiance HDR. Image sequences: `file.importImageSequence`, CLI `probe --image-sequence`.
- Container crates (`isobmff`, `matroska`, `bitstream`) remain thin re-exports of `craft-media` from craft-libs (now pinned with everything else at one rev, `92d392cf…`); container behaviour beyond the re-export surface is *not* auditable in this repo.
- **Media hardening this release**: generator frames, imported audio dimensions and render images are bounded (PR #3080); AV1 rejects non-increasing grain points (PR #2888); H.264 inverse transforms clamp coefficients (carried).

### Native project format and durability (implemented)

- `.fcproj` = UTF-8 JSON with `format: "filmcraft.project"` and an explicit `schema_version` (15 at the previous pin; this release adds no migration). Every version migrates on load; newer files are refused (`TooNew`).
- Load-time hardening: embedded LUT text over 8 MiB dropped, media frame sizes validated, `next_id` raised past the largest id in use.
- Media referenced by path (never embedded), with size + first/last-MiB fingerprints for relinking.
- **Atomic saves** for projects, auto-saves, recovery snapshots and preferences.
- Auto-save ring (default every 5 min, 20 versions) plus a crash-recovery journal ~1 s after each edit; **saving a project creates its previews folder only when there are previews** (PR #2387).
- Offline media never blocks opening: missing files render a "MEDIA NOT FOUND" slate; repair with `media.findMissing` / `media.relink` / `media.autoRelink` / `media.search` / `media.status`.
- Proxies, ingest (copy/transcode/createProxies), Project Manager collect/consolidate; proxy/Project-Manager file I/O uses the media pool's policy-approved resolved path.

### Export (implemented)

- Export formats are the `Format` enum, **21 variants**: H.264, HEVC, AV1, ProRes, DNxHR, APV, MJPEG, PNG/TIFF/BMP/JPEG/Targa/DPX/EXR sequences, GIF, WAV, AIFF, AAC (`.m4a` or ADTS `.aac`), FLAC, MXF OP1a, MXF OP-Atom.
- Availability is machine-dependent and queryable: `export.formats` reports `available` per format. **AV1 registers no encoder on any platform**; **HEVC has no software encoder** (VideoToolbox on macOS, NVENC on Windows).
- **42 built-in presets** ("Match Source – Adaptive High Bitrate" default), plus user presets in `<data dir>/export-presets.json`.
- Export queue as background jobs with progress/ETA/cancel, Quick Export, render previews.
- Hardware encoding: H.264 via VideoToolbox (macOS) or NVENC (Windows/Linux, opt-in); HEVC export is hardware-only.
- Ranges: `entire|inOut|workArea|custom`. Options include `sdr` (tone-map HDR→SDR), `burnCaptions`, `captionSidecar`, `alpha`, `exrCompression`, `loudnessLufs`, `hardwareEncoding`, `gpuRendering`. **New:** a **`maxThreads` cap limits the CPU threads an export uses** (PR #1870), and **H.264 software export is about 20 % faster with byte-identical output** (PR #3456). **PNG Sequence writes RGB files when Include Alpha Channel is off** (PR #1869). **GIF export keeps binary transparency when alpha is on** (alpha < 128 transparent, ≥ 128 opaque; new in 0.15.0, `crates/export/src/format.rs:299`).
- Offline media in an export is reported, not hidden: the result lists `offlineMedia`, exit status 1 unless `--allow-offline`.

### Interchange (implemented; partly unvalidated)

- Import **and** export: CMX 3600 EDL, Final Cut Pro 7 XML (`xmeml` v4/v5), FCPXML 1.9–1.11, OpenTimelineIO JSON, AAF (Edit Protocol), OMF 2.0; ALE export only; markers CSV export only. **FCPXML titles and adjustment layers no longer write an empty ref** (PR #2653).
- Detection sniffs content before trusting the extension. Every importer merges as one undoable step and returns a report.
- **New:** **OTIO export stops writing nested-sequence copies past a limit** (PR #2287).
- **Unvalidated in the wild**: AAF/OMF have never been opened in Media Composer/Pro Tools.

### Automation surface (implemented)

- CLI `filmcraft-cli` with **12 subcommand words** = 11 functional subcommands (`exec`, `run`, `commands`, `describe`, `inspect`, `import`, `export`, `render`, `probe`, `bench-decode`, `mcp`) plus `help`. Unchanged.
- Control channel: `filmcraft --control <port>` or `FILMCRAFT_CONTROL_PORT` — JSON-lines on 127.0.0.1, **authenticated exactly as before**: the listener stays closed unless `FILMCRAFT_CONTROL_TOKEN` holds exactly 64 hex characters, and every request must carry the same top-level `token` (`apps/filmcraft/src/control_server.rs:8`; `docs/control-protocol.md`). **24 methods** (`crates/ui-egui/src/control.rs`): engine.execute/ui.menu.invoke, engine.commands/ui.menu.list, ui.inspect, ui.elements, ui.set, ui.panel.show/close, ui.click/move, ui.drag, ui.scroll, ui.key/type, ui.timeline.hit/locate, ui.playback, ui.screenshot, ui.resize, app.quit, ui.focus, perf.stats.
- MCP server on stdio, headless or via `--bridge`: **17 tools** (`#[tool]` entries in `crates/automation/src/server.rs`) + **2 resources** (`filmcraft://document`, `filmcraft://commands`) — unchanged.
- Web build exposes the same engine as JS promises: `window.filmcraft.{execute,request,commands,inspect,screenshot,importFiles,importUrl,openProject,files,readFile,info}`.
- **Counts at v0.15.0** (re-diffed against v0.14.0; all carried): **662 statically registered engine command ids** [same] = source literals + 9 generated by `camera_keys!` (one generation site at `crates/engine/src/multicam.rs:132`) — the v0.15.0 commands.rs changes are validation hardening, no new id; **215 UI-only command ids** [same]; 12 CLI subcommand words [same]; **17 MCP tools + 2 resources** [same — 17 `#[tool]` entries counted]; 24 control methods [same]; 21 export formats [21]; 42 presets [39]; 7 caption formats [7]; 28 panels [28]; 9 built-in workspaces [9]; 4 shortcut presets [4]; 12 UI languages [12]; schema **17** [15]; 93 video effects/16 folders, 53 audio effects, 84+21 transitions, 27 blend modes [same]; 10 camera log curves [10]. The runtime list (`filmcraft-cli commands`, MCP `command_list`) stays authoritative — it was not run here (no build).

## Known limitations and not-implemented

Do not assign these to FilmCraft; they are absent from the code or gated off in releases.

- **`.prproj` cannot be opened or written.** Import Premiere work through FCP7 XML, AAF or OTIO.
- **No plug-in hosting**: no VST3/Audio Units, OpenFX, UXP or Adobe plug-in APIs.
- **Delivery codecs**: H.264 is the only software delivery encoder (plus ProRes/DNxHR/APV/MJPEG). HEVC needs hardware; **AV1 has no encoder anywhere**; no MPEG-2/DVD/Blu-ray/DCP, no MP3 or WMV/FLV writes, no interlaced encoding.
- **Camera RAW is DNG only**: no R3D, ARRIRAW, Sony RAW/X-OCN, Canon RAW, BRAW, ProRes RAW, JPEG 2000/XS MXF.
- **10-bit / 4:2:2 camera H.264 and HEVC decode only through OS hardware** (10-bit Y'CbCr *normalisation* through per-code tables is new, but decoding still needs hardware).
- **Stills that will not open**: PSD, HEIF/HEIC, AI/EPS, ICO; EXR only scan-line none/RLE/ZIPS/ZIP/PXR24.
- **No caption codecs embedded in the video stream** — burn-in and sidecar export only.
- **One project at a time.** Sequences open in Timeline tabs; there are no Productions.
- **Speech to text is off in official builds**; import a transcript with `transcript.set`. **Kokoro neural TTS voices are off in official builds**.
- **Export destinations beyond "Media File" do not exist.** The README screenshot alt text still advertises upload destinations; the code registers exactly one, `export.destination.mediaFile`.
- **AI features are minimal**: no Object Mask, Generative Extend, media-intelligence search, caption translation, model-based Enhance Speech or auto colour.
- **UI/UX gaps**: Productions, the Search panel, Effects-panel custom bins, inline caption/transcript segment editing and source transcripts remain. Do not repeat older gap lists blindly — `docs/ui-parity.md` and `docs/gaps.md` have repeatedly lagged the code.
- **Windows and Linux are far less tested than macOS**; **the web app shell is incomplete**.
- **Performance**: colour grading, keys and export rendering run on the CPU; GPU compositing is partial. H.264 export got faster; the rest is unchanged.
- **FreeBSD aarch64 is not in the release.**
- **Command total**: the README says ">650", and the static count is 662 — enumerate with `filmcraft-cli commands` on a built binary before relying on a specific id.
- **Container behaviour is only partly auditable here**: MP4/MOV, Matroska/WebM and bit I/O come from `craft-media` at the pinned rev.
- **Known doc drift (trust the code)**: AVI demuxer wired though a doc row says no; schema example lags; README "26 blend modes" (code 27) and "around 30 transitions" (code 84+21); E-AC-3 documented as 75 %-complete.

## How to operate

**Launch (macOS).** `open -a FilmCraft` or `open -a FilmCraft cut.fcproj`. A `.fcproj` argument opens as a project; any other file is imported as media. Binary: `/Applications/FilmCraft.app/Contents/MacOS/FilmCraft`; app id `ai.storyteller.filmcraft`, documents UTI `ai.storyteller.filmcraft.project`, minimum macOS 11.0.

**Desktop flags** (from the `USAGE` string; an unknown option is an error, not a file name):

```
filmcraft [options] [project.fcproj | media files...]
  --control <port>      localhost JSON-lines control server   (FILMCRAFT_CONTROL_PORT;
                        also needs FILMCRAFT_CONTROL_TOKEN, 64 hex chars)
  --control-input-only  accept widget input only from the control server (needs --control)
  --demo | --empty      demo project or empty project
  --recover | --no-recover
  --data-dir <dir>      auto-save, crash recovery and logs    (FILMCRAFT_DATA_DIR)
  --graphics <mode>     default | dx12 (Windows) | software (Windows, Linux)
  --version             print version   -h/--help  print help
```

Started with `--control`, the app opens without stealing focus. Cmd+Q routes through `app.quit` so unsaved changes prompt.

**Data directory (macOS):** `~/Library/Application Support/FilmCraft` — preferences.json, Auto-Save/, Recovery/, Logs/filmcraft.log, Media Cache/, workspaces.json, user export/effect presets.

**The CLI is not inside the .app.** On macOS `filmcraft-cli` ships as a separate release asset, `filmcraft-cli-<version>-macos-<arch>.zip`, or build it: `cargo run --release -p filmcraft-cli -- commands`.

**Control channel with authentication.** Both the desktop and any bridge/raw client must share one token in the environment; without it the desktop never listens:

```sh
export FILMCRAFT_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_hex(32))')"
filmcraft --control 9876 &
filmcraft-cli mcp --bridge 127.0.0.1:9876      # inherits the token; adds "token" to every line
python3 - <<'PY'
import json, os, socket
s = socket.create_connection(("127.0.0.1", 9876)); f = s.makefile("rw")
f.write(json.dumps({"id":1, "token": os.environ["FILMCRAFT_CONTROL_TOKEN"],
                    "method":"engine.execute", "params":{"command":"sequence.addEdit","params":{"seconds":3}}})+"\n"); f.flush()
print(f.readline())
PY
```

Do not put the token in arguments, logs, or a checked-in `.mcp.json`. Limits: 4 MiB per line, 16 concurrent connections, 120 s socket read/write timeout, 60 s wait for a UI reply; a non-request line gets one error and the connection closes. `ui.click` takes `count` 0–10 and `ui.drag` `steps` 0–1024.

**CLI shape** (full reference: `references/cli-and-protocol.md`):

```sh
filmcraft-cli commands razor                    # find command ids
filmcraft-cli describe timeline.razor           # one command: menu, shortcut, params, enabled now
filmcraft-cli --demo inspect sequence           # project/sequence as JSON, no window
filmcraft-cli --project cut.fcproj --save exec timeline.razor seconds=3.5
filmcraft-cli --project cut.fcproj --save import a.mov b.wav
filmcraft-cli --project cut.fcproj export out.mp4 --preset "YouTube 1080p Full HD" --start 0 --end 10
filmcraft-cli export --list-presets prores
filmcraft-cli --project cut.fcproj render --seconds 2.5 --out frame.png
filmcraft-cli --bridge 127.0.0.1:9876 exec window.workspace.color   # needs FILMCRAFT_CONTROL_TOKEN
filmcraft-cli mcp --demo                                            # MCP on stdio, headless
```

Values parse as JSON when they can, else strings; dotted keys nest (capped at 64 levels). Exit status: 0 success, 1 a command failed or offline media was drawn without `--allow-offline`, 2 usage error.

**Document model.** One project per running app; sequences are the timelines and open in Timeline tabs. Panels dock/float on craft-ui's shared docking; 28 panel kinds; 9 built-in workspaces plus your own saved layouts.

**Core workflow.** Import media (⌘I or `file.import`) → build a sequence (`file.newSequence` / `file.newSequenceFromClip`) → edit on the timeline → save `.fcproj` (⌘S; `file.save` / `file.saveAs` ⇧⌘S / `file.saveCopy` ⌥⌘S) → export (`File ▸ Export ▸ Media…`, `file.exportMedia`, or `export.quick`). Verified keys: `Cmd+Z`/`Cmd+Shift+Z` undo/redo, `Cmd+K` Add Edit, `Cmd+S` save, `Cmd+O` open, `Cmd+I` import, `Alt+Shift+1..8` workspaces, `Alt+[` / `Alt+]` work area In/Out.

**Time.** Ticks everywhere: 254 016 000 000 per second. Commands accept `ticks`, `seconds`, `frame` or `timecode`.

**Work area.** Show it with `sequence.workAreaBar`, set in/out with `sequence.setWorkAreaIn`/`Out` or both with `sequence.setWorkArea {start,end}`; `range: "workArea"` in an export then works. `export.resolve` errors with "the sequence has no work area" until one exists.

## Working with an AI agent

Legitimate and effective:

- **Headless round trips** with `filmcraft-cli` (no window, no GUI state): import → edit via `exec`/`run` → `export` → verify. `run script.jsonl` takes one `{"id","params"}` per line and stops at the first failure unless `--keep-going`.
- **Drive the live app** through a tokened `--control <port>` or `filmcraft-cli mcp --bridge 127.0.0.1:9876`: run commands, inspect `ui.elements` for automation ids, click/drag/type, screenshot, then `edit.undo` if wrong. Pass the token through the environment of both processes; never embed it in a script argument.
- **Enumerate before you guess**: never invent command ids, parameter names or shortcuts. `commands`, `describe <id>` and `command_list` are authoritative. `effects.apply` returns the applied instances — use them to target later `effects.setParam` calls, and expect out-of-range values to be refused with the parameter and accepted value named.
- **Prepare and convert inputs**: generate test media with ffmpeg (allowed as an external oracle); convert unsupported sources into what FilmCraft reads.
- **Interpret and repair project files**: `.fcproj` is documented JSON with a migration chain and atomic writes. Repair by relinking media through commands, not by editing paths while the app has the project open.
- **Verify exports outside the app**: `ffprobe`/`ffmpeg -i` for streams, duration, frame count, A/V sync; check exit status, the `offlineMedia` array, and the written path (the format may change the extension). `sdr: true` tone-maps HDR to SDR; `maxThreads` bounds export CPU use on shared machines.
- **Follow background exports correctly**: local `file.exportMedia` calls block unless `wait:false`; with the bridge, without `wait`, use the returned `poll: "jobs.list"` / `cancel: "jobs.cancel"` hints. Do not pass `wait:false` to a one-shot local CLI process unless you keep it alive.
- **Batch production**: `export.queue.add … start=true wait=true` for several deliverables; `jobs.list` for progress/ETA; `jobs.cancel` to stop.
- **Import AAF/OMF repeatedly**: embedded audio is extracted next to the document without clobbering; read the import result.
- **Find repeated frames before trimming**: `sequence.duplicateFrames` returns per-clip ranges that another clip also shows; it skips stills, generators, nests, graphics, adjustment layers, frame holds and keyframed Time Remapping, so an empty result is not proof that no frame repeats.

Must not attempt:

- Do not assume `.prproj`, Premiere projects, plug-ins, upload destinations, Whisper transcription or Kokoro voices exist in the installed build.
- Do not start the control server without a token, or reuse one token across machines/sessions in a shared file; the listener refuses to start otherwise.
- Do not drive the GUI blind: read `ui.elements`/`ui.inspect` before clicking by id, and screenshot to confirm.
- Do not leave the control port open when idle: it is loopback-only, authenticated.
- Do not hand-edit a `.fcproj` to look like a newer schema or copy a `schema_version` forward.
- Do not expect the headless MCP server to be sandboxed: there are no confinement flags.
- Do not commit screenshots of Adobe products or use Adobe artwork when producing documentation assets (repo rule `AGENTS.md` §1).

## Verification protocol

FilmCraft is alpha and estimates itself "~56% ready for real work". Assume every step can silently produce a wrong-but-valid file:

1. **Throwaway round trip first.** New project → import one clip → place → export → `ffprobe` the output → reopen the project in a second process and check `inspect` matches. Only then touch real work.
2. **Never trust a silent export.** Check the exit status, the `offlineMedia` list and the message naming the written files.
3. **Read the result as media, not as a file.** Check duration, frame count, frame rate, audio channels and a couple of decoded frames.
4. **Version and back up per session.** Auto-save and the recovery journal are safety nets, not backups. `file.saveAs` / `file.saveCopy` before risky operations.
5. **Mind the schema.** A project saved by a newer build cannot be opened by an older one. Update apps only *between* projects.
6. **Do not trust parity docs or the README over the code.** When a doc and the code disagree, the code wins; when both are silent, write "uncertain" and test.
7. **Record the exact build** you tested (version + commit, e.g. 0.15.0 / `94ceaa91…`) — bug reports with real footage and a build id are what the project asks for.

## Sources & evidence

- Repo: https://github.com/storytold/filmcraft — inspected at **tag `v0.17.0`, commit `eb59ec09daaea519c9c8fffa404a594ae50d00e0`** (shallow clone at the release tag, 2026-11-01), **2026-11-02**; the v0.15.0 ref was fetched for id diffs. The installed app matches the tag (`filmcraft 0.16.0`).
- Registry note: the release notes contain no command-registry PR; the `camera_keys!` generation site (`crates/engine/src/multicam.rs:132`) and the 17 `#[tool]` MCP entries were re-counted; the shared-module refactor moved declarations between macro forms, so static id enumeration across tags is not byte-comparable this round — `filmcraft-cli commands` on a built binary is the authority.
- Files read: `README.md`, `Cargo.toml`, `docs/{agents,control-protocol,gaps,codec-parity,captions,web}.md`, `apps/filmcraft/src/{args,control_server}.rs`, `apps/filmcraft-cli/src/main.rs`, `crates/engine/src/{commands,multicam,graphics,sequence_tools}.rs`, `crates/automation/src/server.rs`, `crates/ui-egui/src/{control,dock}.rs`, `crates/ui-egui/src/i18n/`, `crates/export/src/{lib,format,run,presets}.rs`, `crates/codecs/src/{lib,video,mp4}.rs`, `crates/media/src/lib.rs`, `crates/interchange/src/lib.rs`, `crates/captions/src/lib.rs`, `crates/color/src/log.rs`, `crates/format/src/lib.rs`, `crates/time/src/lib.rs`, `crates/platform/src/lib.rs`.
- Shared libraries consulted only by pin: all craft-libs crates (`craft-media`, `craft-docpath`, `craft-ui`, `craft-update`) at one revision, `92d392cf…` (`Cargo.toml`).
- See `evidence.md` in this directory for the claim → evidence table and how to re-verify.