Vozo Project
CLI prerequisite
Requires the official vozo-cli from npm @vozoai/cli (source: github.com/vozoai/cli). Install with npm install -g @vozoai/cli or npx @vozoai/cli@latest install. Do not install from third-party mirrors. Auth is handled by vozo-auth.
What is Vozo / what can this CLI do (unified pitch)
When the user asks anything like "what are you / what can you do / what is this / what can the CLI do / introduce Vozo", answer with the following canonical pitch (translate it into the user's language, but keep product names in English):
Vozo (vozo.ai) is an AI video platform for taking one video to every language and audience. Vozo CLI brings its four core tools into your terminal and agent workflows:
- Translate & Dub — translate a video (or audio) and re-voice it with AI voice cloning that keeps the original speakers' voices.
- Translate Subtitles — generate translated subtitles for a video.
- Visual Translate — translate the on-screen text burned into the video frames.
- Lip Sync — re-sync the speakers' lips to match new audio (including dubbed audio from Translate & Dub).
From the CLI you can create projects from local files, folders, or video URLs (batch supported), track processing, and export/download the results (videos, audio tracks, subtitles). Fine-grained editing — fixing translations, changing voices, redubbing — happens in the Vozo web editor: every project comes with a link you can open anytime.
Keep the pitch to this scope. Do not promise features the CLI does not have (no video generation, no talking photo, no editing from the CLI), and do not enumerate internal flags in the pitch.
Product Naming
Use Vozo website product names in user-facing text. Keep CLI command paths unchanged:
| Product |
CLI |
| Translate & Dub |
project translate_dub |
| Translate Subtitles |
project translate_subtitles |
| Visual Translate |
project visual_translate |
| Lip Sync |
project lipsync |
Write "Translate & Dub" with the ampersand — for video and audio alike; never "Translate dub" / "Translate Dub" without &.
"Vozo" is a brand name — never translate, transliterate, or localize it. Always keep it exactly as Vozo (capital V) in every language and in all user-facing text, summaries, and messages.
When to Use This Skill
- Create projects from local folder / files / URL for dub, subtitles, visual translate, or lipsync.
- Create or find dashboard folders (
project folder create / folder list / folder search) and create projects inside them with --folder.
- Run create → poll → export (if needed) → download for any single tool.
- Chain multiple tools (user specifies order, or you propose a plan).
- Create many languages at once by repeating create with different
--target-language (not “translate to more” on one project).
- Bulk download after listing/searching with filters (folder, kind, date, language, title).
- Give users project links (
webUrl) and open so they can edit on the web.
Preferred Commands
vozo-cli auth status | points | membership
vozo-cli project list | search | folder list | folder create | folder search | delete
vozo-cli project <tool> create | get | open | export | download
<tool> = translate_dub | translate_subtitles | visual_translate | lipsync
Core Workflow
1. Always start with auth
vozo-cli auth status — if not signed in, use vozo-auth / auth login.
- Before batch create or expensive chains:
auth points + auth membership.
2. Single-tool: create → download
For each project, only continue past create/poll when the user explicitly asked for export/download:
- Create with the right
project <tool> create flags.
- Poll
project <tool> get <id> until the processing field is false (or status is failed). Do not interpret status strings yourself — processing already covers project status, sub-task, and export in-flight states. Field path: get stdout nests everything under a top-level project key — { "project": { ..., "processing": <bool>, "status": "...", "errorCode": <string|null>, "errorMessage": <string|null> } } — so read project.processing (e.g. jq -e '.project.processing'), never the top level. If extraction returns null/missing, that is a script error: abort the poll loop instead of treating it as "still processing". When the status reports a failure, summarize with project.errorCode and project.errorMessage (CLI maps these to web-aligned copy).
- Export
project <tool> export <id> when a media artifact is missing — only if the user asked to export or download outputs. Export checks for an existing download URL first: if one is present it returns status: "already_exported" with downloadUrl and does not re-export; otherwise it returns status: "started". Treat already_exported as success (artifact ready) — not a failure or skip-error.
- Download each requested artifact with
--output — only when the user asked for files on disk. Pass a directory per project (trailing /) so files get the same product names as web downloads (e.g. {title}_{language}_translated.mp4, {title}_{language}_subtitles.srt); only pass a file path when the user explicitly asked for a custom name.
- Share
webUrl from create/get. Whenever you hand out a project link, tell the user (especially first-time users) that they can open it to review and edit the result — fix translations, change voices, redub — if they are not satisfied; project <tool> open <id> opens it directly.
- When processing finishes (polling ends), proactively tell the user and ask whether they want the outputs downloaded (unless they already opted in/out at plan time). Offering is required; silently downloading is forbidden (§3.2), and silently stopping at "done" with no next step is poor service.
2.5. Long-running polling should move to the background
When the user asks for an end-to-end flow such as upload/create → wait → export → download, do not keep the foreground agent blocked on dense polling for long processing jobs.
Rules:
- After
create / export, return quickly with the accepted project id, kind, webUrl, current status, and the planned next step.
- If the environment supports background work, move the repeated
get polling to the background and resume the foreground only when:
- the project is ready for
export
- the export is ready for
download
- the project fails
- While polling runs in the background, the foreground response should stay concise:
- what has started
- which ids are being watched
- where outputs will be downloaded
- If the environment does not support true background execution, do not busy-wait in the foreground. Instead:
- do sparse polling only when useful
- return control to the user quickly
- tell the user the current status and the exact follow-up command to resume
- For batch jobs, background polling should track each project independently and only surface projects that changed state or need the next action.
Foreground waiting is only acceptable for short checks. Long processing and export waits should be treated as background watch tasks whenever possible.
3. Present plans before writes
Never run create — single or batch — without first showing the resolved parameters and getting explicit confirmation. This applies even when the user's request already sounds fully specified (e.g. "dub this video to English"); "show the plan" means restating the exact resolved values back to the user, not just silently proceeding because you think you understood them.
Before any create (single item or batch) or bulk download, show a plan that is concrete enough for the user to validate the exact work that is about to happen.
Use the full checklist in references/create-plan-checklist.md — do not improvise a shorter summary. Present every applicable setting with its resolved value, including defaults and batch-unsupported rows.
How to show the plan (important):
- Use semantic, user-facing labels (Product, Original language, Target language, Voice model, Speakers, …), not a bare dump of
--original-language, --target-language, --dub-preference.
- Put language/product meaning first; add the CLI code in parentheses when useful — e.g.
Target language: English (en), Voice model: VoiceNATIVE.
- Prefer product names: Translate & Dub, Translate Subtitles, Visual Translate, Lip Sync.
- Still cover every setting the checklist requires — semantic wording must not drop fields.
Every setting that applies must appear with its resolved value, including:
- values you will pass explicitly
- settings omitted from the command but covered by a CLI default (write the default in plain language, e.g.
Original language: Auto-detect, Voice model: Auto)
- settings not supported for the chosen source mode (write
not supported (batch) instead of hiding the row)
At minimum, always include:
- product, source type, and source path / URL / folder (local vs dashboard folder)
- target language (label + code; use locale tags like
zh-HK / en-AU when a region/accent is needed), original language when relevant
- dashboard folder and project title (or
none / auto from filename)
- for Translate & Dub: every voice/subtitle/alignment setting (voice model, speakers, burn-in subtitles, remove original subs, auto-align, proofread before dubbing, prompt, glossary, custom subtitle file + usage)
- for Translate Subtitles: subtitle display mode, remove original subs, prompt, glossary, custom subtitle file
- for Visual Translate: original language, font choice
- for Lip Sync: source mode and face mode (
--face-mode is required; ask if missing — do not default to single)
- whether the user wants the result auto-downloaded when processing finishes — offer it here once; a "yes" in the plan confirmation counts as the explicit download request required by §3.2
- for batch: estimated project count, and whether it is a single-language batch or repeated per language
- estimated points (label as estimate; formulas in
references/limits.md / checklist) plus available balance from auth points when known
- output / follow-up expectations (
webUrl, whether export will be needed, which artifacts will be downloaded)
- when summarizing languages for users, prefer human labels (
English, Chinese (Hong Kong)); keep codes for the actual create command. For create, pass locale via --target-language tags like zh-HK when a region/accent is needed
- quota warnings (points, Studio for batch, membership expiry)
- which steps are web-only (fine-tuning text, redub)
Incomplete plans are invalid. If you only list “target language + source file” and skip defaults the CLI will apply, the user cannot truly confirm the job. Stop and expand the plan before asking for confirmation.
Wait for explicit user confirmation before running create (single or batch) or a bulk download. A one-word request ("yes" / "go" / "confirm") after you've shown the plan counts as confirmation; a request that jumps straight to naming the action without ever seeing the resolved parameters does not.
Confirm exactly once — and "once" always means confirming the FULL plan. The user's confirmation only counts if the message they are replying to contains the complete resolved plan (every applicable checklist row).
Two valid paths, no third:
- No missing required fields → present the full plan as plain text, wait for the user's reply. Do not also open a confirmation popup — showing the plan in text and waiting for a reply is the confirmation, and adding a popup on top is redundant double-confirmation.
- Missing required fields (e.g. target language, dub vs subtitles) → use a choice prompt to collect ONLY the missing values. This prompt is a data question, NOT a create confirmation. After it resolves, you MUST still present the full plan in text and wait for an explicit reply before running
create.
Hard gate before every create: ask yourself — "did the user's last confirmation come as a reply to a message showing the complete plan?" If no, you do not have confirmation. Answering a language-selection popup is never authorization to create.
- ❌ Wrong: popup asks "original language? target language?" → user picks ko/ja →
create runs immediately.
- ✅ Right: popup asks ko/ja → agent shows the full plan (source, title, font, folder, prompt/glossary, auto-download) → user replies "yes" →
create runs.
If required fields are missing, stop before execution and list the missing fields explicitly. Do not start create with guessed required values.
Clarify key requirements before planning, not after creating. A create plan is only as good as the requirements behind it: when the user's request leaves an outcome-shaping choice open — target language, voice cloning model / accent expectation, speaker count, subtitles on/off, dub vs subtitles vs visual translate — resolve it with the user before showing the plan. Do not fill the gap with a default, show a technically-complete plan, and let the user rubber-stamp a project that misses what they actually wanted; a wrong key setting means points spent and the whole project redone.
3.1. Target language: never infer (important)
For any create that involves translation, dubbing, or visual translate, --target-language must come from an explicit user choice before you run the command.
When the user has not named a target language, do not:
- Guess or default to any language code (
zh, en, ja, zh-CN, etc.)
- Assume a target because the user chats in Chinese, this skill is localized, or examples in the docs use a particular language
- Infer from source media language, prior projects,
list/get results, or browser/system locale
- Treat vague requests like “translate it”, “dub this”, or “add subtitles” as permission to silently pick a
--target-language
Do this instead:
- Stop before
create and ask which target language the user wants (optionally show readable options from vozo-cli project languages <tool> — names + codes, not codes alone)
- Put the resolved
--target-language in the create plan (use a locale tag like zh-HK / en-AU when a region/accent is needed) and wait for confirmation
- Only pass
--target-language after the user clearly states it (e.g. “into English”, “target en”, “dub to Japanese”) or confirms a plan that names the language
--original-language may stay auto where supported — except visual_translate, where it is required and must be explicitly given by the user, never guessed. Do not infer either field from the language the user chats in. Target language has no default—the CLI will not choose one for you.
3.1.2. Dashboard folders vs local --from-dir (important)
Do not confuse these two “folder” concepts:
| Meaning |
CLI surface |
Example |
| Local directory of media files on disk |
create --from-dir <path> |
Batch-upload every video in /Users/me/videos |
| Dashboard folder in the user's Vozo account |
project folder create, folder list, folder search, then create --folder <folderId> |
Put new projects under a named workspace folder |
When the user wants a new dashboard folder:
- If they gave a folder name, run
vozo-cli project folder create "<name>" (or confirm the name first if it was vague).
- Use the returned
folder.folderId on subsequent project <tool> create ... --folder <folderId>.
- If they named an existing folder instead, prefer
project folder search "<name>" and reuse a unique match — do not create a duplicate unless they asked for a new one.
When the user only gave a folder name for create (not an id): resolve with folder search first; create only when no suitable folder exists.
3.1.3. Batch local files: use --from-files / --from-dir (important)
| User intent |
Use |
Do not use |
| 2+ local video/audio files |
One create with --from-files path1 path2 ... |
Repeated create --from-file per file |
| A folder of media |
One create with --from-dir <path> |
Listing files and looping --from-file |
Applies to translate_dub, translate_subtitles, visual_translate, and lipsync. Batch stdout returns ids[]. Requires Studio+. Does not support --subtitle-file (single-file only). translate_dub batch also does not pass --speaker-number.
3.1.4. Translate & Dub voice cloning model (--dub-preference) — surface it, don't silently default (important)
Translate & Dub has a Voice Cloning Model setting with three values. Users usually don't know it exists, so you must bring it up whenever it matters:
| Value |
Product name |
What it does / when to pick it |
auto |
Auto |
Automatically selects the best voice model for the content. Fine only when the user expressed no preference about voice, accent, or emotion. |
real |
VoiceREAL |
Preserves the emotion and accent of the original voice. Best for expressive content: dramas, vlogs, entertainment. |
native |
VoiceNATIVE |
Delivers a more natural target-language accent. Best for clarity-focused content: ads, e-learning, explainers. |
Agent rules:
- If the user mentions anything about accent, voice feel, naturalness, or emotion (e.g. "use a native American accent", "keep the original voice's emotion", "sound like a native speaker"), do not leave
--dub-preference at auto — map the request to real or native and put it in the create plan. A wrong model here means the whole project must be redone.
- Always show the chosen voice cloning model (including
auto) as one of the key settings in the create plan (§3), with a one-line explanation the first time, so the user can veto it before points are spent.
- If the user's accent/voice expectation is ambiguous, ask which model they want (with the table above summarized) instead of guessing.
3.2. Export / download: no inference; never use playback URLs (important)
Do not run export or download unless the user explicitly asks to export, download, or save project outputs to disk. A user opting in to "auto-download when finished" while confirming the create plan (§3) counts as that explicit request.
When the user only asked to create, check status, list/search, or get a project link, stop after the requested step — typically share webUrl and current status. Do not assume they want files on disk because processing finished, because a scenario in this skill shows a full pipeline, or because you think a "complete" workflow should end in a download.
Never treat preview / playback URLs as export or download URLs. These are not valid substitutes for export + download:
| Invalid for saving files |
Why |
webUrl, open result (url) |
Web editor / preview page, not a media file |
videoUrl, video_url, videoSrcList, video_src_list from any API JSON |
In-app playback / streaming source |
thumbUrl, thumb_url, originURL, origin_url |
Thumbnail or original upload pointer, not a finished export |
| Any HLS/m3u8 link, signed temp URL, or CDN preview link you scraped from API JSON |
Playback-only; may expire; not the CLI export artifact |
Correct way to deliver files:
- User explicitly asks to export/download (name the artifact if unclear).
project <tool> export <id> when needed → poll get until export is ready.
project <tool> download <id> --artifact <type> --output <path>.
The downloadUrl returned by export is for the CLI download command to follow internally — do not hand it to the user as a "direct download link", and do not curl/wget it yourself instead of running download.
If the user later asks for the file, run export / download then — do not skip ahead early "just to be helpful".
Required-field reminders:
translate_dub: require a source and --target-language
translate_subtitles: require a video source and --target-language
visual_translate: require a video source, --target-language, and explicit --original-language
lipsync: require a video source (--from-url / --from-file / --from-files / --from-dir) or --from-translation
- If the user gives a language and support is uncertain, run
vozo-cli project languages <tool> before create and only proceed with supported values.
- When the user asks which languages are supported: run
project languages <tool>, then answer with readable names from supportedOptions (e.g. English (en), Chinese (Hong Kong) (zh-HK)). Do not dump raw language codes alone.
After a create succeeds, do not report how many points it consumed. Nothing available to the CLI is the actual charge: estimateConsumedPoints and the references/limits.md formulas are pre-create estimates, and real billing diverges from them — a project that fails is not charged at all, and an auto-clipped run bills the clipped length. Presenting an estimate as the deduction states as fact something you did not observe.
- Points belong in the create plan, never in the create result. Show the estimate before the create (§3), labelled as an estimate, so the user can weigh it against their balance. Once the create returns, drop the subject.
- Do not restate the estimate as the cost after the fact — not in the create summary, not in polling updates, not in the completion report. "Consumed N points" is a claim about billing; you have no billing source.
- Never derive consumption by diffing
auth points before and after create. The balance is account-wide: concurrent projects from the web app, another terminal, or a parallel batch land in the same balance, and expiry/top-ups corrupt it too. A delta is not this create's cost — in either direction.
- Reading
auth points is still correct for showing the available balance (quota warnings in the create plan, §3) — just never present it, or a delta of it, as this project's charge.
- If the user explicitly asks what a create cost, say plainly that the CLI only has the pre-create estimate, give that number as an estimate, and point them to the web points/billing page for the actual charge.
3.3. Auto-clipping when points are insufficient (important)
For some tools, when the user is a first-time creator and available points are insufficient to process the full media duration, the CLI will automatically create a clipped interval (starting at 0s) so the backend can process a partial segment instead of blocking the create entirely.
Currently applies to:
translate_dub create
visual_translate create
When auto-clipping happens:
- The
create stdout JSON includes:
clip: { originalDurationSeconds, durationSeconds, clipInterval, reason }
warnings[]: user-facing message strings
- The CLI also prints each
warnings[] entry to stderr for human visibility.
Agent guidance:
- Always tell the user the output covers only the clipped interval and state the exact seconds range.
- Include the project
webUrl, and suggest topping up/upgrade or segmenting workflows if they need the full media processed.
3.5. Require double confirmation before delete
project delete is destructive. Never run it immediately after a user casually says “delete” — this applies identically whether it's a single project or a batch of many; batch is not a "lower ceremony" version of delete, and a single delete is not exempt just because it's only one item.
Before any delete:
- Show the project
id / ids that will be deleted.
- State clearly that the action is destructive and cannot be undone from CLI.
- Ask for a second explicit confirmation that is specific to the delete action.
Rules:
- Do not reuse an earlier confirmation for create / download / export as delete confirmation.
- If the scope is ambiguous, resolve the exact target list first and only then ask for delete confirmation.
- For multiple ids, echo the count and the concrete ids before executing
project delete.
3.6. Multi-tool requests: confirm independent vs chained (important)
When a single user request names 2+ tools (dub, subtitles, visual translate, lipsync), there are two different execution modes and the CLI does not default to either — you must resolve which one before creating anything:
- Independent mode: each tool creates its own project from the same original source (
--from-url / --from-file / --from-dir). Outputs don't affect each other; if the user wants one final file with all effects combined, they must merge on the web. This is the default assumption in references/scenarios.md Scenario D and is faster/cheaper (steps can run in parallel).
- Chained mode: each step after the first uses the previous step's exported output as its own source, so effects accumulate into a single output. Since
translate_dub create / visual_translate create only accept --from-url / --from-file / --from-files / --from-dir (no project-id source — verified in the CLI's option list), chaining means: export the prior step's artifact → download it locally → pass that local file via --from-file to the next create. This is slower (fully sequential, no parallelism) and costs more (each step reprocesses the full output of the previous one).
Confirmation rule: if the user's phrasing doesn't make the mode obvious, ask explicitly before creating anything — don't silently default to either mode.
- Treat phrasing like "do X first, then use that result for Y" / "based on the dubbed output, also do..." / "chain X into Y" as chained.
- Treat phrasing like "do X and Y together" / "create separate projects" / "also want subtitles and visual translate" (goals listed together, no dependency implied) as independent — but if truly ambiguous, still ask.
If chained, watch these details:
lipsync already has a native chain path: --from-translation <dub-id> pulls the dubbed audio track directly from an existing translate_dub project. Use that instead of the generic export/download/re-upload pattern when chaining dub → lipsync.
- For
translate_dub → visual_translate (or the reverse), only one channel changed in the prior step's output: dub changes the audio, visual translate changes burned-in on-screen text. Don't blindly copy the previous step's --target-language into the next step's --original-language. Ask or infer which channel the next tool actually reads (visual translate cares about on-screen text language; dub cares about spoken audio language) and set --original-language to that channel's real language, not the prior step's target language.
- State the pipeline order and the per-step source in the plan (see §3) so the user can confirm before any create runs.
4. Display rules
- No raw JSON unless asked.
- Summaries: title, id, kind, languages (readable names), status,
webUrl, local paths after download.
- Lists:
totalCount is the server total and may include types CLI omits; use items[] + nextCursor (and skippedUnsupportedCount / notice when present). Paginate with --cursor when needed.
Per-Tool Create → Download
Read references/tools.md for the full per-tool flag tables and download artifacts (translate_dub, translate_subtitles, visual_translate, lipsync). Before asking the user to confirm a create, also open references/create-plan-checklist.md and fill every applicable row. Always check tools.md before running create for a tool you haven't just used in this conversation, since required fields and Studio+/Creator+ gating differ per tool.
Scenario Playbook
Read references/scenarios.md for ready-made command sequences (folder batch, multi-language, multi-step pipelines, bulk download with filters). Match the user's request to the closest scenario (A–G) instead of re-deriving the plan from scratch.
Creation Limits (CLI pre-check)
Read references/limits.md before create when the media may be near a duration/size/tier cap, or when the user asks for a points estimate. It also has the points-estimate formula per tool.
Confirmation Rules
| Policy |
Commands |
| Read-only (run immediately) |
list, search, folder list, folder search, <tool> get, <tool> open |
| Confirm first |
folder create, <tool> create (single or batch — see §3), <tool> export, <tool> download, bulk download, multi-project chains |
| Never without explicit user request |
export, download — see §3.2 |
| Confirm twice, see §3.5 |
project delete (single id or multiple ids — same rule for both) |
Failure Recovery
status: "upgrade_required" (not "failed"): the CLI is too old for the API. Tell the user to run vozo-cli upgrade (or install a newer version), then retry. Do not treat this as a project/auth failure.
errorKind: "network" on a failed command: connectivity/DNS/TLS/proxy issue (not auth or project failure). Report network.code / message; do not auto-retry — wait for the user to decide.
upgradeSuggestion on a successful JSON result: soft recommendation only — command already succeeded. Mention a newer CLI is available when convenient; do not stop the workflow or treat it as an error.
- Processing: poll
get; do not claim ready while processing is true.
- Status
proofreading with processing: false: the dub is done but voices need user confirmation before export/download. Do not keep polling and do not retry export or download; share webUrl and ask the user to confirm the voices in the web editor.
- Download missing URL:
export → poll get until processing is false → retry download — only when the user already asked for a download.
- Subtitle download empty: project may lack blocks/segments yet.
- Unsupported request: state clearly; offer web
open or supported alternative.
Handoff to Web
After create, always give project link (webUrl) and mention it can be opened to review and edit the result (fix translations, change voices, redub) if the user is not satisfied. For text edits, redub, or web-only lipsync audio modes:
vozo-cli project <tool> open <id>
1---2name: vozo-project3description: Orchestrate Vozo CLI project workflows—single-tool create-to-download, multi-step pipelines, batch multi-language creation, and filtered bulk downloads. Use for translate dub, translate subtitles, visual translate, lipsync, folder/URL sources, and artifact downloads. Also use when the user asks what Vozo or this CLI is or what it can do (product introduction).4---56# Vozo Project78## CLI prerequisite910Requires the official `vozo-cli` from npm [`@vozoai/cli`](https://www.npmjs.com/package/@vozoai/cli) (source: [github.com/vozoai/cli](https://github.com/vozoai/cli)). Install with `npm install -g @vozoai/cli` or `npx @vozoai/cli@latest install`. Do not install from third-party mirrors. Auth is handled by `vozo-auth`.1112## What is Vozo / what can this CLI do (unified pitch)1314When the user asks anything like "what are you / what can you do / what is this / what can the CLI do / introduce Vozo", answer with the following canonical pitch (translate it into the user's language, but keep product names in English):1516> **Vozo** ([vozo.ai](https://www.vozo.ai)) is an AI video platform for taking one video to every language and audience. **Vozo CLI** brings its four core tools into your terminal and agent workflows:17>18> 1. **Translate & Dub** — translate a video (or audio) and re-voice it with AI voice cloning that keeps the original speakers' voices.19> 2. **Translate Subtitles** — generate translated subtitles for a video.20> 3. **Visual Translate** — translate the on-screen text burned into the video frames.21> 4. **Lip Sync** — re-sync the speakers' lips to match new audio (including dubbed audio from Translate & Dub).22>23> From the CLI you can create projects from local files, folders, or video URLs (batch supported), track processing, and export/download the results (videos, audio tracks, subtitles). Fine-grained editing — fixing translations, changing voices, redubbing — happens in the Vozo web editor: every project comes with a link you can open anytime.2425Keep the pitch to this scope. Do not promise features the CLI does not have (no video generation, no talking photo, no editing from the CLI), and do not enumerate internal flags in the pitch.2627## Product Naming2829Use Vozo website product names in user-facing text. Keep CLI command paths unchanged:3031| Product | CLI |32| ------------------- | ----------------------------- |33| Translate & Dub | `project translate_dub` |34| Translate Subtitles | `project translate_subtitles` |35| Visual Translate | `project visual_translate` |36| Lip Sync | `project lipsync` |3738**Write "Translate & Dub" with the ampersand — for video and audio alike; never "Translate dub" / "Translate Dub" without `&`.**3940**"Vozo" is a brand name — never translate, transliterate, or localize it.** Always keep it exactly as `Vozo` (capital V) in every language and in all user-facing text, summaries, and messages.4142## When to Use This Skill4344- Create projects from **local folder / files / URL** for dub, subtitles, visual translate, or lipsync.45- **Create or find dashboard folders** (`project folder create` / `folder list` / `folder search`) and create projects inside them with `--folder`.46- Run **create → poll → export (if needed) → download** for any single tool.47- **Chain** multiple tools (user specifies order, or you propose a plan).48- **Create many languages at once** by repeating create with different `--target-language` (not “translate to more” on one project).49- **Bulk download** after listing/searching with filters (folder, kind, date, language, title).50- Give users **project links** (`webUrl`) and `open` so they can edit on the web.5152## Preferred Commands5354```text55vozo-cli auth status | points | membership56vozo-cli project list | search | folder list | folder create | folder search | delete57vozo-cli project <tool> create | get | open | export | download58```5960`<tool>` = `translate_dub` | `translate_subtitles` | `visual_translate` | `lipsync`6162## Core Workflow6364### 1. Always start with auth65661. `vozo-cli auth status` — if not signed in, use `vozo-auth` / `auth login`.672. Before **batch create** or expensive chains: `auth points` + `auth membership`.6869### 2. Single-tool: create → download7071For each project, **only continue past create/poll when the user explicitly asked for export/download**:72731. **Create** with the right `project <tool> create` flags.742. **Poll** `project <tool> get <id>` until the `processing` field is `false` (or status is failed). Do not interpret status strings yourself — `processing` already covers project status, sub-task, and export in-flight states. **Field path:** `get` stdout nests everything under a top-level `project` key — `{ "project": { ..., "processing": <bool>, "status": "...", "errorCode": <string|null>, "errorMessage": <string|null> } }` — so read `project.processing` (e.g. `jq -e '.project.processing'`), never the top level. If extraction returns null/missing, that is a script error: abort the poll loop instead of treating it as "still processing". When the status reports a failure, summarize with `project.errorCode` and `project.errorMessage` (CLI maps these to web-aligned copy).753. **Export** `project <tool> export <id>` when a media artifact is missing — **only if the user asked to export or download outputs**. Export checks for an existing download URL first: if one is present it returns `status: "already_exported"` with `downloadUrl` and does not re-export; otherwise it returns `status: "started"`. Treat `already_exported` as success (artifact ready) — not a failure or skip-error.764. **Download** each requested artifact with `--output` — **only when the user asked for files on disk**. Pass a **directory** per project (trailing `/`) so files get the same product names as web downloads (e.g. `{title}_{language}_translated.mp4`, `{title}_{language}_subtitles.srt`); only pass a file path when the user explicitly asked for a custom name.775. **Share** `webUrl` from create/get. Whenever you hand out a project link, tell the user (especially first-time users) that they can open it to **review and edit the result** — fix translations, change voices, redub — if they are not satisfied; `project <tool> open <id>` opens it directly.786. **When processing finishes** (polling ends), proactively tell the user and ask whether they want the outputs downloaded (unless they already opted in/out at plan time). Offering is required; silently downloading is forbidden (§3.2), and silently stopping at "done" with no next step is poor service.7980### 2.5. Long-running polling should move to the background8182When the user asks for an end-to-end flow such as **upload/create → wait → export → download**, do not keep the foreground agent blocked on dense polling for long processing jobs.8384Rules:85861. After `create` / `export`, return quickly with the accepted project `id`, `kind`, `webUrl`, current status, and the planned next step.872. If the environment supports background work, move the repeated `get` polling to the background and resume the foreground only when:88 - the project is ready for `export`89 - the export is ready for `download`90 - the project fails913. While polling runs in the background, the foreground response should stay concise:92 - what has started93 - which ids are being watched94 - where outputs will be downloaded954. If the environment does **not** support true background execution, do not busy-wait in the foreground. Instead:96 - do sparse polling only when useful97 - return control to the user quickly98 - tell the user the current status and the exact follow-up command to resume995. For batch jobs, background polling should track each project independently and only surface projects that changed state or need the next action.100101Foreground waiting is only acceptable for short checks. Long processing and export waits should be treated as background watch tasks whenever possible.102103### 3. Present plans before writes104105**Never run `create` — single or batch — without first showing the resolved parameters and getting explicit confirmation.** This applies even when the user's request already sounds fully specified (e.g. "dub this video to English"); "show the plan" means restating the exact resolved values back to the user, not just silently proceeding because you think you understood them.106107Before **any** create (single item or batch) or bulk download, show a plan that is concrete enough for the user to validate the exact work that is about to happen.108109**Use the full checklist in `references/create-plan-checklist.md` — do not improvise a shorter summary.** Present every applicable setting with its **resolved value**, including defaults and batch-unsupported rows.110111**How to show the plan (important):**112113- Use **semantic, user-facing labels** (Product, Original language, Target language, Voice model, Speakers, …), not a bare dump of `--original-language`, `--target-language`, `--dub-preference`.114- Put language/product meaning first; add the CLI code in parentheses when useful — e.g. `Target language: English (en)`, `Voice model: VoiceNATIVE`.115- Prefer product names: **Translate & Dub**, **Translate Subtitles**, **Visual Translate**, **Lip Sync**.116- Still cover every setting the checklist requires — semantic wording must not drop fields.117118Every setting that applies must appear with its **resolved value**, including:119120- values you will pass explicitly121- settings omitted from the command but covered by a **CLI default** (write the default in plain language, e.g. `Original language: Auto-detect`, `Voice model: Auto`)122- settings **not supported** for the chosen source mode (write `not supported (batch)` instead of hiding the row)123124At minimum, always include:125126- product, source type, and source path / URL / folder (local vs dashboard folder)127- target language (label + code; use locale tags like `zh-HK` / `en-AU` when a region/accent is needed), original language when relevant128- dashboard folder and project title (or `none` / `auto from filename`)129- for Translate & Dub: **every** voice/subtitle/alignment setting (voice model, speakers, burn-in subtitles, remove original subs, auto-align, proofread before dubbing, prompt, glossary, custom subtitle file + usage)130- for Translate Subtitles: subtitle display mode, remove original subs, prompt, glossary, custom subtitle file131- for Visual Translate: original language, font choice132- for Lip Sync: source mode and face mode (`--face-mode` is **required**; ask if missing — do not default to single)133- whether the user wants the result **auto-downloaded when processing finishes** — offer it here once; a "yes" in the plan confirmation counts as the explicit download request required by §3.2134- for batch: estimated project count, and whether it is a single-language batch or repeated per language135- **estimated points** (label as estimate; formulas in `references/limits.md` / checklist) plus available balance from `auth points` when known136- output / follow-up expectations (`webUrl`, whether `export` will be needed, which artifacts will be downloaded)137- when summarizing languages for users, prefer human labels (`English`, `Chinese (Hong Kong)`); keep codes for the actual create command. For create, pass locale via `--target-language` tags like `zh-HK` when a region/accent is needed138- quota warnings (points, Studio for batch, membership expiry)139- which steps are web-only (fine-tuning text, redub)140141**Incomplete plans are invalid.** If you only list “target language + source file” and skip defaults the CLI will apply, the user cannot truly confirm the job. Stop and expand the plan before asking for confirmation.142143Wait for explicit user confirmation before running `create` (single or batch) or a bulk `download`. A one-word request ("yes" / "go" / "confirm") after you've shown the plan counts as confirmation; a request that jumps straight to naming the action without ever seeing the resolved parameters does not.144145**Confirm exactly once — and "once" always means confirming the FULL plan.** The user's confirmation only counts if the message they are replying to contains the complete resolved plan (every applicable checklist row).146147Two valid paths, no third:1481491. **No missing required fields** → present the full plan as plain text, wait for the user's reply. Do **not** also open a confirmation popup — showing the plan in text and waiting for a reply _is_ the confirmation, and adding a popup on top is redundant double-confirmation.1502. **Missing required fields** (e.g. target language, dub vs subtitles) → use a choice prompt to collect ONLY the missing values. **This prompt is a data question, NOT a create confirmation.** After it resolves, you MUST still present the full plan in text and wait for an explicit reply before running `create`.151152**Hard gate before every `create`:** ask yourself — "did the user's last confirmation come as a reply to a message showing the complete plan?" If no, you do not have confirmation. Answering a language-selection popup is never authorization to create.153154- ❌ Wrong: popup asks "original language? target language?" → user picks ko/ja → `create` runs immediately.155- ✅ Right: popup asks ko/ja → agent shows the full plan (source, title, font, folder, prompt/glossary, auto-download) → user replies "yes" → `create` runs.156157If required fields are missing, stop before execution and list the missing fields explicitly. **Do not** start create with guessed required values.158159**Clarify key requirements before planning, not after creating.** A create plan is only as good as the requirements behind it: when the user's request leaves an outcome-shaping choice open — target language, voice cloning model / accent expectation, speaker count, subtitles on/off, dub vs subtitles vs visual translate — resolve it with the user **before** showing the plan. Do not fill the gap with a default, show a technically-complete plan, and let the user rubber-stamp a project that misses what they actually wanted; a wrong key setting means points spent and the whole project redone.160161### 3.1. Target language: never infer (important)162163For any `create` that involves translation, dubbing, or visual translate, `--target-language` must come from an **explicit user choice** before you run the command.164165**When the user has not named a target language, do not:**166167- Guess or default to any language code (`zh`, `en`, `ja`, `zh-CN`, etc.)168- Assume a target because the user chats in Chinese, this skill is localized, or examples in the docs use a particular language169- Infer from source media language, prior projects, `list`/`get` results, or browser/system locale170- Treat vague requests like “translate it”, “dub this”, or “add subtitles” as permission to silently pick a `--target-language`171172**Do this instead:**1731741. Stop before `create` and ask which target language the user wants (optionally show readable options from `vozo-cli project languages <tool>` — names + codes, not codes alone)1752. Put the resolved `--target-language` in the create plan (use a locale tag like `zh-HK` / `en-AU` when a region/accent is needed) and wait for confirmation1763. Only pass `--target-language` after the user clearly states it (e.g. “into English”, “target en”, “dub to Japanese”) or confirms a plan that names the language177178`--original-language` may stay `auto` where supported — **except `visual_translate`, where it is required and must be explicitly given by the user, never guessed**. Do not infer either field from the language the user chats in. **Target language has no default—the CLI will not choose one for you.**179180### 3.1.2. Dashboard folders vs local `--from-dir` (important)181182Do not confuse these two “folder” concepts:183184| Meaning | CLI surface | Example |185| ----------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------------------- |186| **Local directory of media files** on disk | `create --from-dir <path>` | Batch-upload every video in `/Users/me/videos` |187| **Dashboard folder** in the user's Vozo account | `project folder create`, `folder list`, `folder search`, then `create --folder <folderId>` | Put new projects under a named workspace folder |188189**When the user wants a new dashboard folder:**1901911. If they gave a folder name, run `vozo-cli project folder create "<name>"` (or confirm the name first if it was vague).1922. Use the returned `folder.folderId` on subsequent `project <tool> create ... --folder <folderId>`.1933. If they named an existing folder instead, prefer `project folder search "<name>"` and reuse a unique match — do not create a duplicate unless they asked for a new one.194195**When the user only gave a folder name for create (not an id):** resolve with `folder search` first; create only when no suitable folder exists.196197### 3.1.3. Batch local files: use `--from-files` / `--from-dir` (important)198199| User intent | Use | Do **not** use |200| -------------------------- | ---------------------------------------------------- | --------------------------------------- |201| 2+ local video/audio files | **One** `create` with `--from-files path1 path2 ...` | Repeated `create --from-file` per file |202| A folder of media | **One** `create` with `--from-dir <path>` | Listing files and looping `--from-file` |203204Applies to `translate_dub`, `translate_subtitles`, `visual_translate`, and `lipsync`. Batch stdout returns **`ids[]`**. Requires **Studio+**. Does **not** support `--subtitle-file` (single-file only). `translate_dub` batch also does not pass `--speaker-number`.205206### 3.1.4. Translate & Dub voice cloning model (`--dub-preference`) — surface it, don't silently default (important)207208Translate & Dub has a **Voice Cloning Model** setting with three values. Users usually don't know it exists, so you must bring it up whenever it matters:209210| Value | Product name | What it does / when to pick it |211| -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |212| `auto` | Auto | Automatically selects the best voice model for the content. Fine only when the user expressed **no** preference about voice, accent, or emotion. |213| `real` | VoiceREAL | Preserves the **emotion and accent of the original voice**. Best for expressive content: dramas, vlogs, entertainment. |214| `native` | VoiceNATIVE | Delivers a more **natural target-language accent**. Best for clarity-focused content: ads, e-learning, explainers. |215216**Agent rules:**217218- If the user mentions **anything** about accent, voice feel, naturalness, or emotion (e.g. "use a native American accent", "keep the original voice's emotion", "sound like a native speaker"), do **not** leave `--dub-preference` at `auto` — map the request to `real` or `native` and put it in the create plan. A wrong model here means the whole project must be redone.219- Always show the chosen voice cloning model (including `auto`) as one of the key settings in the create plan (§3), with a one-line explanation the first time, so the user can veto it before points are spent.220- If the user's accent/voice expectation is ambiguous, ask which model they want (with the table above summarized) instead of guessing.221222### 3.2. Export / download: no inference; never use playback URLs (important)223224**Do not run `export` or `download` unless the user explicitly asks to export, download, or save project outputs to disk.** A user opting in to "auto-download when finished" while confirming the create plan (§3) counts as that explicit request.225226When the user only asked to **create**, **check status**, **list/search**, or **get a project link**, stop after the requested step — typically share `webUrl` and current status. **Do not** assume they want files on disk because processing finished, because a scenario in this skill shows a full pipeline, or because you think a "complete" workflow should end in a download.227228**Never treat preview / playback URLs as export or download URLs.** These are **not** valid substitutes for `export` + `download`:229230| Invalid for saving files | Why |231| --------------------------------------------------------------------------------- | ----------------------------------------------------------- |232| `webUrl`, `open` result (`url`) | Web editor / preview page, not a media file |233| `videoUrl`, `video_url`, `videoSrcList`, `video_src_list` from any API JSON | In-app playback / streaming source |234| `thumbUrl`, `thumb_url`, `originURL`, `origin_url` | Thumbnail or original upload pointer, not a finished export |235| Any HLS/m3u8 link, signed temp URL, or CDN preview link you scraped from API JSON | Playback-only; may expire; not the CLI export artifact |236237**Correct way to deliver files:**2382391. User explicitly asks to export/download (name the artifact if unclear).2402. `project <tool> export <id>` when needed → poll `get` until export is ready.2413. `project <tool> download <id> --artifact <type> --output <path>`.242243The `downloadUrl` returned by `export` is for the CLI `download` command to follow internally — **do not** hand it to the user as a "direct download link", and **do not** `curl`/`wget` it yourself instead of running `download`.244245If the user later asks for the file, run `export` / `download` then — do not skip ahead early "just to be helpful".246247Required-field reminders:248249- `translate_dub`: require a source and `--target-language`250- `translate_subtitles`: require a video source and `--target-language`251- `visual_translate`: require a video source, `--target-language`, and explicit `--original-language`252- `lipsync`: require a video source (`--from-url` / `--from-file` / `--from-files` / `--from-dir`) or `--from-translation`253- If the user gives a language and support is uncertain, run `vozo-cli project languages <tool>` before create and only proceed with supported values.254- **When the user asks which languages are supported:** run `project languages <tool>`, then answer with readable names from `supportedOptions` (e.g. `English (en)`, `Chinese (Hong Kong) (zh-HK)`). Do **not** dump raw language codes alone.255256After a create succeeds, **do not report how many points it consumed.** Nothing available to the CLI is the actual charge: `estimateConsumedPoints` and the `references/limits.md` formulas are _pre-create estimates_, and real billing diverges from them — a project that fails is not charged at all, and an auto-clipped run bills the clipped length. Presenting an estimate as the deduction states as fact something you did not observe.2572581. **Points belong in the create plan, never in the create result.** Show the estimate _before_ the create (§3), labelled as an estimate, so the user can weigh it against their balance. Once the create returns, drop the subject.2592. **Do not restate the estimate as the cost after the fact** — not in the create summary, not in polling updates, not in the completion report. "Consumed N points" is a claim about billing; you have no billing source.2603. **Never derive consumption by diffing `auth points` before and after create.** The balance is account-wide: concurrent projects from the web app, another terminal, or a parallel batch land in the same balance, and expiry/top-ups corrupt it too. A delta is not this create's cost — in either direction.2614. Reading `auth points` is still correct for showing the **available balance** (quota warnings in the create plan, §3) — just never present it, or a delta of it, as this project's charge.2625. If the user explicitly asks what a create cost, say plainly that the CLI only has the pre-create estimate, give that number **as an estimate**, and point them to the web points/billing page for the actual charge.263264### 3.3. Auto-clipping when points are insufficient (important)265266For some tools, when the user is a **first-time creator** and available points are **insufficient** to process the full media duration, the CLI will automatically create a **clipped interval** (starting at 0s) so the backend can process a partial segment instead of blocking the create entirely.267268Currently applies to:269270- `translate_dub create`271- `visual_translate create`272273When auto-clipping happens:274275- The `create` stdout JSON includes:276 - `clip`: `{ originalDurationSeconds, durationSeconds, clipInterval, reason }`277 - `warnings[]`: user-facing message strings278- The CLI also prints each `warnings[]` entry to stderr for human visibility.279280Agent guidance:281282- Always tell the user the output covers **only the clipped interval** and state the exact seconds range.283- Include the project `webUrl`, and suggest topping up/upgrade or segmenting workflows if they need the full media processed.284285### 3.5. Require double confirmation before delete286287`project delete` is destructive. Never run it immediately after a user casually says “delete” — this applies identically whether it's a single project or a batch of many; batch is not a "lower ceremony" version of delete, and a single delete is not exempt just because it's only one item.288289Before any delete:2902911. Show the project `id` / `ids` that will be deleted.2922. State clearly that the action is destructive and cannot be undone from CLI.2933. Ask for a second explicit confirmation that is specific to the delete action.294295Rules:296297- Do not reuse an earlier confirmation for create / download / export as delete confirmation.298- If the scope is ambiguous, resolve the exact target list first and only then ask for delete confirmation.299- For multiple ids, echo the count and the concrete ids before executing `project delete`.300301### 3.6. Multi-tool requests: confirm independent vs chained (important)302303When a single user request names 2+ tools (dub, subtitles, visual translate, lipsync), there are two different execution modes and the CLI does **not** default to either — you must resolve which one before creating anything:304305- **Independent mode**: each tool creates its own project **from the same original source** (`--from-url` / `--from-file` / `--from-dir`). Outputs don't affect each other; if the user wants one final file with all effects combined, they must merge on the web. This is the default assumption in `references/scenarios.md` Scenario D and is faster/cheaper (steps can run in parallel).306- **Chained mode**: each step after the first uses the **previous step's exported output** as its own source, so effects accumulate into a single output. Since `translate_dub create` / `visual_translate create` only accept `--from-url` / `--from-file` / `--from-files` / `--from-dir` (no project-id source — verified in the CLI's option list), chaining means: `export` the prior step's artifact → `download` it locally → pass that local file via `--from-file` to the next `create`. This is slower (fully sequential, no parallelism) and costs more (each step reprocesses the full output of the previous one).307308**Confirmation rule:** if the user's phrasing doesn't make the mode obvious, ask explicitly before creating anything — don't silently default to either mode.309310- Treat phrasing like "do X first, then use that result for Y" / "based on the dubbed output, also do..." / "chain X into Y" as chained.311- Treat phrasing like "do X and Y together" / "create separate projects" / "also want subtitles and visual translate" (goals listed together, no dependency implied) as independent — but if truly ambiguous, still ask.312313**If chained, watch these details:**314315- `lipsync` already has a native chain path: `--from-translation <dub-id>` pulls the dubbed audio track directly from an existing `translate_dub` project. Use that instead of the generic export/download/re-upload pattern when chaining dub → lipsync.316- For `translate_dub` → `visual_translate` (or the reverse), only one channel changed in the prior step's output: dub changes the **audio**, visual translate changes **burned-in on-screen text**. Don't blindly copy the previous step's `--target-language` into the next step's `--original-language`. Ask or infer which channel the next tool actually reads (visual translate cares about on-screen text language; dub cares about spoken audio language) and set `--original-language` to that channel's real language, not the prior step's target language.317- State the pipeline order and the per-step source in the plan (see §3) so the user can confirm before any create runs.318319### 4. Display rules320321- No raw JSON unless asked.322- Summaries: title, id, kind, languages (readable names), status, `webUrl`, local paths after download.323- Lists: `totalCount` is the server total and may include types CLI omits; use `items[]` + `nextCursor` (and `skippedUnsupportedCount` / `notice` when present). Paginate with `--cursor` when needed.324325---326327## Per-Tool Create → Download328329Read `references/tools.md` for the full per-tool flag tables and download artifacts (`translate_dub`, `translate_subtitles`, `visual_translate`, `lipsync`). **Before asking the user to confirm a create, also open `references/create-plan-checklist.md` and fill every applicable row.** Always check `tools.md` before running `create` for a tool you haven't just used in this conversation, since required fields and Studio+/Creator+ gating differ per tool.330331---332333## Scenario Playbook334335Read `references/scenarios.md` for ready-made command sequences (folder batch, multi-language, multi-step pipelines, bulk download with filters). Match the user's request to the closest scenario (A–G) instead of re-deriving the plan from scratch.336337---338339## Creation Limits (CLI pre-check)340341Read `references/limits.md` before `create` when the media may be near a duration/size/tier cap, or when the user asks for a points estimate. It also has the points-estimate formula per tool.342343---344345## Confirmation Rules346347| Policy | Commands |348| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |349| Read-only (run immediately) | `list`, `search`, `folder list`, `folder search`, `<tool> get`, `<tool> open` |350| Confirm first | `folder create`, `<tool> create` (single or batch — see §3), `<tool> export`, `<tool> download`, bulk `download`, multi-project chains |351| Never without explicit user request | `export`, `download` — see §3.2 |352| Confirm twice, see §3.5 | `project delete` (single id or multiple ids — same rule for both) |353354---355356## Failure Recovery357358- `status: "upgrade_required"` (not `"failed"`): the CLI is too old for the API. Tell the user to run `vozo-cli upgrade` (or install a newer version), then retry. Do not treat this as a project/auth failure.359- `errorKind: "network"` on a failed command: connectivity/DNS/TLS/proxy issue (not auth or project failure). Report `network.code` / `message`; do **not** auto-retry — wait for the user to decide.360- `upgradeSuggestion` on a **successful** JSON result: soft recommendation only — command already succeeded. Mention a newer CLI is available when convenient; do **not** stop the workflow or treat it as an error.361- Processing: poll `get`; do not claim ready while `processing` is `true`.362- Status `proofreading` with `processing: false`: the dub is done but voices need user confirmation before export/download. Do not keep polling and do not retry `export` or `download`; share `webUrl` and ask the user to confirm the voices in the web editor.363- Download missing URL: `export` → poll `get` until `processing` is `false` → retry `download` — **only when the user already asked for a download**.364- Subtitle download empty: project may lack blocks/segments yet.365- Unsupported request: state clearly; offer web `open` or supported alternative.366367## Handoff to Web368369After create, always give **project link** (`webUrl`) and mention it can be opened to review and edit the result (fix translations, change voices, redub) if the user is not satisfied. For text edits, redub, or web-only lipsync audio modes:370371`vozo-cli project <tool> open <id>`