---
name: reachpad
version: 1.0.0
description: Create, run, fork and pause persistent workspaces with the reachpad CLI or its MCP server, and publish a running port as a link. Use when software you write has to keep running after this session ends, when it needs its repository, dependencies, services, data and secrets kept together between visits, when a long build or test run should survive a disconnect, or when someone else has to be able to open what you built.
---

# reachpad

A reachpad workspace is a persistent cloud machine. Its disk outlives the VM,
so the repository, branch, dependencies, installed tools and files are all
there on the next start. A run keeps going after you disconnect, because it
executes on the fleet and not on your machine.

This file lives at https://reachpad.dev/SKILL.md. Asked to set it up, save it
to your skill directory (for example `.claude/skills/reachpad/SKILL.md`) so
it loads in future sessions, and re-fetch it when a saved copy and the product
disagree.

Snapshots are filesystem only and every start is a cold boot. Files survive a
pause; processes do not.

Claude Code, Codex and Kimi are installed in every workspace, none signed in.
Sign in to one inside the workspace with the user's own account, the way they
would on a laptop. To have reachpad make the model calls instead, the user
adds an Anthropic or OpenAI key at https://reachpad.dev/dashboard/secrets; by
default that value is brokered by reachpad and never enters the workspace. The
sheet can instead keep it in the workspace, where anything running there can
read it.

## Install and sign in

- Homebrew: `brew install reachpad/tap/reachpad`
- npm: `npm install -g @reachpad/cli`
- Neither: `curl -fsSL https://reachpad.dev/install | sh`

`reachpad` opens hosted sign-in on first run and lists
your workspaces. On a machine with no browser, `reachpad auth login
--no-browser` prints a URL and a code to enter on another device.
`reachpad auth whoami` prints who you are, which credential you hold, when
it expires, your limits and your credit balance.

## The lifecycle is three verbs

- `reachpad create [name]` creates a workspace and prints its id. The id is
  the handle; the name is only a label. Nothing is running in it yet: `reachpad
  attach <id>` opens an interactive shell in it, and `run` below sends one
  command instead.
- `reachpad run <id> -- <command...>` runs one command, waking the
  workspace first if it is paused. Everything after `--` is argv. For a shell
  line, `-s 'cd /repo && make'`. Guest stdout and stderr stay unmerged and the
  process exits with the guest command's own code.
- `reachpad pause <id>` seals the disk and stops the meter. The next
  `run` or `attach` boots the workspace from that save. Nothing else stops
  a workspace: idle auto-pause is off during the beta, so an unpaused one
  keeps billing.

Also: `list [--state running|paused|archived|all]`, `status <id> [--wait
running|paused|archived]`, `archive <id>`, and `attach <id>` for an
interactive terminal (Ctrl-] detaches and leaves everything running;
`--new` opens another terminal in the same workspace).

Verbs that act on one workspace also take it from `-w <id>` or
`REACHPAD_WORKSPACE` (`keys mint` reuses `-w` as the key's scope list).

## Move code into a workspace

Over MCP, pass `repo` and, when needed, `ref` to `create_workspace`. The
server clones the repository into `$HOME/work`. The reachpad MCP server has
no local-file upload or stdin field. Do not put a base64 archive or full file
contents in `run_command.argv`, because that makes the archive part of the
MCP tool call and its transcript.

If the client can run a local shell and the compressed input is at most about
1 MiB, use the CLI's stdin path instead:

```bash
tar --exclude=.git --exclude=node_modules -czf - . | reachpad run <workspace-id> --stdin -s 'tar -xzf - -C "$HOME/work"'
```

For a larger or repeatedly changing tree, push to a Git remote and clone it.
From the CLI, `reachpad create --repo <owner>/<name>` clones on create,
once `reachpad connect github` has linked the account. The full decision
is at https://reachpad.dev/docs/mcp.md, which links the repository
authentication rules.

## Parallel work

`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 how one prepared workspace becomes a fan-out. `--snapshot <snap>`
roots them at an older save. `reachpad ws lineage <id>` lists retained
checkpoints and `reachpad ws rewind <id> --snapshot <snap>` moves a
workspace back to one (rewind takes its id positionally, never from `-w`).

## Publish a port

`reachpad ports expose <port> [workspace]` opens a port your app listens
on and prints the link that reaches it. Anyone who has the link AND is signed
in to reachpad can open it; re-exposing an open port returns the same link.
`ports list` shows what is open. `ports revoke <port>` closes one, and a
later re-expose mints a new link.

## Reading the results

`--json` on any command answers 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.
`run --json` prints one object per output chunk and the envelope last;
`events <id> [--since <seq>]` streams one object per event with no envelope,
which is how a long run is checkable without attaching to it. `-q` prints ids
only (`keys mint` still prints the minted key).

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

## Calling it without the CLI

- MCP: `https://reachpad.dev/mcp`, streamable HTTP with an OAuth token, or
  `npx @reachpad/mcp` over stdio. Tools cover create, list, inspect, run,
  fork, pause, archive and the credit balance, plus expose/list/revoke for a
  port. Two tool names differ from the CLI verbs: fork is
  `checkpoint_workspace` and archive is `delete_workspace`. Tool arguments,
  code-transfer paths and limits are documented at
  https://reachpad.dev/docs/mcp.md.
- REST: `https://m1.reachpad.dev/v1` with `Authorization: Bearer <key>`.
  `reachpad keys mint` issues a scoped, expiring key for an agent or a CI
  job. Pass it with `--api-key -`, `--api-key @<path>` or
  `--api-key env:<VAR>`; a key spelled out in argv is refused.

How to get either credential: https://reachpad.dev/auth.md

## Rules for agents

1. **Pause the workspace the moment the job is done.** Nothing else stops the
   meter: idle auto-pause is off during the beta, and an unpaused workspace
   keeps billing.
2. **Parse `--json`, never the human output**, and `-q` when you only need
   ids. A refusal names a code, whether a retry can help, and the next command.
3. **Treat exit 70 as unknown, not as failure.** Reachpad accepted the command
   and lost the result; check `status` before running it again.
4. **Fan out by forking, not by rebuilding.** Prepare one workspace, then
   `fork --count <n>` from its save; do not hand-assemble copies.
5. **Move code by clone or the stdin tar path.** Never inline file contents or
   a base64 archive in an MCP tool call.
6. **Keep credentials out of argv.** Mint scoped keys with `keys mint` and
   pass them as `--api-key env:<VAR>`; a key spelled in argv is refused.
