Skip to content

Command line

studio has 32 commands, read from the typer app in engine/cli.py. studio <command> --help prints the same text in the terminal.

Most commands take a project: a folder holding a site.yaml, given as a path or by name (a name is looked up in the projects folder, then in examples/).

Command What it does
studio new Create a project.
studio remake Read a live landing page and write a new project that tells it as a scroll site: its hero picture as the opening scene, its sections as blocks, its calls to action with …
studio build Build a project into dist/.
studio storyboard Storyboard the site before the full render: <project>/storyboard/ (the page with stills standing in for films, storyboard.html + sheet.jpg with a card per shot and the …
studio directions Art directions for the site, pitched like a studio: one brief in, several complete directions out (concept, palette, type, style, imagery, motion), each a board of …
studio looks Build the site once in every style: dist/looks/<style>/ with a look switcher, and a gallery at dist/looks/.
studio brand Set the theme's colours from a logo (contrast-checked) and use it as the nav logo, or (--from) write a brand's colours, fonts, radius and logo into theme.from, where …
studio freeze Render one frozen-moment beat (deep zoom and layers included), or print its tile plan, or measure its clip.
studio preview Serve a built project locally.
studio record Record a scroll-through to MP4 (for README, social posts, Reddit).
studio inspect Polish report for a built film (beats, a take or a video): scores it second by second and beat by beat for pops (jumps, flicker, judder and crossfades that do not line …
studio previews Preview video + poster for each project's first scene (for galleries and READMEs).
studio snapshot Screenshots at scroll positions + a contact sheet (snapshots/sheet.jpg).
studio cuts The film grammar between a built site's sections (transition:): each cut, how long it is, the shapes a match cut found; with --strip, a frame strip around each one to …
studio poster A poster JPG of a built site at one scroll position (screenshot -> FFmpeg -> JPG).
studio publish Assemble built projects into one static folder: out/<project>/... ready for GitHub Pages or any host.
studio combine Join recordings into one video with crossfades (e.g. a reel of several sites).
studio product The site's product: normalise its model (cached), list its parts, render stills.
studio inside The product as the set: print the route (which parts each stop found, how the camera comes in, where the copy sits on the scroll) and render quick stills of stops or a …
studio trailer Cut a launch trailer from the site's own renders: dist/trailer/trailer-16x9.mp4 and trailer-9x16.mp4.
studio camera Keyed camera moves on a moving beat (camera: on a beat): preview the guide, or measure how well the render follows the keys.
studio diorama Miniature worlds: lay a diorama section out and say what was decided: the map with the places numbered (diorama/<id>-map.jpg), which step lives at which place, where …
studio cinemagraph Build the site's cinemagraphs (an image input with cinemagraph:: a still where only one thing moves) and report on each: the loop's seam, how much of the picture …
studio world Check the in-world type of a built film (steps with place: {kind: behind \| surface \| sky}): draws each title's box through the per-frame matrices the page will use on …
studio light Light as the scroll (type: light): build the section, then write what it made to look at, in <project>/light/<section>/: sheet.jpg (every time of day with its drift …
studio journey The one-take page (journey: on a film): its approach, every move and hold with the film seconds and scroll they get, and, once built, where each stop's blocks sit on …
studio schema Print the site.yaml JSON Schema.
studio doctor Check the toolchain and report what each scene type needs.
studio setup-comfy Install the ComfyUI custom nodes that reveal (scroll-driven colour) and faces: restore use.
studio ui Start the Studio app.
studio copy export Write the site's text to a Markdown copy deck.
studio copy import Apply an edited copy deck to site.yaml (comments kept; an invalid result is refused).

studio new

studio new [OPTIONS] NAME

Create a project.

Argument Type Default Description
name text required
Option Type Default Description
--example text Copy an example from examples/
--laptop flag off A starter that builds on any laptop, with no GPU, ComfyUI or Blender
--image path With --laptop: your photo, opened as a photo parallax (default: the page opens on kinetic type)

studio remake

studio remake [OPTIONS] URL

Read a live landing page and write a new project that tells it as a scroll site: its hero picture as the opening scene, its sections as blocks, its calls to action with their links, its brand in theme.from.

Argument Type Default Description
url text required
Option Type Default Description
--name text Project name (default: from the site's address)
--style text Wear one of the styles (engine/styles/) over the brand
--no-gpu flag off Open with a laptop scene (photo parallax) even when a GPU is here

studio build

studio build [OPTIONS] NAME

Build a project into dist/. Prints what will render and about how long it takes here before starting.

Argument Type Default Description
name text required
Option Type Default Description
--only text Render only these sections and beats (ids, comma separated); the rest keep their cache or show their storyboard stand-in
--section text Rebuild one scene only (same as --only <id>)
--force / --no-force flag off Ignore the cache (locked scenes and beats are still kept)
--draft / --no-draft flag off Fast low-quality renders where supported
--yes / -y flag off Don't ask, even over studio.toml's confirm_over
--plan flag off Print what would render and the estimate, then stop

studio storyboard

studio storyboard [OPTIONS] NAME

Storyboard the site before the full render: <project>/storyboard/ (the page with stills standing in for films, storyboard.html + sheet.jpg with a card per shot and the render estimate, animatic.mp4). With --edit: the same shots as an editing workspace on a local server.

Argument Type Default Description
name text required
Option Type Default Description
--level text "stills" sketch (no ComfyUI: blockouts, cached stills, cards), stills (the real first frames) or animatic (stills in motion + animatic.mp4)
--only text Redo only these shots (beat, section or block ids); the rest keep their last storyboard frames
--motion flag off animatic: a tiny LTX-2.3 preview per shot (512x288, 2 s) to check motion
--open flag off Open storyboard.html when done
--edit flag off Serve the storyboard as an editing workspace instead: change any shot's text, seed, motion or length (written into site.yaml), regenerate one image at a time, keep every variant, lock and approve shots
--port integer --edit: port (default: the first free one of 8971-8979)
--browser / --no-browser flag true --edit: open the browser
--notes flag off Print the open notes written in the editor, each with its shot's current values and image paths (for an agent without MCP), and stop
--all flag off --notes: include working and done notes

studio directions

studio directions [OPTIONS] NAME

Art directions for the site, pitched like a studio: one brief in, several complete directions out (concept, palette, type, style, imagery, motion), each a board of storyboard stills, side by side on one page. Pick one and it is written into site.yaml. Outputs in <project>/directions/: board.html, board.png (contact sheet), directions.json.

Argument Type Default Description
name text required
Option Type Default Description
--n / --count integer How many directions (default: the spec's directions.count, 6)
--seed integer Another seed, another set of directions (default: the spec's, 1)
--brief text What to pitch, in your words (default: the spec's directions.brief)
--pick text Write this direction (its letter, or its name) into site.yaml: theme, style, fonts, imagery, pace; copy is never touched. The old file is kept
--undo flag off Put site.yaml back as it was before the last pick
--reroll text Another idea in place of this direction (its letter)
--stills flag off Draw the stills of the saved directions again (ComfyUI was down)
--images / --no-images flag true --no-images: placeholder cards instead of Z-Image stills
--sheet / --no-sheet flag true Make board.png (headless Chrome)
--serve flag off Serve the boards in the browser, with a Pick button on each
--port integer --serve: port (default: the first free one of 8981-8989)
--browser / --no-browser flag true --serve: open the browser
--show flag off Print the saved directions and stop

studio looks

studio looks [OPTIONS] NAME

Build the site once in every style: dist/looks/<style>/ with a look switcher, and a gallery at dist/looks/.

Argument Type Default Description
name text required
Option Type Default Description
--styles text Comma-separated styles (default: all of engine/styles.yaml)
--thumbs / --no-thumbs flag true Screenshot each look for the gallery page

studio brand

studio brand [OPTIONS] NAME

Set the theme's colours from a logo (contrast-checked) and use it as the nav logo, or (--from) write a brand's colours, fonts, radius and logo into theme.from, where they can be edited.

Argument Type Default Description
name text required
Option Type Default Description
--logo text Logo file inside the project (png, svg rendered as png, jpg)
--mode text "light" light or dark
--dry-run / --no-dry-run flag off
--from text Read a brand from a web page URL, a saved .html page, a logo image or a brand.yaml, and write its tokens into site.yaml as theme.from

studio freeze

studio freeze [OPTIONS] NAME BEAT

Render one frozen-moment beat (deep zoom and layers included), or print its tile plan, or measure its clip.

Argument Type Default Description
name text required
beat text required
Option Type Default Description
--plan flag off Print the deep-zoom tile plan (levels, tiles, boxes) and stop: no ComfyUI, no GPU
--report flag off After rendering, measure the clip: sharpness at each zoom the camera reaches, a frame-difference plot (pops), a frame strip; written beside the clip
--against text --report: another frozen beat to measure alongside (the same camera without detail, say)

studio preview

studio preview [OPTIONS] NAME

Serve a built project locally.

Argument Type Default Description
name text required
Option Type Default Description
--port integer 5173

studio record

studio record [OPTIONS] NAME

Record a scroll-through to MP4 (for README, social posts, Reddit).

Argument Type Default Description
name text required
Option Type Default Description
--section text
--seconds number 12.0
--out path
--gif / --no-gif flag off
--width integer 1920
--height integer 1080
--out-width integer
--poster-at number 0.5 Where in the recording (0-1) to take the poster JPG
--pointer text Move the mouse while recording, for pictures that follow it (pointer: lenses and lights): 'wander' for a slow tour of the frame, or waypoints 'x,y x,y ...' in 0-1 of the viewport
--cursor / --no-cursor flag true With --pointer: draw a small ring where the pointer is (headless frames have no cursor)

studio inspect

studio inspect [OPTIONS] NAME

Polish report for a built film (beats, a take or a video): scores it second by second and beat by beat for pops (jumps, flicker, judder and crossfades that do not line up), softness (looks upscaled), halos (rims and double edges), style drift (the look moving away from the section's start) and morphs (shapes rebuilding instead of moving). Writes <project>/.build/inspect/<section>.json and .html (the worst moments with pictures and a line saying what is wrong); the storyboard editor shows each beat's worst problem. CPU only; unchanged films are answered from the saved report.

With --page it checks the built page instead (see the guide, "Check a page before you ship it"): the report is <project>/.build/inspect/page/report.json with a contact sheet per screen size, and the exit code is 1 when a check fails, so a showcase page can be gated on it.

Argument Type Default Description
name text required
Option Type Default Description
--section text Film section to inspect (default: every film section that has a built film)
--video path Inspect any video file as one shot instead (a screen recording, a clip)
--json flag off Print the report as JSON and nothing else
--force flag off Measure again even if the film has not changed
--embed flag off Also measure style drift with a local CLIP embedding (OpenCLIP ViT-H/14 from the Hugging Face cache, CPU, slow; nothing is downloaded)
--open flag off Open the HTML report when done
--page flag off Check the built page instead of its films: screenshots at desktop and phone size (headless Chromium, reduced motion), text over pictures, type, pictures and layout, per section; exits 1 when anything fails. --section limits it to one section

studio previews

studio previews [OPTIONS] NAMES...

Preview video + poster for each project's first scene (for galleries and READMEs).

Argument Type Default Description
names text required
Option Type Default Description
--out path required Folder for <project>.mp4 + <project>.jpg
--seconds number 10.0
--out-width integer 1280
--poster-at number 0.5
--skip-existing / --no-skip-existing flag true

studio snapshot

studio snapshot [OPTIONS] NAME

Screenshots at scroll positions + a contact sheet (snapshots/sheet.jpg).

Argument Type Default Description
name text required
Option Type Default Description
--at text, repeatable required scene:progress, top, bottom or y:<px>; repeatable
--width integer 1600
--height integer 900

studio cuts

studio cuts [OPTIONS] NAME

The film grammar between a built site's sections (transition:): each cut, how long it is, the shapes a match cut found; with --strip, a frame strip around each one to look at.

Argument Type Default Description
name text required
Option Type Default Description
--strip flag off Frame strips around each cut of the built site (<project>/.build/cuts/cut_<n>.jpg)
--only text Comma-separated cut numbers (default: all)
--mobile flag off Strips at a phone's size (390x844)
--reduced-motion flag off Strips with prefers-reduced-motion on (the cuts fall back to plain cuts)
--frames integer 9 Frames in each strip
--clip flag off With --strip: also a short video of each cut (cut_<n>.mp4)

studio poster

studio poster [OPTIONS] NAME

A poster JPG of a built site at one scroll position (screenshot -> FFmpeg -> JPG).

Argument Type Default Description
name text required
Option Type Default Description
--at text required scene:progress (e.g. studio:0.88), top, bottom or y:<px>
--out path required JPG to write
--width integer 1280

studio publish

studio publish [OPTIONS] NAMES...

Assemble built projects into one static folder: out/<project>/... ready for GitHub Pages or any host.

Cross-links between projects written as ../<project>/dist/ (how the showcase gallery links locally) are rewritten to ../<project>/. A .nojekyll file keeps GitHub Pages from dropping folders that start with _.

Argument Type Default Description
names text required
Option Type Default Description
--out path required Folder to deploy (e.g. a GitHub Pages repo)
--home text Project whose page becomes the folder's index.html

studio combine

studio combine [OPTIONS] VIDEOS...

Join recordings into one video with crossfades (e.g. a reel of several sites).

Argument Type Default Description
videos path required
Option Type Default Description
--out path required MP4 to write
--fade number 0.6 Crossfade between clips, seconds

studio product

studio product [OPTIONS] NAME

The site's product: normalise its model (cached), list its parts, render stills.

Argument Type Default Description
name text required
Option Type Default Description
--parts flag off List the model's parts and materials (names to target in product.parts)
--still text Render a still: front, three-quarter, side, top, back, hero-low, exploded, detail
--part text detail (or any view): glob on the part to frame
--size text "1600x1200" Still size WxH
--background text "transparent" transparent, theme or a hex colour
--scene text Render the still into a generated scene (prompt; needs ComfyUI)
--out path Copy the still here
--exposure number 0.0 Exposure in stops
--all flag off With --parts: every part, not grouped by name

studio inside

studio inside [OPTIONS] NAME

The product as the set: print the route (which parts each stop found, how the camera comes in, where the copy sits on the scroll) and render quick stills of stops or a strip along the route, with a contact sheet.

Argument Type Default Description
name text required
Option Type Default Description
--section text The type: inside section (when the site has several)
--still text Render stills: stop numbers (1,3), all for every stop, wide for the opening shot
--strip integer 0 Render this many frames spaced evenly along the whole route
--samples integer 24 Cycles samples for the stills
--scale number 0.5 Still size as a fraction of the scene's frame size
--out path Contact sheet of the stills (default: <project>/inside_<section>.jpg)

studio trailer

studio trailer [OPTIONS] NAME

Cut a launch trailer from the site's own renders: dist/trailer/trailer-16x9.mp4 and trailer-9x16.mp4.

Argument Type Default Description
name text required
Option Type Default Description
--format text 16x9 or 9x16 (default: trailer.formats)
--force / --no-force flag off Ignore the cache
--plan / --no-plan flag off Print the cut and stop

studio camera

studio camera [OPTIONS] NAME BEAT

Keyed camera moves on a moving beat (camera: on a beat): preview the guide, or measure how well the render follows the keys.

Argument Type Default Description
name text required
beat text required
Option Type Default Description
--guide flag off Only make the camera guide (depth, people mask, the guide videos) and print where it is: guide_rgb.mp4 is a pure-camera preview of the keyed move
--check flag off Measure the beat's rendered frames: does the camera follow its keys, do the people still move? Writes camera.json beside the beat's frames
--section text The film section, when the beat id is in more than one

studio diorama

studio diorama [OPTIONS] NAME

Miniature worlds: lay a diorama section out and say what was decided: the map with the places numbered (diorama/<id>-map.jpg), which step lives at which place, where the camera dives from, how far it orbits. Takes a couple of seconds and needs no GPU; with --strip it also photographs the built site along the whole scroll.

Argument Type Default Description
name text required
Option Type Default Description
--section text The diorama section (default: the first)
--strip flag off Also take a frame strip of the built site: every place at rest, and the lift, orbit and dive between places (dioramas/<id>-strip.jpg)
--full flag off Lay the ground out at full resolution (default: draft)

studio cinemagraph

studio cinemagraph [OPTIONS] NAME

Build the site's cinemagraphs (an image input with cinemagraph:: a still where only one thing moves) and report on each: the loop's seam, how much of the picture moves, what the page holds still, bytes. Files are in <project>/.build/_cinemagraph/. studio build makes them too, as part of the page.

Argument Type Default Description
name text required
Option Type Default Description
--only text Only the cinemagraphs whose moves or spec path contains this text
--force / --no-force flag off Ignore the cache
--list flag off List the cinemagraphs in the spec and their cache state, build nothing
--check flag off Instead of building, measure the BUILT page (dist/) in Chrome: is everything but the moving part truly still, does the loop hitch, does reduced motion show the still
--mobile flag off With --check: a 390 px phone viewport

studio world

studio world [OPTIONS] NAME

Check the in-world type of a built film (steps with place: {kind: behind | surface | sky}): draws each title's box through the per-frame matrices the page will use on the film's own frames (with the depth map beside them for behind and sky type), measures how steady the track is and how much of the time the type is on screen, and says what to change. Writes .build/<section>/world/sheet.jpg and report.json: read the sheet.

Argument Type Default Description
name text required
Option Type Default Description
--section text The film section (default: every film with in-world type)
--frames integer 6 Frames drawn on the sheet per title

studio light

studio light [OPTIONS] NAME

Light as the scroll (type: light): build the section, then write what it made to look at, in <project>/light/<section>/: sheet.jpg (every time of day with its drift from the world, raw and aligned), strip_*.jpg (the page across each transition, the same scroll positions a viewer passes through) and light.json (drift, edge agreement and how far apart neighbouring times are). The drift is how far the editor moved the place, in pixels at 1024 across.

Argument Type Default Description
name text required
Option Type Default Description
--section text The light section (default: every one)
--build / --no-build flag true Build the section first (cached stages are skipped)
--strips / --no-strips flag true Screenshot the built page across every transition
--frames integer 7 Frames per transition strip
--presets flag off List the named times of day and exit

studio journey

studio journey [OPTIONS] NAME

The one-take page (journey: on a film): its approach, every move and hold with the film seconds and scroll they get, and, once built, where each stop's blocks sit on its picture and the contrast they reach.

Argument Type Default Description
name text required
Option Type Default Description
--section text The film section, when there is more than one journey
--json flag off Print the report as JSON

studio schema

studio schema

Print the site.yaml JSON Schema.

studio doctor

studio doctor [OPTIONS]

Check the toolchain and report what each scene type needs.

Option Type Default Description
--verify / --no-verify flag off Also hash the model files in ComfyUI's folder against engine/models.yaml (slow)

studio setup-comfy

studio setup-comfy [OPTIONS]

Install the ComfyUI custom nodes that reveal (scroll-driven colour) and faces: restore use.

Option Type Default Description
--no-weights / --no-no-weights flag off Skip the GFPGAN face-restore weights (~330 MB)

studio ui

studio ui [OPTIONS]

Start the Studio app.

Option Type Default Description
--port integer 5180
--no-open / --no-no-open flag off Don't open a browser

studio copy export

studio copy export [OPTIONS] NAME

Write the site's text to a Markdown copy deck.

Argument Type Default Description
name text required
Option Type Default Description
--out path Default: <project>/copy.md

studio copy import

studio copy import [OPTIONS] NAME DECK

Apply an edited copy deck to site.yaml (comments kept; an invalid result is refused).

Argument Type Default Description
name text required
deck path required
Option Type Default Description
--dry-run / --no-dry-run flag off Show the changes without writing