Skip to content

Commands

Commands are the only write path into the engine. Instead of calling imperative methods that mutate state directly, you dispatch descriptive intents:

project.dispatch({
  type: "clip/move",
  payload: { clipId: "clip-1", trackId: "video-1", startUs: 1_000_000 },
});

Properties

  • Descriptive — a command says what should happen, not how. The engine decides how to apply it.
  • Validated — every command is checked against its schema before execution; invalid commands are rejected with typed errors and never touch state.
  • Deterministic — the same state plus the same command always produces the same result. This is a hard requirement for collaboration and AI replay.
  • Invertible — each executed command records inverse patches, so history is exact.
  • Serializable — commands are plain JSON, so they can be logged, synced, stored, or generated by an LLM.

Transactions

Group commands into a single history entry that undoes and redoes as a unit:

project.transaction(() => {
  project.dispatch({ type: "clip/split", payload: { clipId: "clip-1", atUs: 2_000_000 } });
  project.dispatch({ type: "clip/remove", payload: { clipId: "clip-1b" } });
});

Custom commands

Consumers can register their own command types alongside the built-in catalog, with the same validation, history, and patch semantics.

AI integration

Because the command catalog ships with JSON schemas, it doubles as a tool definition for LLMs: give a model the current project state and the catalog, and it can emit a valid command sequence to perform an edit.