---
name: agent-cli
description: Install and drive the transcribe-so CLI (0.2.0) from agents and scripts - JSON on stdout, meaningful exit codes, quote before create, a required spend cap on `run`, and the full transcript, captions and who-said-what search.
---

# Use the transcribe-so CLI

A command-line client for https://transcribe.so. This skill owns the CLI. The
same operations over plain HTTP or MCP are the `transcribe-audio`,
`get-transcript` and `connect-mcp` skills.

## Hard rules (read first)

- Check the price before creating a job. Stay within the user's authorized
  budget; ask before exceeding it or starting another paid attempt.
- `create`, `run` and `retry` spend money. `quote` does not.
- Two ceilings. `--max-usd` is required on `run` and is LOCAL: the free quote
  is checked first and the CLI refuses (exit 6) before anything is created.
  `--max-charge-usd` on `create`, `run` and `retry` is the SERVER ceiling,
  enforced at the wallet hold (exit 7, nothing charged). `run` sends its
  `--max-usd` as the server ceiling too, unless you pass `--no-server-ceiling`.
  Never raise either ceiling yourself after a refusal.
- `create` returning `status: "queued"` is SUCCESS. Re-submitting charges again;
  call `wait` instead.
- `retry <id> --yes` re-charges from scratch. Confirm with the user first, and
  pass `--max-charge-usd` again: the create call's ceiling does not carry over.

## Install and authenticate

```
npm install -g transcribe-so
export TRANSCRIBE_API_KEY=tsk_live_...
transcribe-so auth:status
```

`TRANSCRIBE_API_KEY` holds a Bearer API key (`tsk_live_*`). There is no
interactive login. Where to create keys: https://transcribe.so/auth.md

## Workflow

```
transcribe-so quote --source youtube --url https://...       # free, price first
transcribe-so create --source youtube --url https://... --max-charge-usd 2   # charges; prints the job id
transcribe-so wait <id>                                      # blocks until terminal
transcribe-so result <id>                                    # chapters + sections + cited Q&A
transcribe-so transcript <id> > talk.txt                     # the complete transcript
```

One-shot: `transcribe-so run --source youtube --url ... --max-usd 2.00` does
quote, create, wait and result in one call and refuses locally if the quote is
over the cap.

Local files: `transcribe-so upload <file>` first, then pass the returned
`upload_id` and the duration to `create`. Never pass a local path to `create`.

## Output contracts

Stated once, here:

- Every command prints a JSON envelope to stdout. Progress and chatter go to
  stderr, so `stdout` is always parseable.
- Three raw-output exceptions print the body with no envelope, so it can be
  piped to a file: `subtitles <id>` (SRT / VTT / karaoke VTT / JSON),
  `transcript <id>` (txt or md) and `captions <id>` (unless `--json`).
- Exit codes: `0` ok, `1` error, `2` usage, `3` auth, `4` payment (402,
  insufficient funds, spend cap), `5` transient (429 or 5xx, safe to retry),
  `6` local budget (the `--max-usd` preflight refused), `7` server charge
  ceiling (`max_charge_exceeded`: nothing held, no job; report
  `error.charge_usd` and ask).

## Commands in 0.2.0

`auth:status`, `me`, `capabilities`, `pipelines`, `quote`, `create`,
`wait <id>`, `result <id>`, `run`, `list`, `get <id>`, `delete <id> --yes`,
`retry <id> --yes`, `upload <file>`, `transcript <id>`, `subtitles <id>`,
`captions <id> --for <destination>`, `search <q>`, `ask <id> -q "..."`.

- `transcript <id> [--format txt|md] [--no-speaker-labels] [--no-timestamps]
  [--out FILE] [--wait-seconds N]`: the complete transcript, never capped.
- `captions <id> --for instagram|x|threads|linkedin|youtube|spotify|apple_podcasts|markdown|plain
  [--variant standard|highlights|clips|quoted_sections|show_notes|original]
  [--json] [--regenerate]`: paste-ready post text or chapter list.
- `search <q> [--id <id>] [--limit N] [--offset N]`: who said what, and when.
  Each hit carries `speaker`, `start_ms`, `end_ms` and a deep-link `url`.
- `capabilities`: account, pipeline catalog, every accepted format value and
  the exit codes, in one JSON object.

`create`, `run` and `retry` send an `Idempotency-Key` on every call
(auto-generated per invocation). Pass `--idempotency-key` on those commands to
reuse one across processes, which is what makes a re-run after a lost response
safe instead of a second charge.

## Gotchas

- Three different things are called "captions": social post text
  (`captions <id> --for ...`, the `/timestamps` endpoint), timed subtitle files
  (`subtitles <id>`), and a captioned video (`/clips`, HTTP or MCP only).
- A 409 `not_ready` carries a `reason`. Only `transcription_processing`
  resolves by waiting (`transcript --wait-seconds N` does it for you). For
  `captions`, `artifact_missing` is fixed by ONE `--regenerate`, which replaces
  the cached caption variants and uses 1 of 10 regenerations per
  transcription. Never loop on it.
- `ask` consumes the account's daily Q&A allowance, not the wallet, and a
  quota error exits `1` (not `5`): the allowance frees up in hours, so stop
  rather than retry.
- `result <id>` returns analysis with windowed segments, not a full-text field.
  For the complete transcript use `transcript <id>`.
- Speaker labels are recording-local: `SPEAKER_00` in one transcription is not
  the same person in another, and `null` means unknown.

## Quick reference

- Source and full command reference:
  https://github.com/shsunmoonlee/transcribe-agent
- Install page (skill, Claude Code plugin, CLI): https://transcribe.so/agent
- Auth guide: https://transcribe.so/auth.md
- Developer docs: https://transcribe.so/developers/docs
