> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pyai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PyAI CLI

> Render speech, transcribe files, run Dub jobs, and manage PyAI from your terminal. Shortcuts, browser login, JSON output, and agent-ready project starters.

Use PyAI's voice APIs directly from a terminal. Turn a script into a voiceover,
get a transcript from a recording, or carry a Dub job through to its downloaded
audio. Engineers and coding agents use the same commands and API contract.

<Note>
  The CLI is included in `@pyai/sdk` 0.5.0. It supports browser sign-in, saved
  profiles, and environment keys for coding agents and CI.
</Note>

## Install

Use Node.js 22 or newer for the recommended setup:

```bash theme={null}
npm install -g @pyai/sdk@0.5.0
pyai --version
pyai login
pyai --help
```

The compiled executable supports Node.js 18 or newer. Use
`pyai schema --json` to inspect the installed command surface. See the
[full handbook](https://pyai.com/cli.md) for source builds and local packages.

## Go from text to audio

With `PYAI_API_KEY` provided by your secret manager:

```bash theme={null}
pyai whoami -j
pyai speak "Your appointment is confirmed." -o confirmation.wav
pyai hear confirmation.wav --text-only
```

Need an isolated sandbox first? `pyai auth sandbox -p sandbox` creates an
organization and saves its key privately. Reuse that profile for later work;
each sandbox creation creates a separate organization. Review its returned
scopes before selecting a product.

```bash theme={null}
pyai voices --language en -j
pyai speak --text-file script.txt --format mp3 -o narration.mp3
printf '%s\n' 'The build is ready.' | pyai speak -o build.wav
pyai transcribe meeting.wav --text-only > meeting.txt
```

Use a voice ID returned by `voices` with `--voice`. Speech defaults to WAV;
changing the extension does not change the audio format. Use `--format` for
MP3, WAV, Opus, AAC, FLAC, PCM, or G.711 output. Transcription accepts a local path or an HTTP(S) URL as its
positional input; a URL selects an asynchronous job, so add `--wait` when
you need the finished transcript. Files written through `--out`
are not overwritten unless you pass `--force`. Shell redirects such as
`> meeting.txt` follow your shell's overwrite behavior.

## Sign in through the browser

On a deployment with browser authentication enabled:

```bash theme={null}
pyai login -p work
pyai whoami -p work -j
```

The CLI displays a code and opens the console. Sign in with your existing
email or Google login, match the code, select a project, and approve access.
An owner or admin can approve a 30-day credential with the displayed scopes.
The key is saved privately in your profile and never appears in the browser URL
or login receipt. Revoke it through the console's API Keys screen.

For SSH or a container, use `pyai login --no-browser -p remote`. Open the printed
link on another device and approve the matching code. The CLI polls outbound;
no callback port or port forwarding is needed. Login requests expire after ten
minutes; `--login-timeout` can shorten the local wait.

Unattended CI and coding agents can use `PYAI_API_KEY` directly. To save an
existing key without putting it in command arguments:

```bash theme={null}
printf '%s\n' "$PYAI_API_KEY" | pyai login --key-stdin -p work
pyai profiles -j
pyai use work
```

An exported `PYAI_API_KEY` overrides a stored profile's key, including when `-p`
is supplied. `PYAI_BASE_URL` and `--base-url` select a deployment. `pyai logout
-p work` removes local credentials; it does not revoke the key server-side.

## Dub through to a file

Check currently enabled source and target languages first:

```bash theme={null}
pyai request GET /healthz/dub -j
```

When the language pair is listed and your key has `dub:render`:

```bash theme={null}
pyai dub interview.wav --from en --to hi -o interview-hi.wav --wait-timeout 600
```

This submits once, polls with a deadline, and downloads completed audio. The
explicit job commands remain useful for separate CI stages or resuming work:

```bash theme={null}
pyai dub create -f interview.wav --language hi --source-language en -j
pyai dub wait DUB_JOB_ID --wait-timeout 600 -j
pyai dub audio DUB_JOB_ID -o dubbed.wav -j
```

A wait timeout does not cancel the remote job. Inspect the job path returned in
the error and resume waiting instead of blindly resubmitting.

## Review API configuration as JSON

```bash theme={null}
pyai agents create --data @agent.json --dry-run -j
pyai agents create --data @agent.json -j
pyai agents get AGENT_ID -j
pyai agents update AGENT_ID --data @agent-update.json -j
```

`--data` accepts inline JSON, `@file.json`, or `@-` for stdin. Dedicated
mutations expect an object. `--dry-run` validates local input and shows the
planned request without sending it. It does not prove remote authorization or
server schema validity. Explicit delete and cancel commands do not prompt for
terminal confirmation.

The CLI also covers transcription jobs, cloned voices, voice design, Cast,
Recap, Trace, tools, Hear vocabulary, and AMD configuration and call records.
Discover exact flags with `pyai GROUP --help` or `pyai help all`.

## Shortcuts that stay predictable

| Short form                              | Meaning                                            |
| --------------------------------------- | -------------------------------------------------- |
| `login`, `logout`, `whoami`, `use NAME` | Authentication and profile selection               |
| `speak "Text"`                          | Speech without a separate `--text` flag            |
| `hear FILE`                             | Alias for `transcribe --file FILE`                 |
| `say "Text"`                            | Optional alias for `speak`                         |
| `voices`, `models`, `profiles`          | List the corresponding collection                  |
| `-o`, `-f`, `-t`, `-p`, `-j`            | `--out`, `--file`, `--text`, `--profile`, `--json` |

Use separate short options with a space before each value. `pyai recipes`
shows an offline cookbook; `pyai recipes speak` narrows it to a task. Recipe
names are `auth`, `speak`, `transcribe`, `dub`, `agent`, `inspect`, and `ci`.
Displaying recipes makes no API calls.

## Give a coding agent the right context

```bash theme={null}
pyai init voice-project
pyai init voice-ts --template typescript
pyai init voice-python --template python
pyai schema agents create -j
pyai schema --openapi -j > openapi.json
```

`init` creates a new directory containing `PYAI.md` and starter assets. The
parent directory must exist. The default template is `agent`; creation is
offline and does not install dependencies, save credentials, or call an API.
Follow the generated README to run the starter.

`schema` describes the installed CLI offline. Filter it to a command or group
to give an agent only the syntax it needs. `schema --openapi` retrieves the
configured deployment's API contract. Use `pyai request METHOD /PATH` for routes
without a dedicated command. API paths stay on the configured origin.

Give your agent this instruction:

> Read PYAI.md and inspect `pyai schema --json`. Fetch the live OpenAPI before
> constructing API bodies. Use PYAI\_API\_KEY without printing it. Discover
> voices, preview mutations with --dry-run, and use bounded waits. Return a
> runnable verification command and handle stable error codes.

## Script output and failure handling

`--json` writes one command result to stdout and structured errors to stderr.
Audio commands save bytes to a file and return a receipt with `path`, `bytes`,
and `content_type`. `--out -` streams raw bytes and is incompatible with JSON.
`transcribe --text-only` emits plain transcript text; URL jobs require `--wait`
for text-only output. Large results may require reading the returned `result_url`.

| Exit  | Meaning                                        |
| ----- | ---------------------------------------------- |
| `0`   | Success                                        |
| `1`   | API, job, or operational failure               |
| `2`   | Invalid arguments or local configuration/input |
| `3`   | Authentication or permission failure           |
| `4`   | Network failure or timeout                     |
| `130` | Interrupted                                    |

Branch on the error's `code`, not its message. HTTP `status`, `request_id`, and
job `path` are included when available. Browser login also emits public JSON
events on stderr while waiting, so treat its stderr as newline-delimited JSON.

`--timeout` defaults to 30 seconds per HTTP request, `--wait-timeout` to 120
seconds per wait, and `--poll-interval` to 2 seconds. Only reads are automatically
retried; mutations are not retried. Idempotency support is determined by each
API route. List commands return one page; continue with the returned
`next_cursor` as `--cursor`.

`pyai doctor` checks credentials, catalogs, and a Speak-to-Hear round trip;
`pyai smoke` makes a smaller synthesis check. Both consume applicable API usage.
Use `--dry-run` to inspect their request plans without calling the API.

## Further reading

* [Full CLI handbook, raw Markdown](https://pyai.com/cli.md)
* [CLI integration guide for coding agents](https://pyai.com/cli-agent-guide.md)
* [Downloadable CLI schema snapshot](https://pyai.com/cli-schema.json)
* [CLI overview](https://pyai.com/cli)
* [TypeScript and Python SDKs](/guides/sdks)
* [MCP setup for Cursor and other coding agents](/guides/use-pyai-in-cursor)
* [API source of truth](https://api.pyai.com/openapi.json)

The CLI works with files, REST resources, and asynchronous jobs. Use the SDK
for live microphone input, Hear streams, Omni conversations, and AMD streams.
