skill
narova
Open video production system for humans and agents — local-first CLI and agent skill: scene scripts, deterministic rendering, local TTS, word-synced captions, product walkthroughs, AI clips (Sora/Runw
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/ammar-hasan/narova itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 17, 2026Narova — open video production system for humans and agents
Turn an idea, script, source, repository, or real product flow into video you can direct, inspect, revise, reproduce, and ship.
Narova is not a video-generation model and it does not impose a house style.
Your agent—or you—owns the creative decisions. Narova provides the production
system underneath them: structured scenes, deterministic timelines, local
speech and rendering, proof branches, incremental revisions, walkthrough
capture, provenance, release gates, and machine-readable inspection. Agents
calling the CLI directly can use the versioned
--json protocol without parsing terminal prose.
This 30-second reel was made by Narova, about Narova. Watch it with sound · Explore the project · Install from npm · View on skills.sh · Live site
- Why Narova exists
- Mental model
- What makes it different
- What you can make
- Try it — one command
- Agent quickstart
- Direct CLI workflow
- Creative proofs and branches
- Deterministic iteration and releases
- Judge, assertions, and evidence
- Sources, assets, walkthroughs, and provenance
- Renderers and speech
- Machine protocol
- Architecture
- Installation and reference
- License
Why Narova exists
Generating a video once is becoming easy. Continuing to direct that video is still hard.
A generated clip usually throws away most of the production state that created it. Changing one decision can mean starting over. Agents cannot reliably tell what changed, what was actually rendered, which source supported a claim, whether a previous experiment was better, or which artifacts belong to the final release.
Narova treats video as an evolving production project instead of a disposable generation. A project is a folder with a reviewable scene script and the measured production state around it — manifest, timings, audio fingerprints, a revision ledger, proof bundles, provenance registers, and named releases. Every render is addressed by identity, so unchanged work is reused, changed work is limited to exactly what changed, and the encoded result can be inspected against the intent that produced it.
Mental model
intent
↓
creative direction
↓
small visual proofs
↓
structured production
↓
preview + direction
↓
deterministic render
↓
inspect the encoded result
↓
revise / branch / release
A Narova project moves through: source → brief → scene script → proof → synthesis → compose → preview → build → judge → revision → release. Each stage
remains inspectable and scriptable.
You (or your agent) own creative authorship: the script, the visuals, the taste, the selection. What you build and publish is your choice, and you are fully answerable for it — under law, by your own ethics, values, and conscience, and by the religious or cultural commitments you hold. Narova gives you inspectable sources, reviewable creative proofs, and explicit provider choice to support that judgment; it does not verify legality, rights, or acceptability for you. Narova owns the production machinery underneath: timing, orchestration, rendering, caching, inspection, and delivery. It is zero-style by default — no implicit palette, layout, chrome, or camera grammar. Every aesthetic choice is an explicit one.
What makes it different
Creative control without a built-in taste model. Narova is zero-style by default. It gives the creator and the agent a raw production canvas rather than silently deciding layouts, palettes, camera language, typography, or visual taste. Narova owns timing, orchestration, rendering, caching, inspection, and delivery; creative authorship stays with you.
Prove an idea before producing the whole thing. For ambitious work, Narova preserves several small, orthogonal visual proofs rather than generating several complete videos. Each proof has a rationale and rendered evidence. Choose deliberately, restore the selected production state, and expand only that direction.
Change the part you meant to change. Narration, scenes, walkthrough takes, and rendered outputs carry identities that let Narova reuse unchanged work. A visual change does not require regenerating narration. A changed scene does not require re-rendering every scene. Branches preserve experiments instead of turning them into lost prompts.
Inspect evidence, not an invented quality score. narova judge examines the
encoded artifact against creator-authored assertions. It can measure timing,
motion, silence, captions, hierarchy, continuity evidence, and other observable
properties while keeping uncertainty explicit. It does not reduce creative work
to a universal score or automatically "fix" creative decisions.
Built for agents without being dependent on one. Humans get readable CLI
output. Agents can request the versioned narova.result/1 JSON protocol, with
stable operations, diagnostics, exit classes, and artifact records. Narova works
through an agent skill or directly from the CLI, and the project remains
ordinary local files either way.
What you can make
The system is not limited to one input or one output. Any of these are first-class starting points or scene materials:
- Explainers and social video
- Product launch films
- Real browser walkthroughs
- Repository and technical overviews
- Research and source-grounded videos
- Multi-speaker dialogue
- Silent motion pieces and marker-driven events
- HTML/CSS/SVG motion design
- Three.js/WebGL 3D and mixed compositing
- AI-generated clips through explicitly selected providers (Sora, Runway)
- Stock, original, and generated media combined in one timeline
- Platform presets and SRT/VTT delivery
Nothing above requires a particular renderer, voice vendor, or cloud service. Narova renders through either of its two local renderers, speaks through local TTS or an explicitly registered hosted provider, and treats AI clip generation as one optional source of scene media — not the product itself.
Try it — one command
With Node 18+ as the only download prerequisite, the demo builds a real narrated, captioned MP4 on your machine and leaves the project behind as a working reference:
npx @narova/narova demo
The first run shows a readiness checklist with live progress, then fetches what this machine is missing — a digest-verified ffmpeg (on pinned Linux platforms), the pinned local voice, the renderer engine, and the Python speech environment — into Narova user storage. No keys, no configuration, no decisions; nothing is installed on system paths. The completion report states the measured time-to-first-video and network bytes. Reference budget, advisory only: about a minute on a modern laptop with a typical broadband link (measured 2026-08-19: 47 s cold on macOS arm64, 3 s warm; the clean-machine Linux CI job prints its own measurement on every run). Re-running reuses everything.
On macOS, install ffmpeg yourself first (brew install ffmpeg) — Narova
auto-provisions it only where a digest-verified source is pinned.
Agent quickstart
Install the CLI and the agent skill, then ask your agent for the video in normal language:
npm install --global @narova/narova
npx skills add ammar-hasan/narova --skill narova -g
Narova supports different starting points:
- Idea: "Make a 45-second vertical explainer about why starting small makes habits easier to keep. Make it warm and practical, and show me a preview before rendering."
- Product page: "Turn this product page into a 30-second LinkedIn launch
video:
[product URL]. Lead with the user outcome and use the site's visual identity." - Product walkthrough: "Explore our demo account, then make a 45-second sales walkthrough that creates a project and shows the finished result. Narrate it, add word-synced captions and a CTA, and show me the preview."
- Research: "Turn this paper into a 60-second explainer:
[paper URL]. Separate the authors' findings from inference, cite the source on screen, and keep the language accessible." - Repository: "Read this repository and make a 45-second technical
overview:
[repository URL]. Explain what it does, show the architecture, and end with how to get started." - Script or dialogue: "Turn the script below into a fast two-host vertical reel. Keep the exchange natural, use distinct caption colors, and let the visuals change with each speaker."
The exact instruction the agent needs is: "Make a 45-second launch video from this product page. Show me a small proof of the visual direction before full production, then let me direct the result."
Direct CLI workflow
The CLI is available when you want to inspect or automate each step yourself:
narova init generated/myreel && cd generated/myreel
# complete the medium-neutral creative brief; keep each direction to a small proof
narova check # validate the config + estimate narration length
narova synth # makes narration + word timings
narova compose && narova shots --motion --proof # reject an invisible pilot
narova branch save proof-a --rationale "why this direction may serve the brief"
narova preview --detach # direct the film in HyperFrames Studio
narova build --release # fail-before-render final gate → out/video.mp4
narova judge # inspect intent vs the encoded result; read-only, scoreless
You need: Node 18+, plus ffmpeg and Python 3.10+ (the published package self-provisions the Python speech environment and, on pinned platforms, a digest-verified ffmpeg; a source checkout expects them on PATH).
Creative proofs and branches
For ambitious work, your agent turns medium-neutral creative intent into 2–3 small proof branches, renders their decisive states, records why each might work, and expands only the selected branch. You direct revisions in the same conversation; deterministic timelines, sentence and scene caching, and explicit branches keep bold exploration surgically editable.
narova branch save proof-a --rationale "why this direction may serve the brief"
# repeat for proof-b/proof-c; approve + restore one; record its proof identity
# in creative-brief.md, then expand only that config
narova branch compare proof-a proof-b # actual evidence; Narova chooses nothing
Proof bundles are bound to their originating project, so a same-named global branch cannot satisfy another project's final release gate. Saving a focused proof also preserves the actual encoded bytes plus one assertion-linked observation; comparing two or three verifies and displays the stored evidence in requested order but never ranks, recommends, selects, restores, renders, or mutates. Rejected and archived attempts remain inspectable creative memory; branch status is the creator's explicit decision.
Deterministic iteration and releases
Rebuilds are incremental and dependency-aware: narova build (and --release)
re-renders only the scenes whose audiovisual work actually changed, reuses the
rest, and re-places reused scenes when an earlier scene's duration shifts them.
Unchanged scenes cause zero renderer frame evaluation; one scene-referenced
asset edit invalidates only the scenes that reference it; an unused asset edit
invalidates nothing. The build prints what rebuilt, what reused, and why, plus
dirty-unit seconds and renderer invocation counts. Audio-only changes (bed/SFX
or a voice with unchanged timing) re-mux audio over reused spans without
re-rendering. If safe reuse cannot be proven, Narova rebuilds conservatively and
says why — it never serves a stale frame. The incremental result is
audiovisually equivalent to a forced-clean build (decoded frames, frame
counts/boundaries, audio/sync, captions, duration).
Authored motion keeps that locality when it uses the scope it actually needs:
attach one-scene JavaScript with scene.choreographyFile; reserve top-level
choreography for behavior that intentionally coordinates the full
composition. Global choreography remains unrestricted and valid, but an
isolated browser renderer conservatively uses whole-video reuse because it
cannot prove arbitrary project code is scene-local.
Revisions are recorded as changes in effective authored state. narova diff
reports the per-scene revision impact with predicted reuse and an honest render
estimate; narova history lists, annotates, and compares the append-only
project ledger; every successful base build binds a measured reuse record into
out/revisions.jsonl. Named releases (narova release save/list/restore/remove)
are content-hashed snapshots you can compare, restore, and remove.
Judge, assertions, and evidence
narova judge is a read-only rendered-evidence mirror. It inspects the existing
encoded video against creator-authored assertions — explicit requirements,
unusual hypotheses, deliberate violations, continuity, accessibility, brand,
factual constraints — and exposes measured motion, silence, timing, spatial
hierarchy, and uncertainty, mapped back to production state. It emits no
universal score (score: null), changes no project validity, mutates nothing,
calls no hosted model, and accesses no network. Stillness, silence, darkness,
and abrupt change may be deliberate; uncertainty is preferable to an
unevidenced defect.
narova judge --plan adds plural, unranked intervention options for each
assertion-linked divergence or uncertainty — always including keeping the work
unchanged — without selecting or executing one. One deliberately bounded repair
is available for missing or invalid caption sidecars (narova judge --repair),
which publishes only an isolated, unapproved proof-branch candidate; creative
findings remain creator decisions. None of these surfaces emits a universal
quality score or quietly changes current production.
See the exact assertion, judge, plan, and repair contracts in
skills/narova/references/cli.md.
Sources, assets, walkthroughs, and provenance
Source-grounded claims. Every factual claim in the narration must trace to
a source. Narova's check detects a supported class of numeric and superlative
claims and requires them to be ledged (claims.md); release checking fails
unledgered claims. Agents interpret selected sources; ingest handles two
bounded mechanical passes: an HTTP(S) page fetch with up to five images and an
optional browser screenshot, or explicitly selected physical pages from a
regular local PDF as PNG evidence plus available embedded text. PDF intake does
not follow links, execute actions, use OCR, interpret claims, or choose creative
material. These heuristics prove neither that every claim was detected nor that
a source is correct; for contested topics the ledger should preserve the major
relevant perspectives.
Assets and provenance. The small asset lifecycle stays explicit:
narova assets providers
narova assets search "home" --provider iconify --kind image --limit 5
narova assets acquire mdi:home --provider iconify --kind image \
--output assets/home.svg
narova assets download "https://cdn.example/clip.mp4" --output assets/clip.mp4 \
--origin stock --provider example --source-page "https://example/items/clip" \
--license CC-BY-4.0 --attribution "Creator / Example"
narova assets import assets/logo.svg --origin original
narova assets verify
narova assets credits --format youtube # or text|web|json
narova provenance # graded project trust report
narova provenance composes the evidence Narova already has into four read-only
sections: claim grounding, tracked media and rights buckets, AI generation, and
reproducibility. Every fact is labeled verified (artifact-backed), declared
(authored statement), or unknown; missing records stay visible instead of
becoming green checks. The report is advisory and offline. It does not prove
legal permission or exact used-asset closure, and it never changes the project.
Core owns every deterministic adapter: Wikimedia, Openverse, NASA, Internet
Archive, Iconify, Poly Haven, The Met, Cleveland Museum, Library of Congress,
Pexels, Pixabay, and Freesound. The first nine need no key; the other three are
optional and appear unavailable until their environment key is present. The
separate narova-stock-extensions skill is LLM-led discovery for long-tail
catalogues. Creative sourcing is not limited to the built-in catalogues: if an
agent finds a better asset through a browser, archive, or new source, it can use
assets download or assets import and preserve the same provenance record.
ingest, AI generate, and walkthrough capture register their outputs
automatically; builds consume local files only and never acquire media.
AI clips as scene material. When a project wants a generated shot, narova generate "<prompt>" asks an explicitly registered video companion to produce
a clip, then commits it to the project asset registry with a generation recipe,
so it participates in the same provenance, cache identity, and release evidence
as any other media. Sora lives in narova-openai; Runway lives in the separate
narova-runway skill; Google Veo lives in the separate narova-google skill.
Vendor APIs and credentials never enter core. This is an
optional scene input, never the product itself, and the network is used only
when generation is invoked.
Generated shots can also use a small creator-owned continuity plan in the existing project config. Name the characters, objects, or places that matter; select what one shot should keep or change; and optionally attach one image anchor when the chosen provider declares support:
continuity: {
entities: {
amina: { kind: "character", description: "Amina in a teal scarf" },
lantern: { kind: "object", description: "brass lantern with blue glass" },
},
shots: {
arrival: {
entities: ["amina", "lantern"],
keep: ["same scarf and lantern"],
change: ["Amina raises the lantern"],
// anchor: "assets/arrival-reference.png",
},
},
}
narova generate "Amina enters the observatory" \
--continuity arrival --output assets/arrival.mp4
Narova validates the selected context before paid work, fails rather than
silently dropping an unsupported anchor, and records the exact prompt,
continuity snapshot, and anchor identity in recipe version 3. Regeneration
retains it unless the author replaces it or uses --no-continuity. Narova does
not infer a world, choose style or camera, rank candidates, or claim that a
provider honored the reference in its pixels.
Real product walkthroughs. Explore a website/app semantically, record cursor-guided actions on narration beats, frame or full-bleed the real UI, then layer captions, callouts, branding, music, and SFX around it.
npm install -g agent-browser && agent-browser install # optional adapter
narova walkthrough explore onboarding # inspect real semantic controls
narova synth # establishes measured narration timing
narova walkthrough capture onboarding # explicit live action + WebM/evidence
narova preview --detach
narova shots --beats
narova build --reuse --release
Recipes prefer roles, labels, test ids, and visible text over brittle coordinates. Captures are invalidated when narration timing or actions change; body/theme/window/full presentation edits reuse them. Authentication belongs in a dedicated browser restore/profile, never a scripted password. See the full walkthrough contract.
Watch the complete 83-second narrated walkthrough generated by this workflow. Watch the voiced, captioned real-browser click proof.
Renderers and speech
Narova ships two free local renderers. HyperFrames is the default and
full-fidelity path: arbitrary scene HTML/CSS, the complete HyperFrames
component/effects surface, browser Studio, and captured walkthrough composition.
Narova No-Browser is the browserless path: it draws a provider-neutral
scene.visual tree with Skia and encodes it with FFmpeg. Both run on your
machine with no render service or fee.
narova renderers list
narova build --renderer no-browser
narova preview --renderer no-browser # writes out/preview-no-browser.mp4
See the exact renderer capability contract.
Local speech ships as built-in backends; optional hosted speech and video providers are separate, explicitly registered companions — never dependencies. Keep credentials in the provider's required environment variables, never in the config.
| Backend | Quality | Speed | Setup | Notes |
|---|---|---|---|---|
piper | good | fast | none (default) | small local voices |
xtts | higher | slow | narova-setup --xtts | ~1.9GB model, 58 speakers |
qwen | high | slow | narova-setup --qwen | ~1.2GB model, Apache 2.0, 9 speakers |
chatterbox | voice cloning | slowest | narova-setup --chatterbox | speaker = absolute path to a 10–20s recording; own venv, ~1GB model |
pockettts | listening unverified | model/machine dependent | narova-setup --pockettts | local CPU, own Python 3.12 runtime, 27 presets, seven languages; cloning needs full-model access |
narova providers add <provider-manifest.json>
narova providers doctor <name>
npx skills add ammar-hasan/narova --skill narova-elevenlabs -g
npx skills add ammar-hasan/narova --skill narova-openai -g
npx skills add ammar-hasan/narova --skill narova-runway -g
npx skills add ammar-hasan/narova --skill narova-google -g
npx skills add ammar-hasan/narova --skill narova-xiaomi -g
For authored 3D work that needs intentional subject/world representation or
specialist direction, install the independent
narova-3d-production companion:
npx skills add ammar-hasan/narova --skill narova-3d-production -g
It is a concise, high-freedom direction layer with conditional references. For work where gravity, collision, support, or rigid constraints carry the idea, it also includes a separately installed deterministic rigid-body baker that writes project-local time-indexed transforms. The baker is optional, adds no Narova core dependency or renderer behavior, and core Narova works identically without it.
Machine protocol
Agents are first-class API consumers. Every public operation honors --json
and returns exactly one versioned narova.result/1 envelope on stdout — no
prose to parse. The protocol provides a stable exit-status vocabulary
(success / operation-failure / usage-error / subject-non-pass), a
stable diagnostic-code registry, declared artifact records for paths the
operation created or replaced, and additive-only schema evolution within schema
major version 1. Redaction is a protocol property: known secrets are redacted
from the envelope and from captured child-process boundaries.
narova check --json
narova build --json
narova judge --json
The canonical agent loop is inspect → modify authoring source → validate →
preview → critique → build → perceive the encoded result → verify. See
AGENT_PROTOCOL.md for the full operation payloads,
diagnostic registry, and loop.
Architecture
creative-brief.md
│ 2–3 small proof branches → rendered evidence → select one
▼
reel.config.mjs
│
▼ synth Python makes the speech and the word timings.
│ Timings are scaled to match the real audio exactly.
▼ capture Optional: agent-browser records declared product actions
│ against measured narration anchors. Never runs in build.
▼ compose narova writes the selected local renderer project:
│ scene visuals, karaoke captions, reveals, one timeline.
▼ render HyperFrames or No-browser renders the mp4 with audio inside.
│
out/video.mp4
│
▼ judge read-only rendered evidence ↔ authored intent; no score or repair
out/, out/hf-*, and out/no-browser-* are build folders. Never edit them.
The config remains the render source of truth; the approved brief records why
the creative direction is ready to scale.
The scene script
A project is a folder with reel.config.mjs as its render source of truth. New
projects also include creative-brief.md; approve its pilot gate before
releasing a non-trivial production.
export default {
title: "My Reel",
renderer: "hyperframes", // default; or "no-browser"
size: "16:9", // "16:9" | "1:1" | "9:16"
safeLayout: true, // optional centering/gutters/max-width/caption reserve
assets: "assets", // copied into out/hf/assets/
voices: {
a: { backend: "piper", speaker: "en_US-ryan-high", color: "#2ee6d6", label: "host · A" },
b: { backend: "piper", speaker: "en_US-hfc_female-medium", color: "#ff7eb6", label: "host · B" },
},
provenance: { // optional authored declarations
script: { authorship: "mixed", note: "agent draft, human review" },
disclosure: "Contains AI-generated media",
},
assertions: [{ // optional creator-owned Video CI intent
id: "restrained-opening",
class: "creative-hypothesis",
expect: "The opening should feel restrained; only the cue reveal should move.",
origin: { kind: "agent-hypothesis", ref: "opening proof" },
scope: { scene: "title" },
observe: [
{ metric: "video.static_ratio", operator: "gte", value: 0.7 },
{ metric: "video.cut_count", operator: "lte", value: 1 },
],
riskyBecause: ["unconventional stillness"],
questions: ["Did unintended motion weaken the restraint?"],
related: { scene: "title", source: "reel.config.mjs", protected: ["camera rhythm"] },
}],
sceneState: [{ // optional hidden mechanical/spatial evidence
scene: "title", file: "evidence/title.state.json",
}], // bound to built video; never changes rendering
theme: { accent: "#2ee6d6", bg: "#080d16" }, // optional
timing: { gapSentence: 0.24, gapTurn: 0.44, lead: 0.16, tail: 0.58, tempo: 1.12 },
scenes: [
{
id: "title",
// For a generated clip with visibly synchronized dialogue, an agent can
// choose the preserved source performance instead of synthesizing `vo`:
// clip: "assets/title.mp4",
// dur: 8,
// clipAudio: {
// authority: "native", role: "dialogue",
// rationale: "The visible delivery requires lip sync.",
// wordTimings: "assets/title.words.json", // optional; one cue/vo turn
// },
vo: [ // what is SPOKEN, in order
{ who: "a", text: "This is narova." },
{ who: "b", text: "Scenes in, video out. Let's go." },
],
body: `<div class="s-title">
<h1 class="display reveal">narova</h1>
<p class="lede cue" data-cue="1">scenes in, video out</p>
</div>`,
},
],
}
The rules:
vois the spoken dialogue. Each turn is{ who, text }.- Direct clips remain visual-only unless
clipAudiorecords a choice. Useauthority: "native"when the source performance itself is authoritative (especially generated visible dialogue requiring lip sync), orauthority: "synthesis"to document a deliberate replacement. How the file was downloaded is not a decision rule. Native authority requiresclip, an explicitdur, and a non-empty rationale; native dialogue additionally requires the matchingvotranscript. Native audio plays once and any remaining scene time is silence. bodyis HTML for the screen.data-cue="1"means: stay hidden until turn 1 starts. Counting starts at 0.class="reveal"means: animate in when the scene starts.- You never set durations for spoken scenes — the real audio decides how long each scene is. Silent and some external-narration scenes use explicit authored/resolved durations, and named markers are another first-class timing source.
- Styling is optional. Set colors with
theme, or add a CSS file withtheme: { css: "theme.css" }. Do not useanimation: ... infinitein that CSS. The renderer jumps between frames, so looping animations break. - Put logos, images, and local fonts in
assets/; scene HTML and theme CSS reference them asassets/.... Inline SVG and small data URIs also work. Remote render-time files do not. - Word-level timing is estimated by default (distributed across the measured sentence duration) and becomes measured when the optional alignment path succeeds; captions and cue reveals follow the measured turn/sentence clock.
assertions describe what the creator intends to survive into the finished
artifact. Free-form expectations remain creator-owned prose; only explicit
observe probes are mechanically compared. Assertions do not change rendering,
cache identity, proof validity, or release eligibility.
Multi-video series
Use narova series pin <source> --episode <id> to keep different shared
revisions in fresh CI checkouts without tracking shared file copies in every
episode. Commit the catalog pin and series store; builds verify and materialize
its complete selected dependencies. See pinning and migration.
Courses, vlogs and drama can share voices, characters, pronunciation, theme/caption defaults,
selected local resources and creator-owned context. Episodes stay independent:
each retains its selected shared bytes, and later edits affect only explicit
adopters. Catalog relationships and authored handoffs never force render order.
Create/catalog the episode, then use narova series build <source> --episode <id>
to copy its selected shared inputs and build in one command. Later builds keep
that saved revision; --update-shared explicitly adopts current inputs and builds
only that episode. Local files and overrides stay its own. Ordinary build also
consumes a saved binding without reading the live series.
CI selects episodes independently: track shared originals, episode sources and
selection recipes, then run the combined command after checkout. Derived copies
need not be committed; ignore membership and binding together. To preserve an
older shared revision, commit membership plus the complete current binding/files.
In a reused workspace, request --update-shared to pick up current originals.
An episode can mix shared fonts, CSS and images with local footage/assets and local overrides. Theme/caption properties merge by key; a matching local voice/character ID replaces the entire shared record. Font files and custom CSS are selected resources with explicit episode references; shared theme defaults carry mode/tokens, not stylesheet files. See the guide's worked mixed example.
Start with the complete two-episode example. It needs a ready CLI/no-browser runtime and uses shared/local SVGs without voices, fonts, CSS or continuity settings. The ordinary workflow is:
# After creating the catalog and episode files in the example:
narova series build course --episode intro --resources logo
# Repeat with the same saved shared inputs.
narova series build course --episode intro --reuse
# Deliberately pick up edited shared originals for Intro only.
narova series build course --episode intro --update-shared --reuse
narova series --help
logo selects a catalog resource; the episode's scene reference applies the
retained file. See series authoring for
optional fonts/CSS, voice order, removals, continuity, restoration, exchange and
standalone detachment. Legacy series: {part,total} remains display metadata.
Narrated-series controls
Keep optional alignment settings in the project with
align: { engine: "faster-whisper", model: "base.en", partial: true }.
Explicit settings override environment defaults; alignment requires the chosen
optional engine. Hyphenated authored words can match split measured words.
Scene effects can follow speech rather than copied timestamps:
sfx: [{ scene: "title", file: "assets/chime.wav",
at: { sentence: 0, word: 2, offset: 0.05 },
start: 1.5, duration: 0.8, fadeIn: 0.05, fadeOut: 0.2, volume: 0.6 }],
Sentence and word indices start at zero within the selected scene. start
selects the source offset; duration and fades shape that selected interval.
These controls work with synthesized and external narration. For a scene with
custom typography, set captions: false on that scene: visual captions disappear,
while SRT/VTT exports and cue timing remain available. Zero-length word and
sentence cues are valid instants. Speech at tempo 1 retains its original speed,
and production bed/SFX mixes preserve stereo.
See the audio reference and choreography reference for details.
Product walkthroughs
Product demos add a driver-neutral walkthroughs recipe and point scenes at
it:
export default {
// voices, theme, …
walkthroughs: {
onboarding: {
url: "https://app.example.com/projects",
viewport: { w: 1440, h: 900 },
ready: { text: "New project" },
steps: [
{ at: { scene: "create", cue: 0, offset: 0.25 },
action: "click",
target: { role: "button", name: "New project" } },
{ at: { scene: "create", cue: 0, offset: 1.1 },
action: "type",
target: { label: "Project name" },
value: "Launch plan" },
],
},
},
scenes: [{
id: "create",
walkthrough: "onboarding", // or { id, layout: "full", fit: "cover" }
vo: [{ who: "a", text: "Create a project and give it a clear name." }],
body: `<p class="eyebrow reveal">From idea to workspace</p>`,
}],
}
Installation and reference
The two-part install
Narova has two parts: the CLI and the agent skill. Install the CLI first from the public npm package:
npm install --global @narova/narova
narova doctor
The npm package does not change agent skills. Releases from 0.31.1 onward
publish through npm Trusted Publishing with provenance linking the package to
this public repository and its release workflow. The manually bootstrapped
0.31.0 release has an npm registry signature but no provenance attestation.
Then install the skill for any agent that supports skills. If the CLI is missing or its version differs, the skill installs its exact matching published npm version before use:
npx skills add ammar-hasan/narova --skill narova -g
# check for updates: npx skills update narova -g (only when you're ready — upgrading replaces the skill files)
The CLI and skill are distributed separately, but the skill is authoritative
for compatibility: after a skill update, its next session verifies
narova --version and reconciles the global CLI to the exact pinned release.
Installing another CLI version manually does not change the skill; the next
skill session restores the skill's pinned version.
Update or remove
npm install --global @narova/narova@latest
Remove the CLI with narova-uninstall (it detects a custom install prefix
automatically; --purge-tools also removes the TTS venv, provisioned media
tools, and the voice cache — projects, media assets, and voice samples are
always kept). The skill is updated separately with npx skills update narova -g.
Commands
narova init <dir> new project
narova demo build the one-command sample film end to end
narova pack write a deterministic .narova project archive
narova open <archive> verify, inspect, or materialize an untrusted archive
narova remix <source> copy a local project/archive or public github: locator
narova ingest <url> bounded HTTP(S) source pass → sources.md/claims.md
narova ingest <pdf> --pages <1,3-5> selected local PDF evidence
narova check validate the config (fast, no side effects) + claim sniffing
narova plan compare config vs the last manifest; classify what changed
narova diff per-scene revision impact vs the latest recorded revision
narova history list/annotate/compare the append-only revision ledger
narova synth make the audio + word timings
narova walkthrough explore/capture/status narrated product demos
narova compose make the selected renderer project
narova captions rewrite SRT/VTT from existing timings
narova shots snapshot QA frames per scene, motion sample, or narration beat
narova build synth + compose + render -> out/video.mp4
narova preview HyperFrames Studio, or a no-browser draft MP4
narova preview --detach keep Studio alive; stop with preview --stop
narova judge inspect the encoded result against creative assertions
narova judge --plan add plural, unranked intervention options; change nothing
narova judge --repair create only a delegated caption-sidecar proof candidate
narova branch save optionally preserve a rendered proof for one assertion
narova branch compare compare 2–3 preserved proofs; no ranking or selection
narova branch set record the proof decision (approved/rejected/archived)
narova review observability suite (visual, timing, mix, and delivered-audio facts)
narova critique optional craft guidance; not a correctness gate
narova generate AI clip generation via an explicitly selected provider
narova voices list or download voices
narova providers add/list/remove/doctor external speech/video providers
narova renderers list/doctor the two bundled local renderers
narova assets import/download/search/acquire/verify/credits
narova provenance graded project trust report (verified/declared/unknown)
narova release save/list/restore/remove content-hashed named releases
narova doctor check your machine
Commands find the project from any folder inside it (they walk up to the
nearest reel.config.*). check also prints an estimated narration length, so
a target duration can be tuned before any audio exists.
Useful flags: --backend <built-in-or-registered-provider>,
--renderer hyperframes|no-browser, --reuse (keep old audio),
--tempo, --size, --fps, --quality draft|standard|high,
--video <file> (judge only), --deliverables (per-platform export presets
via scale+pad), --variants, --json (machine protocol). See
skills/narova/references/cli.md for the
full list.
Repo layout
tool/ CLI package: installer, Node/Python runtime, vendors, tests
skills/narova/ agent instructions and references
skills/narova-*/ optional production, sourcing, and voice companions
docs/ the marketing site (GitHub Pages) + /changelog + /explore
docs/explore/projects/ local verification mirrors of reviewed Explore projects
docs/public-assets.json pinned mapping to the CC0 Narova asset repository
CHANGELOG.md every notable change, version by version
AGENT_PROTOCOL.md versioned JSON envelopes, exit codes, and the agent loop
VISION.md the product vision, mapped to where each point is implemented
LEARNINGS.md non-normative implementation notes for public maintainers
Run everything with npm test, or test the CLI independently with
npm test --prefix tool.
Release version contract
The root package.json is the only canonical Narova version. Prepare a release
on a branch with npm version patch|minor|major --no-git-tag-version; the npm
version lifecycle runs version:sync and propagates that value to the CLI
package, lockfile, skill metadata, exact npm compatibility pin, badge, spec,
agent protocol, and website markers. Add the dated changelog entry, then require
npm run release:check and CI before merging.
After the release PR lands on main, tag that merge as v<version>. The tag
workflow rejects version drift and off-main tags, then publishes the matching
npm package through Trusted Publishing. skills.sh reads the skill from GitHub;
users receive it with npx skills update narova -g, and the updated skill
reconciles the CLI to its exact pinned npm release before use.
License
Apache-2.0 — see LICENSE. Changes are tracked in CHANGELOG.md and on the changelog page.
First-party Explore projects and demo media are published separately under CC0 1.0 for unrestricted reuse; no attribution or proof of use is required.
Narration controls and portable speech
Use turn pauseAfter for authored silence, turn captions: false to hide visual
words while retaining subtitles, and root mix.loudness for optional final mix
normalization. Literal word selectors can anchor effects and choreography by
text plus occurrence. narova voice-cache export/import carries selected sentence
WAVs for matching keyless builds. See the audio guide.
The ElevenLabs companion guide
covers v4/v4 turbo, phrasing context and optional hosted MCP authoring.
Script-to-speech checks
narova review --speech reports per-turn transcripts and dropped, added or
replaced words from existing synthesized takes. Optional root
speech: { check: 'warn', retakes: 1 } checks builds and re-synthesizes only
mismatched turns with the next take nonce. Use check: 'fail' to stop before
rendering when speech differs or recognition is unavailable. Warn retains the
latest completed candidate when recognition becomes unavailable. Explicit checks
require current take records; replacing selected local model bytes with a positive
retake budget starts fresh selection while reusing eligible sentence audio. Review remains
advisory and read-only; optional local ASR tools are required. Transcripts can
mishear, so audition flagged turns. See the speech check guide.
Pocket TTS
Pocket TTS is a built-in optional local
CPU backend alongside Piper, XTTS, Qwen and Chatterbox. It offers 27 presets,
seven languages, reference cloning and saved voice states. Run
narova-setup --pockettts, then select backend: 'pockettts' per voice or
--backend pockettts. No separate skill or provider registration is required.
Setup uses an isolated Python 3.12 environment and leaves other backends intact.
Pocket TTS is included in Narova 0.52.0 and later.
Full-model access is required for cloning; it never silently switches to presets.
narova voices list --backend pockettts and narova pockettts catalog need no
Pocket runtime or downloads. narova pockettts doctor explicitly checks the
selected model; narova pockettts export-voice --speaker alba --output alba.safetensors
saves a compatible state. Narova retains timing, captions, processing and rendering.
Model helpers show progress and default to a 120-second deadline; set
NAROVA_POCKETTTS_TIMEOUT for slower acquisition. Failed exports preserve the
existing state file, and catalog metadata identifies preview models.
Pocket and external voices can declare
providerFiles: { voiceState: 'assets/voice.safetensors' }. Core resolves and
hashes files and inspects the Pocket runtime profile before reuse; manifests and
sentence identities carry that evidence. See the
Pocket configuration guide.
Pronunciation without changing captions
Keep the real spelling in each turn's text. Add an explicit root dictionary
for speech input on any backend, including Pocket TTS:
pronounce: { 'CLAUDE.md': 'Claude Em Dee', 'Claude Code': 'Clawd Code' },
Captions, SRT/VTT and word cues retain CLAUDE.md; the voice receives Claude Em Dee. Matching is literal and case sensitive, outside letters, combining marks,
numbers and underscores. The longest matching entry wins; replacements do not
trigger other replacements. Clean sentences are split first, so replacements
cannot change sentence/cue ownership or span sentence boundaries. Existing
external-only synthesisText still selects the provider input first; the map
then applies to its sentences (or clean text after a sentence-count fallback).
Supplied external/native audio is unchanged. Empty/unused maps retain speech
reuse; an effective change replaces affected sentence keys.
A speech check records clean expectedText and changed spokenText, compares
against the spoken form, and keeps the raw recognizer transcript. ASR may write
an applied term as its clean spelling, such as Claude MD; only clean/spoken
pairs actually applied to that turn are accepted as spelling equivalents.
Recognition remains uncertain evidence; audition flagged turns. Alignment still
uses clean caption tokens and may retain estimates when the spoken words differ.
A series catalog can put the same dictionary in defaults.pronounce. Episodes
inherit its frozen selection, override individual keys in their own pronounce,
and remove an inherited literal key with
seriesOverrides: { remove: { pronounce: ['CLAUDE.md'] } }. Empty episode maps
inherit; removal is explicit. Repin/adopt to change existing episodes; detach
retains the effective ordinary map. No runtime dictionary service is needed.