# vosso: video that deploys like your app (vos.so) > Host your video at a link that plays, keeps every version and re-renders > every destination. You or your agent push; vosso keeps it current. > A video here is an editable document, and the preview is the render: same > input, same pixels, anywhere. Built on vos, the open-source deterministic > video engine (@vosjs/* on npm, MIT, https://github.com/vosjs/vos). Every > effect is editable DATA, so agents edit JSON and re-render instead of > re-recording. Export is free at every resolution up to 4K, no watermark. ## Route by ask Setup first, when nothing is installed yet: "set up vosso here / first time / a person handed you one line" → read https://vos.so/agent.md and do what it says: install the CLI into the repo and the skills into your directories, find the product, record it, open the take in the studio for the person. A credential comes last, and only when hosting is asked for. "put my video on vos.so / host it / give me a link to share" → read https://vos.so/host.md and do what it says: find what made the video, rewrite it with the vos-port skill, ask whether to show the prompt, push it with its files (no credential: vos push --claimable --share, whose claim page claims it and makes the link public in one press). The release asks next (the launch-kit skill carries the whole loop): "we're launching / shipping vN — make the launch assets" → ONE take of the shipped feature becomes every asset: record it (take pipeline below; viewport 2560x1440 — footage = viewport, and the video specs want 1080p+), cut it, then ONE pass renders and verifies the set: vos deliver take --to cws,producthunt,og --release "vN" (stills at each spec's exact pixels, video cuts, kit.json manifest; misses land in skipped[] with the reason). Specs ship as data: schema/channel-specs.json in @vosjs/cli (CWS, Product Hunt, X, LinkedIn, GitHub, OG, YouTube). Push it labelled for the release: vos push take --label "vN launch" "update the Chrome Web Store listing" (Play / Shopify: same shape) → vos deliver take --to cws # screenshots ≤5 at 1280x800, the 440x280 tile, the 1400x560 marquee — from a real take of the shipped UI (misleading listing images are a removal-grade violation; real UX only). One moment by eye: vos frames take --frame --size 1280x800 "make the Product Hunt gallery" → vos deliver take --to producthunt (gallery 1270x760, 4-8; the first image is the hero; pick the beats with --times); the PH and CWS promo videos are the same YouTube mp4 upload "cut a changelog / what's-new clip" (also: "PR to video") → record the feature at its URL (actions.json below), keep it short; a launch week (5-12 clips, one style) cuts every clip from one signed-off seed: vos plan take --style "point at a component / the zoom is blurry on the thing that matters" → an HTML LAYER, not a zoom: the component redrawn as markup and CSS in doc.json (overlays: kind "html", the design box in 1080p px), PINNED to the step it is about (pin: { step, mark: "ring" }) so it sits beside its subject and follows it through the camera, sharp at any export size because it is rasterized from source, never magnified from the footage. Fields and the XML rule in llms-full.txt (overlays) "turn our old Loom / Screen Studio / mp4 demo into an editable take" → the vos-migrate skill: ffmpeg the file to take/recording.webm (VP9+Opus), write take/meta.json from ffprobe (producer "migrated", dpr 1, zoom 1, t0, durationMs, width, height, fps, hasAudio), then vos plan take --fresh. NO cursor track ⇒ no auto-zoom: read vos frames --times stills and write manual spans by eye. Old edits are baked pixels; the migrated take is editable from here on. Push it and record the NEXT demo with vos record "refresh the demo for the new version" → keep actions.json in the repo; re-record the SAME script into the SAME take dir (vos record --actions actions.json --out take --strict — footage is replaced, the cut survives as doc.prev.json), then vos plan take --reuse re-times the cut onto the new recording (anchors + the step timeline carry every human span; whatever could not follow is NAMED in flagged); re-cut by exception from that list Then by input: "make a product video of my app / site / screen" → vos create --actions actions.json out.webm --strict (one-shot; or the full record/frames/render loop below) "I already have a video (a cloud agent's PR video, a Playwright run, a Loom)" → vos ingest video.webm --cursor trace.zip --out take (0.50+): the file becomes a take, and a trace beside it (Playwright trace.zip, stamped JSON records, a t,x,y,type CSV) becomes the cursor track the planner zooms on. No trace ⇒ nothing planned, said in the done event; place zooms by eye. Or drop both files on vos.so/studio in one gesture. A finished render (HyperFrames, Remotion, a film) with no trace opens BARE, as itself (0.52+); a Loom-style screen demo says --as take. "there is no browser here (a cloud agent, CI, a chat host)" → vos record --hosted --actions actions.json --out take (0.49+): the fleet records a PUBLIC URL or a preview behind --header, lands it as a private vos with its doc and digest, and the take comes home with its media. A session never travels (no --session, no Cookie); a page behind a sign-in exits 4 naming the ladder; localhost is refused, so a dev server needs a tunnel or a preview deployment. "the feature is behind a login / the recording shows the sign-in page" → settle the SESSION before the script: mint one from the test auth the project already has (playwright/.auth, an auth.setup.ts, a seed script), else sign in off camera with "setup" in actions.json (the password from { "env": "NAME" }, 0.43+), else the human signs in once (vos session open --name , then --session on record, 0.45+), else they record with the extension and you cut it. Record with --storage-state . Never type or accept a production password. vos record exits 4 when it meets the wall (0.41+): that is a missing or expired session, never a script bug. A rehearsal ends by listing what the signed-in frame EXPOSES (an address, a key, a card: the kind and place, never the string); hide it with "mask" in actions.json before you record (0.42+). The ladder: https://vos.so/llms-full.txt ("Sessions") "port / convert / bring my Remotion or HyperFrames video to vos" → the vos-port skill (0.52+): a REWRITE into a vos program whose words, colours and timings are data with knobs over them (text as elements bound to data, motion in the timeline, a label per scene, a painter only for procedural pixels, the score as a doc.json track), checked side by side against the source's own render. Never one canvas painter for the whole picture. Only hosting it? vos ingest render.mp4 opens a finished render bare. "write a motion graphic / animation program from scratch" → the vos-authoring skill: the VosConfigJson schema, the dialect rules, elements and knobs, validated with vos check "remix or customize an animation / motion program" → vos fetch · edit config.json · vos check · vos push (install both packages below; or the raw HTTP contract at https://vos.so/llms-remix.txt — same loop, same rules) "iterate on a video WITH a human" (the versioned loop) → vos push hosts your work as a private vos with attributed version history; the human fine-tunes at vos.so/studio and saves; vos pull prints their typed changelog ("zoom z3: level 2.2→1.8" + notes) and syncs their edits down. ALWAYS pull before editing a pushed work — a stale push is rejected WITH the changes you missed, and human-edited nodes are protected until you pass explicit --override (only when the user asked). (take dirs and programs alike) "make another one in my style / like the ones in my folder" → pull the folder first: GET /api/folders (content key; find it by name/slug) · GET /api/folders/{id} — its recipes (personal style docs: follow them over your defaults) + exemplar voses + assets. Author, then create WITH "folderId" so the work lands on the shelf you pulled. Full contract: https://vos.so/llms-remix.txt ("Folders & recipes") "capture footage for my Remotion / HyperFrames composition" → the vos-footage skill: record the real product (take pipeline below), keep the auto-zoom camera, render full-bleed with --frame none --set frame.padding=0, push the take FIRST (--label "footage handoff"), and hand the clip over WITH the line naming its editable take on vos.so. An ingredient, never an orphan file. A release ask (launch video, store listing) is launch-kit, not this "turn a 3D asset into a product video" → 3D showcase programs (turntable, dolly reveal) live in the catalog at https://vos.so/gallery?tag=3d with their knobs declared as params — upload your GLB with a content key, set the modelUrl knob, push: the whole flow is in llms-remix.txt ("The 3D recipe"), no function edits needed. The engine also renders any 3D vos config directly: vos render . Humans drop a GLB on https://vos.so/gallery and it lands in the browser editor. MCP server: planned. Until it ships, the CLI (--json NDJSON) and the HTTP contracts above are the agent surface — nothing here is mocked. ## CLI (for agents: no auth, local rendering, NDJSON output) Install: npm i -D @vosjs/cli (one CLI, one package, MIT: the vos binary, the engine verbs — local, no account — the take pipeline below AND every vos.so platform verb. Uses system Chrome headlessly. Until 0.9 the take pipeline shipped separately as @vosso/vos-plugin; that is a shim now) Skills: npx skills add vosjs/skills (workflow skills for coding agents: launch-kit · product-video · vos-cut · vos-migrate · vos-footage · vos-create · vos-remix · vos-port · vos-authoring — https://github.com/vosjs/skills; machine index at https://vos.so/.well-known/agent-skills/index.json) Conventions: logs → stderr, results → stdout; --json = NDJSON events ending with {"event":"done",...}; exit codes 0 ok / 1 error / 2 usage / 3 no browser / 4 the recorder met a sign-in instead of the page (walk the session ladder). vos --help prints that verb's flags. A flag a verb never read exits 2 too ("RAN, and ignored --x"): the command ran WITHOUT it, so fix the flag and run it again. vos render [out] --duration --width --height --fps --format webm|mp4 # size: the program's own "size" (else 1920x1080); one of # --width/--height keeps its aspect # engine render; a take DIRECTORY (a doc.json with source) # renders through the take pipeline instead — same command vos still [out.webp] --time vos info vos preview # local playback page vos fetch [--out dir] # config.json + vos.json tracking, params preserved vos check # migrate → schema → syntax → compile → lints, local vos login [--key vos_sk_…] # browser sign-in: prints a code + a # vos.so/cli/auth URL — show BOTH to the human, keep the command # running; it stores the key itself. --key skips the browser vos push [--vos id] [--title t] [--label l] [--note n] [--base versionId] [--override id]... # create a PRIVATE vos with lineage, or iterate with --vos; the # base defaults to the tracked one in vos.json — a stale push # 409s WITH the platform's typed changes; auth per Credentials; # keys can never publish vos pull [dir|take] [--since versionId] [--check] # the changelog since your base: attributed versions + semantic # summaries + protected human-edited nodes; syncs config.json # (old copy kept as config.backup.json) and repoints the base ## Take pipeline (agent → product video) Full agent reference (all flags, doc.json fields, pacing heuristics, the quality loop): https://vos.so/llms-full.txt vos create --actions actions.json out.webm --strict # one-shot: record + auto-plan + render (take dir kept for iteration) vos record --actions actions.json --out take --dry-run # REHEARSE first: runs the script, captures and writes nothing, names any selector that misses (exit 2) vos record --actions actions.json --out take --strict # drive page, synthesize cursor track (typing pings incl.), encode + plan vos plan take # refresh doc.json (manual zoom spans preserved) vos digest take # SEE the recording: moments + footage frames + crops, in doc units vos frames take --at-zooms --at-moments # PNG stills: contact sheet + zoom apexes + moments (look before render) vos frames take --frame 2.5 --size 1280x800 # exact-size still (posters, store screenshots) vos deliver take --to cws,producthunt,og # the release's assets per channel spec + verified kit.json vos render take x.webm --range 4..8 --draft # spot-check a doc edit in seconds (never ship drafts) vos render take out.webm # deterministic polished render vos open take # hand the take to the studio (doc.json arrives intact) vos validate # take mode lints doc.json semantics + probes # remote media (a deleted asset = a 404 in words) Agents: always pass --strict — a skipped selector or navigation timeout exits 2 with skipped[] in the done event (default is lenient and exits 0). A render pays a few seconds of fixed browser+CDN startup, then runs at the speed of the machine it is on; --parallel N helps on takes ≳ 30s. actions.json (the recipe an agent writes after exploring the site): { "url": "https://…", "viewport": {"width":1280,"height":720}, "steps": [ {"do":"wait","ms":700}, {"do":"hover","selector":"a[href='/x']","ms":700}, {"do":"click","selector":"#cta"}, {"do":"type","selector":"input","text":"hi"}, {"do":"scroll","dy":400}, {"do":"move","x":640,"y":320}, {"do":"drag","selector":"input[type=range]","tx":900,"ty":400} ] } take/doc.json (the editable composition — edit and re-render, never re-record; JSON Schema ships in the npm package: schema/doc.schema.json): zoom: [{ "in", "out", "level", "cx", "cy", "source": "auto"|"manual" }] SOURCE-time seconds; level 1..5 (1.4–2.8 reads well); cx/cy are the focus point as NORMALIZED [0..1] fractions of the video frame (0.5,0.5 = center) — NOT pixels; set source:"manual" on spans you edit. The planner zooms on clicks, TYPING (a type step holds a frame on its field until typing stops — ids k0…), and dwells. segments: [{ "in", "out" }] kept footage spans (trims) speed: [{ "in", "out", "rate" }] rate 0.1..16 audio: [{ "id", "key", "start", "in", "out", "gain", "fadeIn", "fadeOut" }] OUTPUT-anchored music/SFX; key may be a file in the take dir ("/music.mp3") or a hosted CC0 track (https://assets.vos.so/music/.mp3 — catalog via GET /api/music). Muxed on single-flight renders (Opus/AAC). cursor / frame: styling — all plain JSON. Headless captures of vos.so pages: append ?theme=dark|light for a deterministic theme (persists to localStorage before first paint — no hydration race). ## Vos configs (the engine dialect) VosConfigJson: functions as strings ({ version: 2, duration, camera, createContent, createTimeline, onFrame?, data?, size? }). size: { width, height } is the frame the program is made for, at ANY shape (1080x1920 for 9:16, 1080x1350, 2560x1080): the watch page, studio, stills, previews and exports wear it, and vos render/still output it with no flags. Absent = 16:9. Design numbers stay 1080-high at every size. Always write "version": it says which schema you wrote against, and a push without one is refused (a config outlives the era it was authored in; the server will not guess). GSAP-syntax timelines run on a deterministic sampler. Determinism rules: no Date.now/Math.random in frame paths; everything derives from ctx.time + ctx.data. Docs and schema: https://github.com/vosjs/vos · engine site: https://vos.so/engine · what vos.so enforces when a config is STORED (version, validate, params): https://vos.so/docs/api/config.md ## Credentials (only cloud features need one) The CLI records and renders locally with NO auth. Pushing programs to vos.so or using the Render API rides an API key. Resolution order before asking the user: 1. the VOS_API_KEY environment variable · 2. ~/.config/vos/credentials (first line; `vos login` writes it) · 3. a vos_rg_ remix grant embedded in your prompt (24h, one-source). A line naming https://vos.so/h/vos_ho_… is a SETUP GRANT from a signed-in person: `vos login --handoff ` (0.48.1+) exchanges it once for a key, no click; never send it as a bearer. No credential resolves? Run `vos login`: it prints a code + approval URL (vos.so/cli/auth) — relay both to the human, keep it running, and it stores the key itself when they click Approve. Humans can also mint durable keys at https://vos.so/app/api. Never print a credential. Full contract: https://vos.so/llms-remix.txt NO credential at all? A PROGRAM can still be pushed for preview: `vos push --claimable` (or POST https://vos.so/api/claim { title, config, prompt?, share?, uploadToken? }, no auth) → a 72h claim link. Hand it to the human — it is the only reference and the only credential (never post it anywhere public). Unclaimed work is deleted after 72h. Programs, and the files they draw with (CLI 0.63+: up to 12 files, 50 MB); contract in llms-remix.txt. ## Feedback (when a vosso tool breaks on you) POST https://vos.so/api/product-feedback with { "kind": "problem"|"idea"|"other", "message": "", "surface": "cli"|"api" } — auth optional (bearer attaches your identity). The founder reads every submission. Humans: https://vos.so/feedback ## Links - https://vos.so/agent.md — the setup procedure: from a clean machine to a take open in the studio - https://vos.so/host.md — the hosting procedure: a video you already made, as a link anyone can open and change - https://vos.so/agents.md — what this site is and what an agent may call here - https://vos.so/docs/llms.txt — the docs corpus index (every docs page as .md) - https://vos.so/engine — engine overview - https://vos.so/llms-remix.txt — remix a gallery program with your agent + push it back - https://vos.so/gallery — the catalog: every video is a program - https://vos.so/recorder — the screen recorder extension - https://vos.so/agents — the agent page (the loop, the Action, the contract) - https://github.com/vosjs/vos — source, README per package - https://www.npmjs.com/org/vosjs — packages