AI agents: fetch the documentation index at llms.txt. Markdown versions are available by appending .md to any page URL, including this page's markdown.
Security
How vs handles credentials, manifests, costs, and ambiguous paid requests.
Reporting a vulnerability
Report security issues privately through GitHub's private vulnerability reporting rather than opening a public issue. Expect a first reply within about a week.
Credentials
vs talks to paid generation APIs on your behalf.
Keys are read from the environment only. ARK_API_KEY and the optional GEMINI_API_KEY, ELEVENLABS_API_KEY, ELEVENLABS_VOICE_ID, and MINIMAX_API_KEY are loaded from .env or the process environment. They are never written to a manifest, log line, or error message. .env is gitignored; .env.example is the canonical list of names.
Manifests are designed to be committed, and are scrubbed for that. Each film keeps a tasks.json recording task ids, parameters, and status so a generation resumes on any machine. It deliberately does not retain the provider's signed result URL once a clip is downloaded — those URLs expire in about 24 hours and carry the provider's access key id in the query string.
Do not paste an unredacted tasks.json into a public issue.
Generated media
Generated video is append-only by default. Every take, render, animatic, upscale, and share export gets a numbered path. Failed retakes do not replace the manifest's selected successful revision. Explicit output paths refuse to replace an existing video.
Generated media is gitignored by default. films/** ignores video, audio, and image files, so a reference photograph or voice recording cannot be committed by accident.
Costs as a safety property
A misconfigured shot list can spend real money quickly.
--dry-runmakes no network callsvs generateasks for confirmation with a cost estimate--max-costrefuses a run whose estimate exceeds your ceiling
Estimates are guardrails, not guarantees. Where a shot binds a reference video whose billed duration is unknown up front, the estimate is a range and the ceiling is enforced against its top.
Ambiguous paid requests
Every POST creates billable work. A create-task request that fails without an answer (dropped socket, gateway 5xx) is not retried — it fails with task_uncertain. vs generate records the attempt in the manifest before it submits.
When you see task_uncertain, or a shot the tool refuses to resubmit:
- Check the provider's console for a task created around that time
- If one exists, let it finish and re-run the same command — it re-attaches
- Only if none exists, pass
--forceto submit again
Passing --force in that state accepts the risk of paying twice. Do step 1 first.
Scope
This is a local CLI. It has no server, no telemetry, and no network calls beyond the generation APIs you configure and the result downloads they hand back.