# The reachpad CLI

> The CLI is the product interface: everything a workspace can do is a command, and your agents can run every one of them. The lifecycle is three verbs, `create`, `run` and `pause`.

Part of the reachpad docs: https://reachpad.dev/docs. Rendered page: https://reachpad.dev/docs/cli. Last checked 2026-08-13.

## Install

Homebrew on Apple silicon macOS, Linux x86_64 and Linux arm64: `brew install reachpad/tap/reachpad`.

Without Homebrew: `curl -fsSL https://reachpad.dev/install | sh`. The installer verifies the published checksum and writes to `~/.local/bin`.

## Sign in through WorkOS

Run `reachpad`. When no saved session exists, the CLI prints a short code, opens hosted WorkOS sign-in, waits for approval, saves the production endpoints and credential, then lists your workspaces. WorkOS applies the account's login, MFA and SSO policy. Reachpad receives the signed result, not the password or authentication factor.

On a remote machine or anywhere without a browser pane, run `reachpad auth login --no-browser`. Open the printed URL on another device, enter the code there, and leave the original terminal waiting. It completes the same WorkOS flow. `reachpad auth whoami` then prints who you are, which credential you hold and when it expires, your limits and your credit balance.

`reachpad auth logout` revokes this machine's credential on the server and deletes the local copy; `--all` does the same for the credentials on your other machines. If a machine cannot open a browser at all, the [connect page](https://reachpad.dev/connect) still mints a credential and shows it once: run `reachpad auth login --operator-token -` and paste it on stdin, so it never lands in shell history.

> Note: Login validates the credential before saving it with mode 0600, and saves the endpoint (`m1.reachpad.dev`) with it. No later command needs an endpoint flag. The operator-token path is recovery and automation, not the normal onboarding flow.

## Keep the CLI healthy

- `reachpad doctor` checks the binary, PATH, endpoint, credential permissions, saved configuration and live session without printing secrets.
- `reachpad update` updates a native install in place through the checksum-verifying installer. Homebrew owns what it installed, so the CLI prints `brew upgrade reachpad` for you to run.

## Shell completions

The CLI generates completions from its current command tree and writes the script to stdout. Enable it for the current shell with one of these commands:

- Bash: `source <(reachpad completions bash)`.
- Zsh: `source <(reachpad completions zsh)`.
- Fish: `reachpad completions fish | source`.

> Note: Add the matching command to your shell startup file to enable completions in future terminals.

## Workspaces

- `reachpad create [name]` creates a workspace and prints its id. The name is a label, the id is the handle, and an unnamed workspace is fine.
- `reachpad list [--state running|paused|archived|all]` shows each workspace with its state, its last save and its forks, plus the account's limits. Archived ones are hidden until you ask for them.
- `reachpad status <id>` reports one workspace: state, last save, lease, limits. `--wait running|paused|archived` blocks until it gets there or `--timeout` runs out.
- `reachpad pause <id>` saves disk and memory, then stops the meter. It returns when the save has started; `--wait` returns when the save is durable. The next `run` or `attach` resumes from it, memory included.
- `reachpad archive <id>` frees the workspace slot and stops compute use. It is not a permanent-backup promise; archived state follows the managed retention policy.
- `reachpad attach <id>` is the interactive terminal: Ctrl-C goes to the workspace, Ctrl-] detaches, and detaching leaves everything running.

> Note: Each verb also takes the workspace from `-w <id>` or `REACHPAD_WORKSPACE`, so a shell that works on one workspace names it once. Per-workspace credentials are cached under `~/.local/state/reachpad/` and re-minted when they lapse; there is nothing to fetch by hand.

## More terminals in one workspace

`reachpad attach <id> --new` opens a fresh terminal in the workspace and attaches to it; `reachpad attach <id> --list` prints the live ones. An agent in terminal 0 keeps running while you watch it from terminal 1.

## Run one command

`reachpad run <id> [--cwd DIR] [--env NAME=VALUE] [--timeout 30m] [--stdin] -- <command...>` runs one command in the workspace, waking it first if it is paused. Everything after `--` is argv, passed to the guest as a list. For a shell line, say so: `reachpad run <id> -s 'cd /repo && make'`.

The guest's stdout goes to your stdout and its stderr to your stderr, unmerged, and the process exits with the command's own exit code, so it composes in scripts. If the command was killed by its timeout or its output hit the account's cap, the CLI says which on stderr afterwards rather than leaving you to guess from a truncated log.

## Watch what a workspace is doing

`reachpad events <id>` streams the workspace's event log live, and `--since <seq>` replays committed history before the live tail. It is the log the fleet itself writes when a workspace is sealed, resumed or finishes a command, so a long run is checkable without attaching to it.

## Forks and rewind

`reachpad fork <id>` branches a new workspace from the source's last save; `--count <n>` branches several from that one save and prints an id per line, which is what makes a fan-out one command. `--snapshot <snap>` roots them at an older save instead of the current one. Every child holds a workspace slot of its own.

`reachpad ws lineage <id>` lists the retained checkpoints with their ids, and `reachpad ws rewind <id> --snapshot <snap>` moves a workspace back to one, keeping the forward history as an auto-created fork. Both keep their v0.1 spelling until they get a v1 verb. Automatic recovery history is managed rather than kept forever; retained forks and rewinds pin the checkpoints they depend on.

## API keys for agents and CI

`reachpad keys mint [--label <l>] [--role collaborator|owner] [--workspace <id>] [--ttl 30d]` prints an `rpak1.…` key once, alone on the last line, so `| tail -1` is exactly the secret. `keys list` shows the metadata afterwards and `keys revoke <id>` ends a key. With no `--workspace` the key covers the whole account.

A key runs commands and reads, pauses, archives and lists the lineage of the workspaces it names. It cannot create, list or fork workspaces, and it cannot mint another key, so a leaked key stays bounded by its scope and its expiry. Hand it to a command with `--api-key -`, `--api-key @<path>` or `--api-key env:<VAR>`: a key written out in argv is refused, because argv is readable by every other process on the machine.

## Output your agent can read

Every command takes `--json` and answers with one object: `{"ok":true,"command":"workspace.status","data":{…}}`, or a refusal carrying a code, a sentence, whether a retry could help and the next command to run. `events --json` prints one object per event and `run --json` prints one per output chunk, then the result envelope last. `-q` prints ids only, one per line, which is what feeds `xargs`.

Exit codes are semantic: 0 worked, 1 is a local failure with no answer from the fleet, 2 is usage, 3 is the credential, 4 is no such workspace, 5 is the wrong state, 6 is a limit, 7 is unavailable. `run` is the exception and the useful one: it exits with the guest command's own code, and 70 means reachpad accepted the command but lost its result, so whether it ran is unknown.
