Skip to content
Esc
navigateopen⌘Jpreview
On this page

CLI

Every odori command, its flags, and what it writes.

The CLI ships as @odori/cli and installs a odori binary.

pnpm add -D @odori/cli
pnpm odori --help

odori dev

Discovers the project, regenerates .odori/, and starts Studio.

odori dev --port 4300

Studio watches videos/ and reloads when a video.tsx, *.preview.tsx, or brand module appears or disappears. The dev server also exposes the endpoints Studio uses to request a still or an export.

Studio opens in the default browser when the shell is interactive. Pass --no-open, set open: false in odori.config.ts, or set ODORI_OPEN=0 to start without it. CI and piped output never open a browser.

odori dev --no-open

docsUrl in odori.config.ts sets where Studio’s documentation link points, and defaults to the local docs site at http://localhost:4321.

odori init

Adds videos/layout.tsx, a first videos/launch/video.tsx, and odori.config.ts to an existing project. Existing files are never overwritten.

odori new <name>

Generates videos/<name>/video.tsx with static metadata and a JSX timeline. It wires the root layout when videos/layout.tsx exists.

odori add <components...>

Copies registry component source and its preview fixture into videos/components/, resolves registry dependencies, and records provenance in .odori/components.json.

odori add @odori/title-reveal @odori/end-card
odori add @odori/terminal --force

A component you have edited locally is kept, with a warning, unless --force is passed.

odori registry

Prints the catalog grouped by family, with aspect ratios, minimum duration, and reduced-motion behavior for each component.

odori diff [components...]

Compares installed component source with the version that was installed and with the version the registry ships today. Each component is reported as up to date, modified locally, update available, or modified locally and updated upstream.

odori diff
odori diff terminal --full

odori update [components...]

Applies upstream changes to components you have not edited. A component that is both edited locally and changed upstream is left alone until you review it with odori diff and pass --force.

odori list

Prints discovered video IDs, formats, durations, source files, and the number of component previews.

odori inspect <id>

Resolves the layout, compiles the timeline in a browser, runs prepare.ts, and freezes a manifest.

odori inspect launch
odori inspect launch --json --input '{"headline":"Ship it."}'

odori still <id>

Renders one deterministic frame.

odori still launch --frame 120 --output out/hero.png

odori test [id]

Validates contracts and representative frames for one video or all of them. It fails when default props do not satisfy the schema, when a declared duration disagrees with the compiled scene total, when a frame is blank, when content escapes the canvas, or when text is smaller than 20px at a 1080p reference.

odori export <id>

Freezes a manifest, records a job under .odori/builds/, renders every frame through the readiness handshake, mixes the audio track, and encodes an MP4 with FFmpeg. Frames are captured by several browser workers in parallel.

odori export launch --output out/launch.mp4
odori export launch --concurrency 8 --preset slow
odori export --retry job-88e09129a0-msw17lz9

A retry replays the frozen manifest, so it never re-resolves inputs or reruns prepare.ts.

odori jobs

Lists recorded export jobs with status, attempts, and output path.

job-88e09129a0-msw17lz9  launch  ready  attempts 2  out/launch.mp4

Shared flags

Flag Purpose
--input '<json>' Serializable input validated by the video schema
--output <path> Output path for still and export
--force Replace locally modified component source
--json Machine-readable output for inspect
--concurrency <n> Parallel render workers for export
--preset <name> x264 preset for export, default medium
--retry <job id> Re-run a recorded job from its frozen manifest
--full Print the diff body in diff

Requirements

Rendering needs Chrome or Chromium and FFmpeg. Odori looks for a browser at the usual macOS and Linux locations, at chromePath in odori.config.ts, or at ODORI_CHROME.

Was this page helpful?