Create AI videos from the terminal. Official CLI for the HeyGen video generation API.
123
stars
185
commits
Go
primary language
Sep 9, 2026
updated
Make AI videos from the command line. Drive HeyGen with code, not clicks.

Full reference and examples: developers.heygen.com/cli.
heygen-com/skills — one-line install for Claude Code, Codex, and other agents. Create your own avatar and generate a video in a single conversation.
--request-schema and --response-schema return JSON Schema without auth or API calls.HEYGEN_API_KEY and nothing reads a TTY.heygen feedback --rating <1-5> --comment "...". It sends an anonymous rating + note (no API key needed); honors the analytics opt-out. Agents should use this for bugs rather than opening GitHub issues automatically (see Reporting bugs).curl -fsSL https://static.heygen.ai/cli/install.sh | bash
Single static binary, no runtime required. Installs to ~/.local/bin.
Supported platforms: macOS, Linux, and Windows (via WSL).
You only need a HeyGen API key — see Authenticate below.
heygen update # install the latest version
Tab-completion for commands, subcommands, and flags is available for bash, zsh, fish, and PowerShell:
source <(heygen completion zsh) # current shell (bash/zsh/fish)
heygen completion zsh > "${fpath[1]}/_heygen" # persist (zsh; adjust path per shell)
Run heygen completion --help for per-shell install instructions.
Choose one of the options below. The first three are agent- and CI-friendly; the remaining options are for humans.
1. Environment variable — agents, CI; ephemeral, no file on disk:
export HEYGEN_API_KEY=your-key-here
2. Pipe to auth login — agents; persists API key to ~/.heygen/credentials:
echo "$KEY" | heygen auth login
3. Explicit --api-key — humans paste from a prompt:
heygen auth login --api-key
4. Browser OAuth — humans, Pro / Max subscription users; persists OAuth tokens to ~/.heygen/credentials:
heygen auth login --oauth
5. Device OAuth — humans in an attended SSH/headless terminal; open the displayed URL on any browser and enter the one-time code:
heygen auth login --device
Device OAuth is refused in CI and HEYGEN_NONINTERACTIVE mode. Unattended agents must use an API key.
6. Interactive picker — humans, no flag: a TTY prompt lets you choose between API key (uses API credits) and OAuth (uses subscription credits):
heygen auth login
Verify any of the above with heygen auth status. Get an API key at app.heygen.com/settings/api.
Single-credential file. The credentials file holds at most one of
api_key/ OAuth tokens at any time. Runningheygen auth login(any method) clears the other on success — re-login overwrites, it does not merge.heygen auth statuswill tell you which one is active.
HEYGEN_API_KEYin the environment always wins over either file credential.
1. Create a finished video from a prompt (returns JSON including video_id):
heygen video-agent create --prompt "30-second product demo" --wait
2. Get its metadata and share link:
heygen video get <video-id>
Returns JSON with video_url (raw mp4), video_page_url (shareable UI link), thumbnail_url, and duration. Pipe to jq to extract what you need:
heygen video get <video-id> | jq -r '.data.video_page_url'
# → https://app.heygen.com/videos/...
3. Download the mp4:
heygen video download <video-id>
Add --human to any command for a readable layout. Set HEYGEN_OUTPUT=human to make it the default.
In --human mode, list responses render as a table and single-object responses render as an indented, humanized layout (similar to kubectl describe). Keys are humanized per segment (auto_reload → Auto Reload), with common acronyms uppercased (video_url → Video URL); nested objects indent under a Label: header, scalar siblings align locally within each block, arrays of scalars join inline (a, b, c), and arrays of objects render as YAML-style - sequence items. Empty objects, empty arrays, and nulls show as (none). Long scalar values (e.g. pre-signed download URLs) are printed in full and may wrap in a narrow terminal; pipe the default JSON to jq if you need to extract one cleanly. For example:
Status: completed
Wallet:
Auto Reload:
Enabled: false
Currency: usd
Remaining Balance: 476.78
Tags: alpha, beta
--human is a readable layout for terminals and may change between releases; scripts and agents should consume the default JSON output, which is stable. JSON output (the default) is never altered.
Mirrors the HeyGen v3 API. Pattern: heygen <noun> <verb>.
| Group | What it does |
|---|---|
video-agent | Create videos from text prompts using AI |
video | Create, list, get, delete, download videos; batch-create and bulk status |
template | List templates and generate videos from them |
avatar | List and manage avatars and looks |
voice | List voices, design voices, generate speech |
audio | Search the background-music catalog |
video-translate | Translate videos into other languages |
lipsync | Dub or replace audio on existing videos |
webhook | Manage webhook endpoints and events |
asset | Upload files for use in video creation |
user | Account info and billing |
Every command supports --help.
| Aspect | Behavior |
|---|---|
| stdout | Always JSON. Even video download — binary writes to disk; stdout emits {"asset", "message", "path"} so you can chain on .path. |
| stderr | Structured envelope on error: {"error": {"code", "message", "hint", "param", "doc_url", "request_id"}}. code/message are always present; hint/param/doc_url/request_id appear when applicable (param/doc_url are surfaced from the API for validation and documented errors). Stable code values for programmatic branching. A code prefixed cli_ is originated by the CLI itself (client/transport/local conditions, e.g. cli_download_url_expired). A bare code is either an API code (or a CLI mirror of one) or one of a small frozen set of legacy CLI codes that predate the prefix. The cli_ prefix is reserved for the CLI, so a new CLI code can never collide with an API code. |
| Exit codes | 0 ok · 1 API or network · 2 usage · 3 auth / not permitted · 4 timeout — a request exceeded its per-operation timeout, or the --wait poll window elapsed (stdout contains partial resource for resume) |
| Request bodies | Flags for simple inputs; -d for nested JSON (inline, file path, or - for stdin). Flags override matching fields. |
| Async jobs | --wait blocks with exponential backoff; --timeout sets max (default 20m). Only some create commands support them — --help on the command is the authority. Poll anything else with whichever get reads the id the create returned. 429 and selected transient 5xx (500/502/503/504) retry automatically on retry-eligible requests. |
Example error envelope:
{"error": {"code": "not_found", "message": "Video not found", "hint": "Check ID with: heygen video list", "doc_url": "https://developers.heygen.com/docs/error-codes#not-found"}}
| File | Purpose |
|---|---|
~/.heygen/credentials | API key or OAuth tokens (one at a time — see Authenticate) |
~/.heygen/config.toml | Output format and other non-secret settings |
HEYGEN_API_KEY and HEYGEN_OUTPUT env vars override the respective files.
heygen config list # show all settings with sources
heygen feedback --rating <1-5> --comment "...". Goes to private, anonymous analytics. Safe to run unattended. Usage telemetry is anonymous until you sign in: running heygen auth login links it to your account email or username. A one-time notice prints the first time analytics runs; opt out anytime with HEYGEN_NO_ANALYTICS=1 (or heygen config set analytics false).Agents: do not open GitHub issues automatically. Use heygen feedback for bug signal; if something seems worth tracking, surface it to the user and let a human file the issue after reviewing it for sensitive content.
See CONTRIBUTING.md.
Go
98.2%
Shell
1.6%
Create AI videos from the terminal. Official CLI for the HeyGen video generation API.
123
stars
185
commits
Go
primary language
Sep 9, 2026
updated
Make AI videos from the command line. Drive HeyGen with code, not clicks.

