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

# Reply CLI

> The Reply.io command line — sign in once, then run any v3 API call as yourself from your terminal, your scripts, or CI.

[`reply`](https://www.npmjs.com/package/reply-cli) is the official command-line interface for
Reply.io. Sign in once and every request runs as you. Today it covers **authentication and
identity**, [`reply api`](#raw-api-access) gives you authenticated access to the full
[v3 API](/api-reference/introduction) — no HTTP client, no header wrangling — and
[`reply skills`](#skills) installs Reply's agent skill packs into your AI assistants. Higher-level
commands for sequences, contacts, and the inbox are on the way.

|             |                                                                            |
| ----------- | -------------------------------------------------------------------------- |
| **Package** | [`reply-cli`](https://www.npmjs.com/package/reply-cli) (npm)               |
| **Command** | `reply`                                                                    |
| **Runtime** | Node.js 20 or newer                                                        |
| **Auth**    | OAuth browser login, or an API key                                         |
| **Output**  | Human-readable by default; `--json` / `--pretty` for machines              |
| **Source**  | [github.com/reply-team/reply-cli](https://github.com/reply-team/reply-cli) |
| **Status**  | Pre-1.0 — see [Versioning](#versioning)                                    |

## Install

```bash theme={null}
npm install -g reply-cli     # installs the `reply` command (Node 20+)
reply --version
```

Or run it without installing:

```bash theme={null}
npx -y reply-cli auth login
```

## Authenticate

Log in through your browser — no key to copy, no key to rotate:

```bash theme={null}
reply auth login
```

Prefer an API key? Read it from stdin so it never lands in your shell history:

```bash theme={null}
reply auth login --with-token
```

Keys come from Reply → **Settings → API Keys**; scopes and key types are covered in
[Authentication](/api-reference/authentication).

Inspect and manage the active credential:

```bash theme={null}
reply auth status     # who you're signed in as, and how — no secrets shown
reply auth whoami     # validate the stored credential against the API
reply auth logout     # remove the stored credential
```

### Credential precedence

Resolved in strict order, first hit wins:

1. `--api-key <key>` flag
2. `REPLY_API_KEY` environment variable
3. the stored credential from `reply auth login`

The flag and the environment variable are used for that one invocation and are never written to
disk.

<Note>
  There is no `.env` file lookup — export `REPLY_API_KEY` yourself, or store a credential with
  `reply auth login`.
</Note>

### Where credentials live

Credentials are stored as JSON in `~/.config/reply` (`%APPDATA%\reply` on Windows), written `0600`
inside a `0700` directory — the same plaintext-file model as `gh`, `aws`, and `az`. OAuth tokens
refresh automatically; if a refresh fails the record is cleared and you're asked to log in again.
Tokens and keys are redacted in every command's output, `--verbose` included.

## Profiles — more than one Reply.io user

A profile is a signed-in account. Profiles let you keep several Reply.io users authenticated at
once and switch between them, each with its own stored credential. Most people never need one: the
default profile is used until you create another.

Name them however you like — account emails work well:

```bash theme={null}
reply profile add alice@reply.io
reply profile use alice@reply.io           # make it the active profile
reply auth login                           # signs in alice@reply.io

reply profile list                         # '*' marks the active profile
reply --profile bob@reply.io auth whoami   # override for a single command
```

The active profile resolves as `--profile` → `REPLY_PROFILE` → the profile set with
`profile use` → the built-in default.

Manage them after creation:

```bash theme={null}
reply profile show                         # the active profile — team, auth method, no secrets
reply profile show alice@reply.io          # a specific one
reply profile rename alice@reply.io ally   # also moves the stored credential
reply profile delete ally                  # removes it and its stored credential
```

## Teams

A profile can pin a team (workspace). The pinned team is sent as the `X-TEAM-ID` header, with
precedence `--team-id` → `REPLY_TEAM_ID` → the profile's team. The `team` command reads and writes
the **active profile's** team:

```bash theme={null}
reply team list            # teams you can act in ('*' marks the profile's team)
reply team current         # the pinned team, plus the effective team from whoami
reply team use 1045        # verify 1045 is one of your teams, then pin it
reply team clear           # remove the pin
```

If a call needs a team and you belong to more than one, the API answers with a `TEAM_REQUIRED`
error listing your teams — run `reply team use <id>` to pin one, or pass `--team-id <id>` for a
single command.

## Raw API access

`reply api` is a raw, authenticated passthrough to any v3 endpoint — the escape hatch for
everything the CLI has no dedicated command for yet.

Use the path exactly as it appears in the [API reference](/api-reference/introduction), starting
with `/v3`; the query string goes in the path. A `--body` switches the method to `POST` (override
with `--method`), and it accepts inline JSON, `@file`, or `-` for stdin.

```bash theme={null}
reply api /v3/whoami                              # your identity + team
reply api /v3/sequences                           # list sequences
reply api /v3/contacts --pretty                   # list contacts, indented
reply api /v3/sequences/12345                     # one sequence by id
reply api /v3/contacts --body @contact.json       # create a contact (POST)
echo '<json>' | reply api /v3/contacts --body -   # body from stdin
reply api /v3/whoami --verbose                    # full request/response on stderr
```

It prints `{ "code": <status>, "data": <body> }` and exits non-zero on HTTP `>= 400`. See
[Using the CLI from agents & scripts](/cli/agents) for the full machine contract.

## Skills

Reply's outbound expertise ships as three markdown skill packs in
[reply-skills](https://github.com/reply-team/reply-skills). `reply skills` detects the AI assistants
on your machine and installs the packs into each one, resolving dependencies itself:

```bash theme={null}
reply skills install
```

```
✓ detected Claude Code, Codex
✓ Claude Code · ai-sdr-core, reply-adapter, agentic-runtime installed
✓ Codex       · ai-sdr-core, reply-adapter, agentic-runtime installed
Start a new session in each assistant so the skills load.
```

| Pack              | Alias     | What it gives your agent                                 |
| ----------------- | --------- | -------------------------------------------------------- |
| `ai-sdr-core`     | `core`    | Vendor-neutral SDR operations, playbooks, and guardrails |
| `reply-adapter`   | `adapter` | Executing those operations against Reply.io              |
| `agentic-runtime` | `runtime` | Durable multi-session work: plans, checkpoints, reports  |

Naming no pack installs all three. Dependencies come along automatically, so `adapter` pulls `core`:

```bash theme={null}
reply skills install core
reply skills install adapter runtime
reply skills install --agent codex        # only this assistant
reply skills install --project            # into this repository, not your home directory
```

Then manage them:

```bash theme={null}
reply skills list             # what's installed where, and what has an update available
reply skills update           # bring installed packs to the latest version
reply skills remove runtime   # remove one pack
reply skills remove           # remove all of them
```

On Claude Code and Codex the packs are installed through the assistant's own plugin mechanism, so
they keep updating through it. Other `SKILL.md` hosts receive the skills as copied files. Add
`--json` for a machine-readable report and `--dry-run` to see the plan without changing anything.

| Assistant      | `--agent` id     | How it receives the packs                             | Paths verified |
| -------------- | ---------------- | ----------------------------------------------------- | -------------- |
| Claude Code    | `claude-code`    | its own plugin CLI                                    | Yes            |
| Codex          | `codex`          | its own plugin CLI (`--project` copies files instead) | Yes            |
| Cursor         | `cursor`         | copied files                                          | Not yet        |
| Gemini CLI     | `gemini-cli`     | copied files                                          | Not yet        |
| GitHub Copilot | `github-copilot` | copied files                                          | Not yet        |
| Windsurf       | `windsurf`       | copied files                                          | Not yet        |

<Note>
  **"Not yet" means that assistant's skills directory comes from its own documentation** and has not
  been confirmed by a verification run — the install works, but Reply cannot promise the assistant
  reads from where the files were put. Those hosts are marked `(paths not yet verified)` in the
  report and carry `"verified": false` in `--json`.
</Note>

Removing a pack another installed pack depends on is refused — remove both, or run
`reply skills remove` with no pack to remove everything.

<Note>
  Installing skills is not the same as connecting Reply: `reply-adapter` needs a Reply.io credential
  (`reply auth login`) to do anything. See [Reply Skills](/skills/overview).
</Note>

## Command reference

Run `reply <command> --help` for the exact flags of any command — the installed help always matches
your version.

### `reply auth`

| Command                         | Description                                                            |
| ------------------------------- | ---------------------------------------------------------------------- |
| `reply auth login`              | Log in via OAuth in the browser                                        |
| `reply auth login --with-token` | Store an API key read from stdin                                       |
| `reply auth status`             | Active credential source, method, user, and OAuth expiry — no secrets  |
| `reply auth whoami`             | Validate the active credential against the API and print the principal |
| `reply auth logout`             | Remove the stored credential                                           |

### `reply profile`

| Command                                   | Description                                                          |
| ----------------------------------------- | -------------------------------------------------------------------- |
| `reply profile add <name>`                | Create a profile (`--team-id` optionally pins a team)                |
| `reply profile use <name>`                | Make it the active profile, used until changed                       |
| `reply profile list`                      | List profiles; `*` marks the active one                              |
| `reply profile current`                   | Print the active profile name                                        |
| `reply profile show [name]`               | Show a profile's team and authorization — no secrets                 |
| `reply profile set <name> --team-id <id>` | Pin a team on a profile                                              |
| `reply profile unset <name> team-id`      | Clear the pinned team                                                |
| `reply profile rename <old> <new>`        | Rename a profile and move its stored credential                      |
| `reply profile delete <name>`             | Delete a profile and its stored credential (`-y` to skip the prompt) |

### `reply team`

| Command               | Description                                             |
| --------------------- | ------------------------------------------------------- |
| `reply team list`     | Teams you can act in                                    |
| `reply team current`  | The active profile's pinned team and the effective team |
| `reply team use <id>` | Pin a team (verified against your teams)                |
| `reply team clear`    | Remove the pin                                          |

### `reply api`

| Command                                    | Description                                                       |
| ------------------------------------------ | ----------------------------------------------------------------- |
| `reply api <path>`                         | Raw authenticated request to a v3 endpoint; prints `{code, data}` |
| `reply api <path> --body <json\|@file\|->` | Send a body (switches the method to `POST`)                       |
| `reply api <path> --method <verb>`         | Override the HTTP method                                          |

### `reply skills`

| Command                           | Description                                                      |
| --------------------------------- | ---------------------------------------------------------------- |
| `reply skills install [packs...]` | Install packs into every detected assistant (default: all three) |
| `reply skills list [packs...]`    | Show which packs are installed in which assistant                |
| `reply skills update [packs...]`  | Update installed packs to the latest published version           |
| `reply skills remove [packs...]`  | Remove packs from your assistants (default: all of them)         |

Pack names accept aliases: `core`, `adapter`, `runtime`. These flags apply to all four subcommands:

| Flag                  | Effect                                                             |
| --------------------- | ------------------------------------------------------------------ |
| `-a, --agent <id...>` | Target these assistants instead of auto-detecting                  |
| `--project`           | Install into the current repository instead of your user directory |
| `--dry-run`           | Show what would happen and change nothing                          |

### Global flags

| Flag                   | Effect                                                                                             |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| `-k, --api-key <key>`  | Use this key for one invocation; overrides the env var and stored credential                       |
| `-p, --profile <name>` | Run as this profile for one invocation                                                             |
| `--team-id <id>`       | Team/workspace to act in, sent as `X-TEAM-ID`                                                      |
| `--user-id <id>`       | Act as this user id — [organization API keys](/api-reference/authentication#special-api-keys) only |
| `--user-email <email>` | Act as this user email — organization keys only; requires a team id                                |
| `--json`               | Compact JSON on stdout                                                                             |
| `--pretty`             | Indented JSON on stdout                                                                            |
| `--verbose`            | Full request/response on stderr, credentials redacted                                              |
| `-q, --quiet`          | Suppress progress messages on stderr; warnings and errors still shown                              |
| `-v, --version`        | Print the CLI version                                                                              |

### Environment variables

| Variable           | Description                                                                |
| ------------------ | -------------------------------------------------------------------------- |
| `REPLY_API_KEY`    | API key used as the credential for the current invocation                  |
| `REPLY_PROFILE`    | Profile to use (same as `--profile`)                                       |
| `REPLY_TEAM_ID`    | Team/workspace id sent as `X-TEAM-ID` (same as `--team-id`)                |
| `REPLY_CONFIG_DIR` | Config directory (default `~/.config/reply`; `%APPDATA%\reply` on Windows) |

## Why a CLI when there's REST and MCP?

* **Authentication is the hard part, and it's solved here.** Browser login, token refresh, multiple
  accounts, and the team header are handled for you — `reply api` is a `curl` that is already
  authenticated as the right user in the right workspace.
* **Coding agents are exceptionally good at shell commands.** They get composability — pipes, `jq`,
  cron — without writing an HTTP client. See [Using the CLI from agents](/cli/agents).
* **Scriptable one-offs.** Terminal and CI access to the API for work that doesn't warrant a real
  integration.

## What isn't in the CLI yet

There are no dedicated commands for sequences, contacts, the inbox, or reporting yet — reach them
through `reply api` today, or use the interface that fits:

| Need                                  | Where today                                               |
| ------------------------------------- | --------------------------------------------------------- |
| Any v3 endpoint, authenticated        | `reply api /v3/…`                                         |
| A tool surface for LLM agents         | [Reply MCP](/mcp/overview)                                |
| Procedure and guardrails for an agent | [Reply Skills](/skills/overview) — `reply skills install` |
| Your own integration                  | [REST API](/api-reference/introduction)                   |
| Event-driven automation               | [Webhooks](/webhook-events)                               |

## Versioning

`reply-cli` follows [semantic versioning](https://semver.org), with versions derived from
Conventional Commits.

<Note>
  **Pre-1.0.** While the version is `0.x` the CLI is still stabilizing, so — per semver's 0.x rule —
  a minor release (`0.x.0`) may contain breaking changes. Pin an exact version if you need stability
  before `1.0.0`.
</Note>

From `1.0.0` onward, a major bump is required to remove or rename a command, flag, or argument;
change the meaning of an exit code; change the `--json` / `--pretty` output shape; change the config
format or a `REPLY_*` environment variable; or raise the minimum Node.js version. New commands, new
optional flags, and new fields in `--json` output are additive and ship in minor releases.

## Links

* Package: [npmjs.com/package/reply-cli](https://www.npmjs.com/package/reply-cli)
* Source and issues: [github.com/reply-team/reply-cli](https://github.com/reply-team/reply-cli)
* Next: [Using the CLI from agents & scripts](/cli/agents)
