> For the complete documentation index, see [llms.txt](/llms.txt)

# The generated CLI

From the same [Glotto IR](/docs/glotto-ir) as your SDKs, docs site, and MCP server, Glotto
generates a **command-line client for your API**: a zero-dependency, executable Node.js script
(Node ≥ 20, `node:` builtins and global `fetch` only), plus a `package.json` with a `bin` entry
and shell-completion scripts. What you ship isn't a one-time scaffold — every regeneration
re-derives the command tree, flags, and auth wiring from your spec, and the
[drift gate](/docs/drift-detection) proves the committed artifact never lags it.

Enable it in `glotto.yml`:

```yaml
targets:
  cli:
    binary_name: acme # optional; defaults from your API name
```

`glotto generate` then writes `<out>/cli/` — `cli.js`, `package.json`, `README.md`, and
`completions/` — installable with `npm install -g .` or runnable directly with
`node cli.js <command>`.

## One command per operation

Every operation becomes a command named by its resource path plus method — subresources nest
(`acme events batches list`), and client-level methods surface at the root. Parameters map to
flags by wire name: path parameters interpolate into the URL, query parameters land on the query
string (array parameters repeat, honoring `query_settings.array_format`), header parameters
become request headers, and cookie parameters fold into a `Cookie` header. `--help` (globally or
per command) prints the derived command list and flags.

## Auth and environments

Auth resolves like the SDKs, from the same spec: bearer/OAuth2 tokens, API keys (header or
query, honoring the declared name), and HTTP basic — including per-endpoint security overrides
on multi-scheme APIs. Credentials come from per-scheme environment variables (or `--api-key`).
For OAuth2 schemes that declare a `clientCredentials` flow, the CLI performs the token handshake
itself: set `<BINARY>_CLIENT_ID` and `<BINARY>_CLIENT_SECRET` (or pass
`--client-id`/`--client-secret`) and it exchanges them at your token endpoint before the
request. Environments come from your spec too — select one with `--environment <name>` or
override with `--base-url <url>`.

## Output, streaming, and exit codes

Successful JSON responses pretty-print to stdout; streaming operations (SSE/NDJSON) pass the raw
response body through as it arrives, so output pipes cleanly into `jq` or a file. Usage errors
exit `2`, request failures exit `1`, success exits `0` — script-friendly by construction.

## Uploads

Request bodies follow the operation's declared content type. JSON bodies take `--data <json>` or
`--data @file`; raw bodies (`application/octet-stream` and friends) take `--data @file` for file
bytes or inline `--data` for text; `multipart/form-data` operations take repeated
`--field <name>=<value>` flags, where a value starting with `@` attaches that file as a file
part.

## Pagination

Commands for paginated operations accept `--all`, which walks every page using the same
pagination locators the SDK iterators use — cursor, cursor-id, page/offset, and `Link`-header
strategies — and prints the concatenated items as a single JSON array.

## Retries

The CLI honors the same retry policy as your SDKs (`client_settings.retry`): exponential backoff
with jitter, `Retry-After` honored, applied to network failures and 408/409/429/5xx responses on
GET commands and operations your spec marks idempotent.

## Shell completions

Bash, zsh, and fish completion scripts for the full command tree and per-command flags are
emitted beside the CLI under `completions/` — the emitted README documents where each installs.

## Kept true, not just generated

Like every Glotto artifact, the CLI is a deterministic projection of your spec: byte-stable
output, locked by golden tests, regenerated in lockstep with your SDKs and docs, and verified by
the same [drift detection](/docs/drift-detection) and compile-verification gates. Add an
operation, rename a parameter, tighten auth — the CLI is provably current on the next
regeneration, forever.