Full reference and examples: developers.heygen.com/cli.
heygen-com/skills — one-line install for Claude Code, Codex, and other agents. Create your own avatar and generate a video in a single conversation.
--request-schema and --response-schema return JSON Schema without auth or API calls.HEYGEN_API_KEY and nothing reads a TTY.heygen feedback --rating <1-5> --comment "...". It sends an anonymous rating + note (no API key needed); honors the analytics opt-out. Agents should use this for bugs rather than opening GitHub issues automatically (see Reporting bugs).curl -fsSL https://static.heygen.ai/cli/install.sh | bash
Single static binary, no runtime required. Installs to ~/.local/bin.
Supported platforms: macOS, Linux, and Windows (via WSL).
You only need a HeyGen API key — see Authenticate below.
heygen update # install the latest version
Tab-completion for commands, subcommands, and flags is available for bash, zsh, fish, and PowerShell:
source <(heygen completion zsh) # current shell (bash/zsh/fish)
heygen completion zsh > "${fpath[1]}/_heygen" # persist (zsh; adjust path per shell)
Run heygen completion --help for per-shell install instructions.
Choose one of the options below. The first three are agent- and CI-friendly; the remaining options are for humans.
1. Environment variable — agents, CI; ephemeral, no file on disk:
export HEYGEN_API_KEY=your-key-here
2. Pipe to auth login — agents; persists API key to ~/.heygen/credentials:
echo "$KEY" | heygen auth login
3. Explicit --api-key — humans paste from a prompt:
heygen auth login --api-key
4. Browser OAuth — humans, Pro / Max subscription users; persists OAuth tokens to ~/.heygen/credentials:
heygen auth login --oauth
5. Device OAuth — humans in an attended SSH/headless terminal; open the displayed URL on any browser and enter the one-time code:
heygen auth login --device
Device OAuth is refused in CI and HEYGEN_NONINTERACTIVE mode. Unattended agents must use an API key.
6. Interactive picker — humans, no flag: a TTY prompt lets you choose between API key (uses API credits) and OAuth (uses subscription credits):
heygen auth login
Verify any of the above with heygen auth status. Get an API key at app.heygen.com/settings/api.
Single-credential file. The credentials file holds at most one of
api_key/ OAuth tokens at any time. Runningheygen auth login(any method) clears the other on success — re-login overwrites, it does not merge.heygen auth statuswill tell you which one is active.
HEYGEN_API_KEYin the environment always wins over either file credential.
1. Create a finished video from a prompt (returns JSON including video_id):
heygen video-agent create --prompt "30-second product demo" --wait
2. Get its metadata and share link:
heygen video get <video-id>
Returns JSON with video_url (raw mp4), video_page_url (shareable UI link), thumbnail_url, and duration. Pipe to jq to extract what you need:
heygen video get <video-id> | jq -r '.data.video_page_url'
# → https://app.heygen.com/videos/...
3. Download the mp4:
heygen video download <video-id>
Add --human to any command for a readable layout. Set HEYGEN_OUTPUT=human to make it the default.
In --human mode, list responses render as a table and single-object responses render as an indented, humanized layout (similar to kubectl describe). Keys are humanized per segment (auto_reload → Auto Reload), with common acronyms uppercased (video_url → Video URL); nested objects indent under a Label: header, scalar siblings align locally within each block, arrays of scalars join inline (a, b, c), and arrays of objects render as YAML-style - sequence items. Empty objects, empty arrays, and nulls show as (none). Long scalar values (e.g. pre-signed download URLs) are printed in full and may wrap in a narrow terminal; pipe the default JSON to jq if you need to extract one cleanly. For example:
Status: completed
Wallet:
Auto Reload:
Enabled: false
Currency: usd
Remaining Balance: 476.78
Tags: alpha, beta
--human is a readable layout for terminals and may change between releases; scripts and agents should consume the default JSON output, which is stable. JSON output (the default) is never altered.
Mirrors the HeyGen v3 API. Pattern: heygen <noun> <verb>.
| Group | What it does |
|---|---|
video-agent | Create videos from text prompts using AI |
video | Create, list, get, delete, download videos; batch-create and bulk status |
template | List templates and generate videos from them |
avatar | List and manage avatars and looks |
voice | List voices, design voices, generate speech |
audio | Search the background-music catalog |
video-translate | Translate videos into other languages |
lipsync | Dub or replace audio on existing videos |
webhook | Manage webhook endpoints and events |
asset | Upload files for use in video creation |
user | Account info and billing |
Every command supports --help.
| Aspect | Behavior |
|---|---|
| stdout | Always JSON. Even video download — binary writes to disk; stdout emits {"asset", "message", "path"} so you can chain on .path. |
| stderr | Structured envelope on error: {"error": {"code", "message", "hint", "param", "doc_url", "request_id"}}. code/message are always present; hint/param/doc_url/request_id appear when applicable (param/doc_url are surfaced from the API for validation and documented errors). Stable code values for programmatic branching. A code prefixed cli_ is originated by the CLI itself (client/transport/local conditions, e.g. cli_download_url_expired). A bare code is either an API code (or a CLI mirror of one) or one of a small frozen set of legacy CLI codes that predate the prefix. The cli_ prefix is reserved for the CLI, so a new CLI code can never collide with an API code. |
| Exit codes | 0 ok · 1 API or network · 2 usage · 3 auth / not permitted · 4 timeout — a request exceeded its per-operation timeout, or the --wait poll window elapsed (stdout contains partial resource for resume) |
| Request bodies | Flags for simple inputs; -d for nested JSON (inline, file path, or - for stdin). Flags override matching fields. |
| Async jobs | --wait blocks with exponential backoff; --timeout sets max (default 20m). Only some create commands support them — --help on the command is the authority. Poll anything else with whichever get reads the id the create returned. 429 and selected transient 5xx (500/502/503/504) retry automatically on retry-eligible requests. |
Example error envelope:
{"error": {"code": "not_found", "message": "Video not found", "hint": "Check ID with: heygen video list", "doc_url": "https://developers.heygen.com/docs/error-codes#not-found"}}
| File | Purpose |
|---|---|
~/.heygen/credentials | API key or OAuth tokens (one at a time — see Authenticate) |
~/.heygen/config.toml | Output format and other non-secret settings |
HEYGEN_API_KEY and HEYGEN_OUTPUT env vars override the respective files.
heygen config list # show all settings with sources
heygen feedback --rating <1-5> --comment "...". Goes to private, anonymous analytics. Safe to run unattended. Usage telemetry is anonymous until you sign in: running heygen auth login links it to your account email or username. A one-time notice prints the first time analytics runs; opt out anytime with HEYGEN_NO_ANALYTICS=1 (or heygen config set analytics false).Agents: do not open GitHub issues automatically. Use heygen feedback for bug signal; if something seems worth tracking, surface it to the user and let a human file the issue after reviewing it for sensitive content.
See CONTRIBUTING.md.
Go
98.2%
Shell
1.6%