Skip to content

kitsoki tour — render a demo video from the binary ​

kitsoki tour drives the embedded web UI headlessly to record a deterministic, no-LLM demo MP4 from a declarative tour manifest — no Node, pnpm, or Playwright. It is the binary-native counterpart to the Playwright recording specs (see Demo, video & testing): a foreign repo that owns a kitsoki instance (importing @kitsoki/<name>) can produce its own demo video with only the kitsoki binary present (the kitsoki-as-dependency epic, slice 2).

It reuses kitsoki web's no-LLM plumbing verbatim: a flow fixture (plus an optional host cassette) stubs every host.* call, the same posture kitsoki web --flow uses. The render is therefore fully reproducible and never touches a real LLM.

Synopsis ​

Load the tour either from the feature catalog — the common case:

kitsoki tour --feature agent-actions

features/<id>.yaml carries both the tour steps and the demo binding (its flow fixture, host cassette, story dir, and video base), so no other flags are needed. Or render a standalone manifest, supplying the no-LLM posture by flag:

kitsoki tour --manifest my-tour.yaml --flow stories/x/flows/happy.yaml \
  --stories-dir stories/x --out .artifacts/my-tour

Exactly one of --feature / --manifest is required, and a flow fixture must resolve (from the feature binding or --flow) — without it the render would not be no-LLM and the command errors.

Output ​

Everything lands in --out (default .artifacts/<feature-id>):

ArtifactContents
<videoBase>.mp4the rendered screencast
<videoBase>.mp4.chapters.jsonone chapter per step (source_ref kind tour)
<videoBase>.mp4.steps.jsonone record per poster PNG, tying it deterministically to its spec step (see below)
NN-<id>.pnga poster frame per step

The stdout line is the MP4 path (script-friendly); progress and the sidecar paths go to stderr.

Deterministic per-step references (steps.json) ​

Each poster PNG is recorded in <videoBase>.mp4.steps.json as a StepShot that points at the exact place in the spec it depicts — no LLM interpretation of the pixels required:

{
  "capture": 5, "step_index": 4, "png": "05-aa-welcome.png",
  "spec_ref": { "kind": "tour", "spec_path": "features/agent-actions.yaml",
                "pointer": "/tour/steps/4", "step_id": "aa-welcome" },
  "title": "Agent action transcripts", "route": "any",
  "states_asserted": ["bf.reproducing"],
  "title_asserted": true
}

spec_ref.pointer is an RFC 6901 JSON Pointer into the feature catalog (/tour/steps/N); states_asserted are the machine states the step's wait-state drives polled the session through before the screenshot; and title_asserted records that the renderer verified the popover title on screen at capture. These are facts the render enforced (it errors out otherwise), so a consumer — e.g. the kitsoki-ui-qa gate — can map a frame to the spec step and its verified states deterministically rather than asking a model what the frame shows. (In the example above, the repeated prd.clarifying entries are the multi-round clarification loop, provable from data alone.)

Requirements ​

ffmpeg and Chrome/Chromium must be on PATH. Without ffmpeg the per-step PNGs and the chapter sidecar are still emitted and the command reports the missing MP4 — useful for a frames-only check in an environment that lacks ffmpeg.

Flags ​

FlagDefaultEffect
--feature <id>—feature catalog entry (features/<id>.yaml) to render
--manifest <yaml>—standalone tour manifest (alternative to --feature)
--flow <yaml>feature's demo.flowno-LLM flow fixture stubbing host.*
--host-cassette <yaml>feature's demo.hostCassettehost cassette backing host.*
--stories-dir <dir>feature's demo.storystory directory to serve (repeatable)
--out <dir>.artifacts/<feature-id>output directory
--pace <f>1pacing multiplier: 0 = instant, 1 = watch speed
--headlesstruelaunch Chrome headless
--fps <n>30output MP4 frame rate
--width / --height1600 / 900viewport / video size

--feature resolves features/ against the repo root: $KITSOKI_REPO (exported from --kitsoki-repo / the persisted ~/.kitsoki/repo) if set, else a walk up from the cwd for a directory holding a features/ dir.

How a tour is authored ​

A tour step carries both narration (title/body/target/placement) and a declarative drive: action list (type-and-send, click-intent, wait-state, reveal-turn, dwell-ms) — the data the binary executes in place of a hand-written .spec.ts. The manifest lives in the feature catalog (features/<id>.yaml); the authoring workflow, the manifest schema, and the quality bar for a shareable artifact are owned by the kitsoki-ui-demo skill.