Skip to content

Scripts & tooling

This is the operator and agent reference for videoclaw's own repo tooling — every npm script defined in package.json, and every helper under scripts/. These are the commands you run on the codebase itself: building it, testing it, smoke-proving the whole pipeline, and guarding against drift before changes land. (For commands you run to make videos, see the CLI reference — vclaw video ... — not this page.)

One command to remember

Before you change anything non-trivial, run npm run check:release-readiness-lite. It is the single pre-flight: it builds, runs every unit test, runs the main smokes, and runs the guardrails — in one shot. If it prints release-readiness-lite checks passed, you are clear.

Everything here is deterministic and offline by default. The smokes create throwaway projects in a temp directory, drive the real CLI end-to-end, assert the on-disk artifacts, and then delete the temp dir. None of them spend provider credits, call an API, or need a key — they stub providers and use --dry-run. The one exception (smoke:assemble-render) actually spawns FFmpeg locally and self-skips if FFmpeg is not installed.

How a run flows

tooling overview diagram

Diagram source (live Mermaid)

Build & test

Run these constantly. build is a prerequisite for everything else — the smokes and test:node run against compiled dist/, never the TypeScript source.

ScriptCommandPurpose
buildnpm run buildWipe dist/, run tsc, then chmod +x the two CLI bins (vclaw, vclaw-provider-adapter). The clean rebuild every other script depends on.
devnpm run devtsc --watch — incremental recompile while you edit. Leave it running in a terminal during development.
testnpm testFull gate: build then test:node. The canonical "did I break the unit suite" command.
test:nodenpm run test:nodeRe-run the compiled node:test suite (dist/tests/*.test.js) without rebuilding. Use after dev has already recompiled, for a fast inner loop. Runs single-threaded (--test-concurrency=1).
demonpm run demobuild then node scripts/demo-quickstart.mjs — runs the quickstart demo walkthrough against the freshly compiled CLI.
demo:recordnpm run demo:recordbash scripts/record-demo.sh — records the demo walkthrough (does not rebuild first).

Never edit dist/

dist/ is generated. Edit src/, then npm run build. Editing compiled output is silently discarded on the next build.

End-to-end smokes

Each smoke:* script runs npm run build first, then drives the real vclaw binary through a complete slice of the pipeline in an isolated temp project and asserts the resulting JSON artifacts. They are your proof that the wiring — CLI → domain modules → on-disk artifacts — actually holds together, not just that units pass in isolation. Run the relevant smoke after touching the area it covers; run them all via the release pre-flight before shipping.

ScriptCommandWhat it verifies
smoke:runtimenpm run smoke:runtimeThe core happy path: init → brief → storyboard → assets → execution-plan → execute --dry-run → status → report → export-obsidian. Confirms the dry-run produces a plan, the portfolio report sees the project, and the Obsidian note is written.
smoke:native-veonpm run smoke:native-veoThe native Veo (veo-useapi) transport. Stubs the local Bun vclaw-cli binary, runs a storyboard-mode execute, and captures the exact command the transport would have run — proving the Veo route assembles its submission correctly.
smoke:character-hydrationnpm run smoke:character-hydrationCreate-time cast hydration. Stands up a fake Go Bananas API server, runs vclaw video create with --import-library-characters and --auto-create-characters, and asserts imported character IDs land in the brief and the characters.json store.
smoke:execution-cancelnpm run smoke:execution-cancelAdapter- and project-level cancellation. Wires a stub UseAPI adapter, submits, then execute-cancel, and asserts the execution-report.json and an execution.cancelled event were written.
smoke:portfolionpm run smoke:portfolioPortfolio visibility: index → report → export-csv. Confirms a project surfaces in the index, the report metrics, and a well-formed projects CSV.
smoke:reference-sheetsnpm run smoke:reference-sheetsThe role-tagged reference-sheet surface end-to-end: reference-sheet-add/list/show/bind/validate, role-vocabulary rejection (non-zero exit), palette collision detection, status summary, and the on-disk reference-sheets.json artifact.
smoke:scene-candidatesnpm run smoke:scene-candidatesThe candidate/take operator surface: select-candidate, reject-candidate, reroll-scene, candidates-list, candidates-show, plus the Candidates section rendered into storyboard.md and a clean doctor-project run.
smoke:story-bible-imagenpm run smoke:story-bible-imageImage-only story-bible continuity: create builds a deterministic story bible, --apply-content-fixes regenerates scene text without going stale, doctor-project accepts it, and a --dry-run execute reaches dry-run-complete with zero video outputs through review → publish. Never submits a provider job.
smoke:assemblenpm run smoke:assembleThe FFmpeg assemble/stitch layer in dry-run. Asserts the plan threads narration (TTS) → slide-animation → final-video in order, records the stitch ffmpeg plan, and writes assemble-report.json. Needs no FFmpeg and no key.
smoke:assemble-rendernpm run smoke:assemble-renderReal FFmpeg render validation (the only non-dry smoke). Synthesizes inputs with FFmpeg lavfi + sharp, then actually renders MP4s and ffprobes them for h264/aac, resolution, fps, stream counts, durations, MP4-validity, and both demuxer and filter stitch paths plus music mixing. Self-skips and exits 0 if FFmpeg/ffprobe are not on PATH. Validates plumbing/codecs only — aesthetic quality still needs a human.
smoke:multi-shotnpm run smoke:multi-shotA plan→validate round-trip across every registered multi-shot preset (cinematic-15s, seedance-10s, veo-8s, runway-10s). Fixture-driven, fully offline, no Gemini.
e2e:image-storyboardnpm run e2e:image-storyboardThe image-storyboard workflow end-to-end, with --verify-server (exercises the review-station UI surface).
e2e:image-storyboard:examplesnpm run e2e:image-storyboard:examplesThe same workflow with --include-examples — runs the bundled example manifests in addition to the default.

Running a single smoke

Every smoke is a standalone Node script. After one npm run build, you can re-run just the compiled CLI driver directly — e.g. node scripts/smoke-assemble.mjs — to iterate fast without rebuilding each time.

Guardrails (check:*)

The check:* scripts are drift guards. They don't test runtime behavior; they assert the repo's invariants stay true — docs don't reference dead paths, schemas and writers stay in sync, helper wrappers still parse, and verification artifacts stay gitignored. Run the relevant guard after editing docs, skills, schemas, or artifact writers.

ScriptCommandPurpose
check:movie-director-wrappersnpm run check:movie-director-wrappersbash -n syntax-checks the six bundled movie-director helper scripts (auto, iterate, run-pipeline, verify, list-library, interview). Catches a broken wrapper before it ships.
check:cleanroom-docsnpm run check:cleanroom-docsScans README.md, docs/, and the movie-director / seedance-prompts skills for stale clean-room references — absolute home paths, retired CLI invocations, and other dead pointers — failing if any are found.
check:skill-frontdoornpm run check:skill-frontdoorScans every skills/*/SKILL.md front door for retired script references, ensuring each skill's entry doc points at the current vclaw CLI surface. The ignore list (e.g. seedance-prompts/SKILL.md) is load-bearing — do not "fix" it.
check:artifact-schema-coveragenpm run check:artifact-schema-coverageAdvisory (always exits 0). Asserts every artifact written via the typed writeArtifact() helper has a matching JSON Schema under schemas/video/artifacts/, and every schema has a writer (with a documented allowlist for artifacts written by other paths). Prints any drift.
check:artifact-schema-coverage:strictnpm run check:artifact-schema-coverage:strictThe same coverage check in strict mode — exits 1 on drift. Use in CI or when you want a hard failure on writer/schema mismatch.

Release pre-flight

ScriptCommandPurpose
prepublishOnly(automatic)npm test — npm lifecycle hook that runs the full build + test:node gate automatically before npm publish. You never invoke it directly.
check:release-readiness-litenpm run check:release-readiness-liteThe one-shot local gate. It checks that the generated verification-artifact paths are gitignored, then runs, in order: buildtest:node → the eight primary smokes (runtime, native-veo, character-hydration, execution-cancel, portfolio, reference-sheets, scene-candidates, assemble) → the e2e:image-storyboard workflow → all three doc/skill guardrails → the advisory schema-coverage check. Prints release-readiness-lite checks passed on success.

What the pre-flight does not cover

By design, check:release-readiness-lite excludes smoke:assemble-render (needs real FFmpeg) and the :strict schema check (advisory drift is tolerated mid-flight). Run those two manually when the area is in scope.

When to run what

SituationRun
Actively editing TypeScriptnpm run dev in a terminal, then npm run test:node to re-check
Quick "did I break units" checknpm test
Touched the assemble / FFmpeg layernpm run smoke:assemble, then npm run smoke:assemble-render locally
Touched docs, skills, or schemasthe matching check:* guard
About to commit anything non-trivialnpm run check:release-readiness-lite
Wiring schema coverage into CInpm run check:artifact-schema-coverage:strict

For agents

Treat check:release-readiness-lite as the success signal: a clean run is evidence the change is safe. Prefer running the narrow smoke for the area you touched first (fast feedback), then the full pre-flight before declaring done. Smokes are self-cleaning and side-effect-free, so they are always safe to run.

Built to be driven by agent hosts like Claude Code, Claude Desktop, or Codex · Source-available, commercial use requires a paid license.