# CLI

The RouterPlus CLI connects your coding tools to the gateway. You approve a key in the browser
once. The CLI stores the key and writes it into each tool's settings. The CLI also has a
coding agent of its own.

The CLI needs Node 24 or later. It has no other dependencies. Run it from a checkout of the
RouterPlus repository:

```bash
node tools/routerplus-cli/main.ts <command> [options]
```

## Commands

| Command | What it does |
|---|---|
| `login` | Opens the consent page, receives the approved key and stores it. |
| `setup <tool>` | Writes a tool's settings to use RouterPlus with the stored key. Tools: `claude-code`, `codex`, `cursor`, `opencode`, `cline`. |
| `status` | Shows the key's prefix, its usage and limit, and the tools that use RouterPlus. |
| `logout` | Deletes the stored key. With a management key, it also revokes the key. |
| `code [prompt]` | Starts a coding agent in the current directory. See [Coding agent](#coding-agent). |

## Log in

```bash
node tools/routerplus-cli/main.ts login
```

1. The CLI starts a server on `127.0.0.1`, on a random port, to receive the approval.
2. The CLI opens the consent page in your browser and prints its URL. If the browser does not
   open, copy the URL.
3. Sign in, select a workspace and click **Approve**. You can set a spending limit on the same
   page.
4. The browser returns to the CLI. The CLI exchanges the one-time code for a key with
   [OAuth PKCE](/docs/oauth).
5. The CLI stores the key in `~/.config/routerplus/credentials.json` with mode `0600`.

The approval must arrive within 5 minutes. The CLI never prints the key. It shows only the
first 12 characters.

| Option | Meaning |
|---|---|
| `--no-browser` | Print the URL and do not open a browser. Use this on a remote machine with port forwarding. |
| `--limit USD` | Ask for a spending limit, for example `25`. You can change it on the consent page. |

## Set up a tool

```bash
node tools/routerplus-cli/main.ts setup claude-code --dry-run
node tools/routerplus-cli/main.ts setup claude-code
```

`--dry-run` shows the lines that would change and writes nothing. Without `--dry-run`, the CLI
does these steps for each file it changes:

1. It copies the file to `<file>.bak`.
2. It writes the new file with mode `0600`.
3. It shows the lines it changed. The key shows as its prefix.

A second `setup` for the same tool changes nothing. The settings are the same as in
[Coding agents](/docs/install):

| Tool | What `setup` writes |
|---|---|
| `claude-code` | `~/.claude/settings.json`: `env.ANTHROPIC_BASE_URL` (`https://demo-api.routerplus.com`, without `/v1`) and `env.ANTHROPIC_AUTH_TOKEN`. It removes `env.ANTHROPIC_API_KEY`, because that variable makes Claude Code open its login screen. Other settings stay. |
| `codex` | `~/.codex/config.toml`: `model_provider = "routerplus"` and a `[model_providers.routerplus]` table with `base_url` `https://demo-api.routerplus.com/v1`, `wire_api = "responses"` and the key in `experimental_bearer_token`. It sets `model = "gpt-6-luna"` only when the file has no model. Other tables stay. |
| `opencode` | `~/.config/opencode/opencode.json`: `provider.routerplus` with `@ai-sdk/openai-compatible`, `baseURL` `https://demo-api.routerplus.com/v1`, the key in `apiKey`, and `claude-sonnet-5-5`, `claude-opus-5-5` and `gpt-6-luna` with image input. It sets `model` only when the file has none. |
| `cline` | Runs `cline auth --provider openai-compatible --modelid claude-sonnet-5-5 --baseurl https://demo-api.routerplus.com/v1` with the key. Cline writes its own files in `~/.cline`. The CLI backs up those files first and shows what changed. If the Cline CLI is not on `PATH`, the CLI shows the steps for the extension. |
| `cursor` | Writes no file. Cursor keeps the key in its settings screen, so the CLI shows the steps. `--copy-key` puts the key on the clipboard for you to paste. |

After `setup`, the Codex and OpenCode files hold your key. Do not commit or share them.

## Status

```bash
node tools/routerplus-cli/main.ts status
```

```
Key: tm_vk_1a2b3c... (approved by you@example.com)
Stored in: /Users/you/.config/routerplus/credentials.json
Gateway: https://demo-api.routerplus.com
Usage: $1.50 (limit $25.00, $23.50 left)
Rate limit: 300 requests per 1m
Tools:
  claude-code  configured
  codex        not configured
  cursor       set by hand
  opencode     configured with another key
  cline        not configured
```

- Usage and the limit come from `GET https://demo-api.routerplus.com/v1/key`.
- "configured with another key" means that the tool uses RouterPlus with a different key. Run
  `setup` for that tool to use the stored key.

## Log out

```bash
node tools/routerplus-cli/main.ts logout
```

`logout` deletes the stored key. The key still works until you disable it in the console, under
Access > [API keys](https://demo.routerplus.com/console/keys).

To revoke the key from the CLI, give a management key. Use `--management-key tm_mk_...` or the
`ROUTERPLUS_MANAGEMENT_KEY` variable. The CLI finds the key by its prefix in `GET /v1/keys` and
calls `DELETE /v1/keys/<id>`.

The tools that you set up keep the key in their own settings. Run `setup` again after the next
`login`, or remove the settings.

## Coding agent

`code` starts a coding agent in your terminal. The agent reads, searches and changes the files
in the current directory, and runs commands there. It uses the key in `ROUTERPLUS_API_KEY` when
that variable is set. Otherwise it uses the stored key.

```bash
cd my-project
node /path/to/routerplus/tools/routerplus-cli/main.ts code
node /path/to/routerplus/tools/routerplus-cli/main.ts code --model claude-sonnet-5-5 --max-cost 2
```

Type a task at the `>` prompt. The agent streams its answer and asks you before each change. It
keeps the conversation until you type `/clear` or `/exit`.

| Command | What it does |
|---|---|
| `/cost` | Shows the cost of the session in USD. |
| `/clear` | Starts a new conversation. |
| `/exit` | Quits and shows the session cost. |

### One-shot mode

Give the task as an argument and pipe stdin. The agent does the task, prints the cost and exits.

```bash
node tools/routerplus-cli/main.ts code --yes "Add a test for parseDate" < /dev/null
```

With no argument, the agent reads the task from stdin. In this mode the agent cannot ask you
for approval:

- Without `--yes`, it refuses writes, edits and commands.
- Without `--auto-approve-reads` or `--yes`, it also refuses reads.

The exit code is `0` when the agent finishes and `1` when it stops early.

### Tools

| Tool | What it does | Asks you |
|---|---|---|
| `read_file` | Reads a text file, with line numbers. Takes `offset` and `limit` in lines. | Unless `--auto-approve-reads` or `--yes` |
| `list_dir` | Lists a directory. | Unless `--auto-approve-reads` or `--yes` |
| `search` | Searches file contents for a regular expression. Skips `.git`, `node_modules`, binary files and files over 1 MB. Returns at most 100 matches. | Unless `--auto-approve-reads` or `--yes` |
| `write_file` | Creates or replaces a file. Shows a diff first. | Unless `--yes` |
| `edit_file` | Replaces one string in a file. The string must occur once. Shows a diff first. | Unless `--yes` |
| `run` | Runs a shell command. Stops the command after 120 s and keeps the first 20,000 characters of output. | Unless `--yes` |

### Safety

- Every path must be inside the current directory. The agent refuses other paths, also through
  a symbolic link.
- Before each write or edit, the agent shows a unified diff.
- These files can hold secrets: `.env`, `.env.*`, `credentials.json`, `*.pem` and names that
  contain `key`. The agent sends their contents only when you type `y`, also with `--yes`.
  `search` does not look in these files.
- `--yes` lets the model change files and run any command. Use it only in a directory you can
  restore, for example a clean git checkout.

### Options

| Option | Default | Meaning |
|---|---|---|
| `--model ID` | `routerplus/auto` | The model. `routerplus/auto` lets the gateway select a model for each request. See [Auto router](/docs/auto-router). |
| `--yes`, `-y` | off | Run writes, edits and commands without asking. |
| `--auto-approve-reads` | off | Read, list and search without asking. |
| `--max-cost USD` | none | Stop when the session cost reaches this amount. The cost is the sum of `usage.cost` in the answers. |

Each request sends these headers:

- `x-session-id`, with one id for the conversation. The gateway keeps the conversation on one
  provider, so the prompt cache stays warm. `/clear` starts a new id.
- `x-tm-labels: client=routerplus-code`, so you can find the agent's requests in your
  usage.

## Options

| Option | Default | Meaning |
|---|---|---|
| `--api URL` | `https://api.routerplus.com` | The gateway. `login` stores it, and later commands use the stored value. `code` also reads `ROUTERPLUS_API_URL`. |
| `--console URL` | `https://app.routerplus.com` | The console with the consent page. |

Both URLs must use https. Plain http works only on `localhost`, `127.0.0.1` and `[::1]`.
