Skip to content

Scripts & tooling ​

This is the reference for videoclaw's own repo tooling — the main npm scripts defined in package.json and helpers 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.

The fixture smokes are designed to run without paid generation. Infrastructure, live acceptance and graph commands have different effects; inspect their contracts before running them. 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 buildStage a tsc build and swap it into dist/ (the previous build stays complete throughout), then chmod +x the four compiled entrypoints (cli/vclaw.js, cli/provider-adapter.js, cli/flow-quote-adapter.js, cli/reapi-quote-adapter.js; the published bin names are videoclaw/vclaw and vclaw-provider-adapter, the two quote adapters being invoked by path). 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: lint, check:module-size, 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).
lintnpm run linteslint src --max-warnings=0 — the lint gate CI runs.
check:module-sizenpm run check:module-sizeFails when a src/video module grows past its ceiling (split it, do not raise the number).
setup:test-pythonnpm run setup:test-pythonCreates the pinned .venv from requirements-test.txt (Pillow, fonttools, numpy, praat-parselmouth).
check:test-pythonnpm run check:test-pythonVerifies the pinned Python test environment; the test runner refuses a drifted Pillow.
test:coveragenpm run test:coveragebuild then the c8-instrumented critical-coverage suite.
test:coverage:compilednpm run test:coverage:compiledThe coverage suite against an existing dist/ (no rebuild).
demo:creatornpm run demo:creatorAlias for npm run demo.
check:build-freshnpm run check:build-freshFails when dist/ is older than src/ — a stale build masquerading as tested.

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 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 four of the six registered multi-shot presets (cinematic-15s, seedance-10s, veo-8s, runway-10s; music-video-15s and social-hook-8s are not covered). 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.
smoke:rap-dryrunnpm run smoke:rap-dryrunRap lane: a solo and a duet film built from nothing reach qc — no renders, no spend (needs ffmpeg-full, macOS say).

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.
frontdoors:installnpm run frontdoors:installMaterialises the /slash front doors declared in scripts/skill-frontdoors.json into .claude/ (pointer skills + trigger blocks).
frontdoors:checknpm run frontdoors:checkReports drift between the declared front doors and what .claude/ has; exits 1, writes nothing.
check:seedance-enginenpm run check:seedance-engineOffline self-test of the free Higgsfield engine that ships with videoclaw (engines/seedance-direct).
check:modelark-pricesnpm run check:modelark-pricesCompares the seedance-modelark price table with the live BytePlus catalogue through the Ark CLI (arkcli pricing models). Fails when a list price or a sold resolution has drifted; reports account discounts without failing. Spends nothing; skips, out loud, when arkcli is missing or signed out — so it is a local check, never CI. Needs npm run build first.
docs:syncnpm run docs:syncRegenerates docs-site/reference/ from docs/ — run after ANY docs/*.md edit.
check:docs-sitenpm run check:docs-siteFails when docs-site/reference/ does not match docs/ (+transforms); CI runs it.
diagrams:lintnpm run diagrams:lintLints docs-site/diagrams/manifest.json: unique ids, sources and pages exist, every labels[] string is in its Mermaid, and the mirrored README/docs diagrams match their fence in docs/DIAGRAMS_SOURCE.md. Renders nothing.
diagrams:mirrornpm run diagrams:mirrorRe-extracts the README/docs Mermaid blocks from docs/DIAGRAMS_SOURCE.md into docs-site/diagrams/src/docs-*.mmd + manifest entries (run after editing a fence there).
diagrams:rendernpm run diagrams:renderRenders the mirrored README/docs diagrams with mermaid-cli (brand config) and publishes their JPGs to docs/assets/ and docs-site/public/diagrams/. Deterministic; the images in docs/assets/ are this render.

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: build → check:build-fresh → lint → check:module-size → test:node → the compiled coverage run → 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 schema-coverage check with --strict, which fails the gate on drift. 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). Run it manually when the area is in scope. It does run the schema-coverage check with --strict, so artifact-schema drift fails the gate rather than being tolerated.

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
acceptance:livenpm run acceptance:live

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. Use the fixture smokes appropriate to the change; live acceptance and infrastructure commands require separate attention to their effects.

Shared queue & knowledge graph ​

Infrastructure scripts for the multi-machine render queue and the repo's knowledge graph.

ScriptCommandPurpose
shared-queue:setupnpm run shared-queue:setupConfigures this machine for the shared multi-machine render queue.
shared-queue:statusnpm run shared-queue:statusPrints the shared queue's lane leases and receipts.
shared-queue:dashboardnpm run shared-queue:dashboardOpens the shared queue's dashboard.
shared-queue:self-testnpm run shared-queue:self-testExercises acquire/heartbeat/release against the deployed coordinator.
shared-queue:verifynpm run shared-queue:verifyRuns coordinator typechecking, tests and a deployment dry run; does not prove the live deployment matches.
graph:fullnpm run graph:fullRebuilds the graphify knowledge graph (graphify-out/), including the Gemini stage.

Additional installed checks ​

CommandPurpose
npm run smoke:story-bible-imageExercise the image-only story-bible path.
npm run smoke:multi-shotExercise multi-shot compilation.
npm run smoke:rap-dryrunRun solo and duet rap fixtures and stamp their dry-run evidence.
npm run frontdoors:installInstall the shared skill front doors.
npm run frontdoors:checkCheck those front doors without installing.

Read package.json for the exact current command bodies. Contributor tests require Node 20.10+, Python 3.12+ in the configured virtual environment, test requirements and FFmpeg/ffprobe. npm test does not run the separate Bun Flow suite or verify live providers.

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