@contenthero/cli
The official ContentHero command-line interface. Generate media, run the content
pipeline, and read your brand and research context from the terminal or any agent
shell. It rides the @contenthero/sdk
kernel, so it talks to the same /api/v1 surface as the SDK and the
MCP server.
Built agent-first: JSON by default, predictable exit codes, and a schema command
so an agent can discover every command's inputs without docs.
Install
npm install -g @contenthero/cli
Requires Node 20+. The binary is contenthero.
Authenticate
The CLI resolves your API key in this order: the --api-key flag, then the
CONTENTHERO_API_KEY environment variable, then a stored credential.
# Browser-assisted (recommended): opens your browser, mints a key for this machine
contenthero login
# Bring your own key (CI / headless): create one in the app under API Keys
export CONTENTHERO_API_KEY=ch_live_...
# ...or store it:
contenthero login --with-key ch_live_... # or: echo "$KEY" | contenthero login --with-key
contenthero auth status # verify the active key and show the account
contenthero logout # remove the stored credential
The stored credential lives at ~/.contenthero/credentials (mode 0600). The env
var always wins over the stored file, so CI can override a local login.
Output
JSON is the default (built for agents and scripts). Add --human for readable
tables and key/value output.
contenthero account get
contenthero model list --type image --human
Generate
generate covers image, video, audio, board, and lip-sync. The waitable kinds
share --cost (preflight, charges nothing), --wait / --no-wait (default
waits), and --timeout <seconds>.
# Model ids come from `contenthero model list`
# Preflight the cost, then generate and wait for the URLs
contenthero generate image "a red ceramic cube on white" --model <imageModelId> --cost
contenthero generate image "a red ceramic cube on white" --model <imageModelId>
# Submit without blocking, then poll
ID=$(contenthero generate video "drone shot over a canyon" --model <videoModelId> --no-wait | jq -r .outputId)
contenthero status "$ID" --no-wait
contenthero status "$ID" --timeout 300
# Chain: feed a previous output id straight in as a reference (URL or output id)
contenthero generate video "slow zoom in" --model <videoModelId> --start-frame "$ID"
# Audio (synchronous) and upscaling
contenthero generate audio --model <audioModelId> --text "Hello there" --voice <voiceId>
contenthero upscale "$ID" --model <upscaleModelId> --factor 2x
Exit code 4 means a render was accepted but did not finish before the timeout. The
outputId is still emitted, so you can keep polling.
The rest of the surface
Each command is named after the MCP tool it runs (export get is get_export, post publish is
publish_post), so what an agent learns on one surface reads the same on the other.
contenthero view see what the user is looking at; render, hear or watch your work; see a raw clip
contenthero project list | get | create | update | duplicate | share | delete | apply
| transcript get | edit undo|redo
| settings get|update | version list|save|restore|update|delete
contenthero media list | search | get | zoom | share
contenthero import <url> | --pptx <url> | --canva <id>: bring a file, video page or deck in
contenthero export <projectId> | get | list: render a project into a file
contenthero download <id> [path]: write any file of yours, or an export, to disk (free)
contenthero upload <file...>: put local files in your library, large ones in parts, a progress line each, `--resume <outputId>` finishes one that stopped
contenthero transcribe [audioUrl] | --content-id <id> [--slide <n>]: speech to text
contenthero status <ids...> [--kind <kind>]: where any background job is
contenthero card list | get | create | update
contenthero post publish
contenthero tag list | create | update | delete
contenthero stage list | create | update | delete
contenthero space list | get | create | update | delete
contenthero folder list | get | create | update | delete
contenthero brand-kit list | get | create | extract | update | knowledge list|get|search|add|remove
contenthero template list | get | create | update | delete
contenthero kling-element list | get | create | update | delete
contenthero avatar list | get | create | update | delete | look add|remove
contenthero voice list | get
contenthero audio isolate | enhance | enhance-clips | split | split-clips
contenthero content list | get | analyze
contenthero tracked-account list | get | add | update | remove
contenthero connected-account list | get
contenthero account get | update
contenthero model list | get
contenthero schema get
For agents
schema get commands dumps every command's arguments and options as JSON, so an agent
can wire up calls without reading these docs:
contenthero schema get commands # the whole surface
contenthero schema get commands generate image # just one command
Exit codes
0 success, 1 general error, 2 usage error, 3 authentication error,
4 timeout (the work was accepted but did not finish in time), 5 a limit refused it (credits, the monthly
spend cap, storage, a plan limit; nothing ran and nothing was charged). In JSON mode a limit error also carries its
code and ranked actions.
Image controls and discovery
The existing generate image command accepts --quality, --output-format, --background, --frame-count, --frame-duration-ms, and --frame-size. Read model list and model get <id> for the selected model's current choices, defaults, conditions, format compatibility, and GIF sheet rules. --json retains the complete discovery response.
The CLI reads the selected model when --frame-count is supplied, sending a number for a slider control and a string for a select control. Frame duration is an integer in milliseconds. Send GIF controls only with GIF output. Omitted flags stay omitted. Use --cost to preview the same request without generating. The server owns model validation and its refusal text is preserved.
Video draft controls
Discover the model declaration before generating. Model lists and details include accepted inputs, input modes, the declared Draft resolution, and upgrade resolution and availability when declared. Upgrade a completed draft owned by the caller while it remains available. Shot settings are inherited and cannot change. The server enforces ownership, completion, expiration and whether the selected draft output already has an upgrade.
generate video accepts --draft, --upgrade-from-output-id, --upgrade-slot, --output-format and --return-last-frame. Omit the prompt and shot settings for an upgrade. Omitting the slot selects the first output. Add --cost to preview the same request without generating.
For generate lip-sync, read model get first. Supply --image for a model declaring singleImage, or --ref-video for a model declaring singleVideo. Add --audio, or --script with --voice. Pass --cost to preview the same request. The server validates the source required by the model.