Runner CLI
Most people only need commandchain-runner, which opens the runner screen. The commands below are optional, for scripts and machines without a screen.
commandchain-runner is the program the runner installer puts at ~/.local/bin/commandchain-runner. Run with no command, it runs connect, which in an interactive terminal is the runner screen.
$ commandchain-runner --helpUsage: commandchain-runner [options] [command]
Universal Agent Runner for CommandChain
Options: -V, --version output the version number -h, --help display help for command
Commands: connect [options] [url] Pair with a running CommandChain instance and begin processing runs start [options] Register with a CommandChain instance and begin processing runs (legacy BYO + managed pool) status Show saved runner credentials logout [url] Remove saved credentials for a CommandChain instance doctor Check that this machine can contain a coding agent, and report what it achieved agents Show which coding agents are installed, and install the ones that are not signin [options] Sign this runner in to a coding CLI (optional; the runner screen does this too) signout [options] Sign this runner out of a coding CLI (optional; press s on the runner screen and x) creds Coding-agent sign-ins for this runner, and logins uploaded for managed runs version Print the runner version help [command] display help for commandconnect
Section titled “connect”Pairs with a CommandChain instance through the browser and then processes runs. It is the default command, so commandchain-runner on its own runs it, and the installer uses it to pair.
In an interactive terminal, connect opens the runner screen: it shows the next thing to do (containment, installing a coding CLI, pairing, signing the runner in) and enter does it, with the optional actions in a menu. If the runner already runs in the background on this machine, the screen attaches to that service instead of starting a second runner, and q closes the screen and leaves the service running. Otherwise q stops the runner.
Piped, under a service manager, in CI, or with --plain, there is no screen, and the same information is written as structured JSON logs on stdout instead. A runner started that way while another runner for the same instance is running on this machine waits for it to stop rather than taking work beside it.
commandchain-runner # the runner screen, for the hosted CommandChaincommandchain-runner connect # the samecommandchain-runner connect https://your-commandchaincommandchain-runner connect https://your-commandchain --display-name maya-macbook --no-open| Argument | Default | Does |
|---|---|---|
[url] | COMMANDCHAIN_URL, else the hosted CommandChain API | Base URL of the CommandChain core to pair with. Pass it only for a self-hosted or local core |
| Flag | Default | Does |
|---|---|---|
--display-name <name> | the name this machine is already paired under, else <user>@<hostname> | The name you approve in the browser and see in the fleet. Does not have to be unique |
--workspace-root <dir> | COMMANDCHAIN_WORKSPACE_ROOT, else ~/.commandchain/workspaces | Where repository checkouts live |
--poll-interval-ms <ms> | 2000 | Heartbeat interval |
--callback-port <port> | 0 | Local callback API port. 0 picks a free one |
--plain | off | Do not draw the runner screen. Write structured JSON logs to stdout instead, which is also what any non-interactive terminal gets. COMMANDCHAIN_RUNNER_PLAIN=1 does the same |
--dashboard | off | Also open the run-observation dashboard, which replaces the runner screen. q there closes the view without stopping the runner |
--force-pair | off | Ignore any saved credential and pair again |
--pair-only | off | Pair and exit, without processing runs. The installer uses this, then hands running to the service manager |
--no-open | off | Do not try to open a browser. Print the URL instead |
--push-login <kind> | none | For managed runs: upload this machine’s login for one coding agent once pairing succeeds: claude-code, codex, or gemini. Passing the flag is the acknowledgment that this copies a provider account session |
--commandchain-agent-path <path> | found on PATH | Override the path to the commandchain-agent binary |
--claude-path <path> | found on PATH | Override the path to the claude binary |
--chromium-path <path> | CC_CHROMIUM_PATH, else found on PATH | Chromium or Chrome for the browser tool. Without one, runs simply proceed without that tool |
-h, --help | Print help for this command |
--push-login is the unattended half of the c key on the runner screen, and it does the same thing creds push does: read one coding CLI’s own login off this machine and upload it for runs on CommandChain’s managed servers. A runner on your own machine never needs it. It runs after pairing and before the run loop. A login that cannot be read or uploaded is logged and nothing more, because a runner is useful without one, so the runner still starts. See agent credentials.
The runner detects its coding agents at startup. With none, the runner screen offers to install one; without a screen, the runner exits and says how to install one. See coding agents, and pairing for the browser half of the flow.
Keys on the runner screen
Section titled “Keys on the runner screen”| Key | Does |
|---|---|
enter | Do the next step shown under NEXT STEP |
i | Install a CLI |
s | Sign-ins |
f | Full setup: off or on |
c | Managed login, for runs on CommandChain’s managed servers, or this runner’s own sign-in when that is the only one on the machine |
r | Check again |
e | Read the errors this runner has reported |
q | Quit, or Close screen when the runner runs in the background |
Inside Sign-ins: enter signs in with your browser, d with a device code (Codex only), a with an API key, and x signs out. See the runner screen.
signin
Section titled “signin”Signs this runner in to a coding CLI. The sign-in belongs to the runner, is kept on this machine, and is uploaded only if you choose to push it for managed runs with creds push --from-runner-signin; your own sign-in for that CLI is not used or changed. It runs the CLI’s own login, so a browser opens to finish it. The runner screen does the same with enter, or with s to pick a CLI. See sign-in only or full setup.
commandchain-runner signin --agent claude-codecommandchain-runner signin --agent codex --device-authprintenv ANTHROPIC_API_KEY | commandchain-runner signin --agent claude-code --api-key| Flag | Default | Does |
|---|---|---|
--agent <kind> | none | The coding agent: claude-code, codex, or gemini. Without it, the command says how to choose one and exits |
--api-key | off | Use an API key instead of a subscription login. It is read from a hidden prompt, or from stdin when piped, and stored only on this machine |
--device-auth | off | Codex only: sign in with a device code instead of a browser redirect |
--cli-path <path> | found on PATH | Path to the coding CLI, when it is not on PATH |
-h, --help | Print help for this command |
signout
Section titled “signout”Signs this runner out of a coding CLI. Runs already going finish with the current sign-in. Your own sign-in for that CLI is not touched.
commandchain-runner signout --agent claude-code| Flag | Default | Does |
|---|---|---|
--agent <kind> | required | The coding agent: claude-code, codex, or gemini |
-h, --help | Print help for this command |
The older flag-driven flow. It registers with a preconfigured credential rather than pairing in a browser, which is why it exists for platform-managed runners and for automation that cannot open a browser.
COMMANDCHAIN_URL=https://your-commandchain \COMMANDCHAIN_TENANT_ID=your-workspace \COMMANDCHAIN_RUNNER_CREDENTIAL=... \commandchain-runner start --display-name my-runner --adapter claude-code-cli| Flag | Default | Does |
|---|---|---|
--commandchain-url <url> | COMMANDCHAIN_URL, else the hosted CommandChain API | Base URL of the control plane |
--tenant-id <id> | COMMANDCHAIN_TENANT_ID | Workspace this runner serves |
--tenant-credential <secret> | COMMANDCHAIN_RUNNER_CREDENTIAL | Bootstrap credential used to register |
--display-name <name> | COMMANDCHAIN_RUNNER_NAME | Runner name |
--workspace-root <dir> | COMMANDCHAIN_WORKSPACE_ROOT, else ~/.commandchain/workspaces | Where checkouts live |
--adapter <id> | auto-detected | Adapter to advertise. Repeat the flag for several |
--poll-interval-ms <ms> | 2000 | Heartbeat interval |
--callback-port <port> | 0 | Local callback API port |
--tunnel-max-sessions <n> | 5 | Concurrent live-app tunnel sessions |
--commandchain-agent-path <path> | COMMANDCHAIN_AGENT_PATH | Path to the commandchain-agent binary |
--claude-path <path> | CLAUDE_PATH | Path to the claude binary |
--chromium-path <path> | CC_CHROMIUM_PATH | Chromium or Chrome for the browser tool |
--plain | off | Structured JSON logs instead of the status screen |
--dashboard | off | Also open the run-observation dashboard |
-h, --help | Print help for this command |
A self-hosted runner whose credential resolves to a different workspace than --tenant-id exits rather than serving the wrong one.
status
Section titled “status”Prints the pairings saved on this machine. Never prints credential material.
$ commandchain-runner statusCredentials file: /home/maya/.commandchain/runner.json
https://your-commandchain tenant alpenglow runnerId 32c152e4-3d5e-49a1-b3df-20b95c0a74b6 displayName maya-macbook adapters claude-code-cli, commandchain-agent-cli pairedAt 2026-07-18T09:14:22.104ZWith nothing paired:
$ commandchain-runner statusNo paired instances.Run commandchain-runner to open the runner and pair it with your workspace.logout
Section titled “logout”Removes the saved credential for one instance. The runner in your fleet is untouched: revoke it in the app if you want it gone from there too.
commandchain-runner logout # the hosted CommandChaincommandchain-runner logout https://your-commandchain| Argument | Default | Does |
|---|---|---|
[url] | the hosted CommandChain API | Which pairing to forget |
doctor
Section titled “doctor”Proves this machine can contain a coding agent, by building a real sandbox policy and running a real process through it. Deliberately flagless: there is nothing to configure about the question, and no way to skip, weaken, or declare a result the machine did not earn.
$ commandchain-runner doctorcommandchain-runner doctor - containment check host type self_hosted provider linux-landlock platform linux tier landlockOK - every agent process on this machine will run inside this boundary.Exit code 0 means contained, non-zero means not. Proving containment with doctor reads the output in full and lists the failure cases.
agents
Section titled “agents”Shows which coding agents this machine has installed, and installs the ones it is missing. The runner screen shows the same list, and i installs one; this is the scriptable form. See coding agents for what each agent is.
agents list
Section titled “agents list”commandchain-runner agents listcommandchain-runner agents list --json| Flag | Default | Does |
|---|---|---|
--json | off | Print the same information as JSON, for scripts |
-h, --help | Print help for this command |
agents install
Section titled “agents install”commandchain-runner agents install # every missing agentcommandchain-runner agents install claude| Argument | Default | Does |
|---|---|---|
[agents...] | every missing one | Which to install: claude, codex, gemini, commandchain-agent |
| Flag | Default | Does |
|---|---|---|
--yes | off | Do not ask for confirmation. Required in a non-interactive session |
-h, --help | Print help for this command |
Each install runs the vendor’s own installer, so what lands on the machine is exactly what installing that agent by hand would put there.
Checks this runner’s own sign-ins, and manages the logins uploaded for runs on CommandChain’s managed servers.
$ commandchain-runner creds --helpUsage: commandchain-runner creds [options] [command]
Coding-agent sign-ins for this runner, and logins uploaded for managed runs
Commands: status [options] Check which coding agents this runner is signed in to (local only; the runner screen shows this too) push [options] Read the coding CLIs' native credentials on this machine and upload them (managed runs) list [options] Show the uploaded logins, metadata only (managed runs) rm [options] <agentKind> Remove one uploaded login (managed runs)creds status
Section titled “creds status”Local only: it reads this machine and sends nothing anywhere. It shows the agent setup and, per coding CLI, whether it is installed and whether the runner is signed in to it. See sign-in only or full setup.
$ commandchain-runner creds statusAgent setup: sign-in only (runs use this runner's own sign-ins) Claude Code signed in for this runner (subscription login) Codex not installed Gemini CLI not installed| Flag | Default | Does |
|---|---|---|
--json | off | Print the same result as JSON, for scripts |
-h, --help | Print help for this command |
For managed runs: creds push, creds list, creds rm
Section titled “For managed runs: creds push, creds list, creds rm”These three are only for runs on CommandChain’s managed servers. Full context in managed runner credentials. Each accepts --url <url>, which defaults to COMMANDCHAIN_URL and then to the hosted CommandChain API. All three authenticate with the pairing credential in ~/.commandchain/runner.json, so this machine has to be paired first.
creds push
Section titled “creds push”For managed runs. The c key on the runner screen does the same.
commandchain-runner creds push # all three, whatever is foundcommandchain-runner creds push --agent claude-codecommandchain-runner creds push --agent claude-code --from-runner-signin| Flag | Default | Does |
|---|---|---|
--agent <kind> | all | One of claude-code, codex, gemini |
--from-runner-signin | off | Push this runner’s own sign-in instead of your personal login. Needs --agent. |
--accept-oauth-risk | off | Acknowledge the risk of uploading a subscription login, for non-interactive use |
--url <url> | COMMANDCHAIN_URL, else the hosted CommandChain API | Which paired instance to upload to |
Two rules are enforced here rather than left to you:
- A provider API key wins over a subscription login when both are on the machine, because a key is revocable and avoids the provider’s terms-of-service question.
pushsays which it chose and why. - A subscription login needs explicit acknowledgment. Interactively you type
i understand; non-interactively you pass--accept-oauth-risk. Without it the upload aborts with a non-zero exit.
The two sources are never mixed and never chosen for you: a push uploads your personal login unless you pass --from-runner-signin, which uploads that one named agent’s runner sign-in and nothing else.
creds list
Section titled “creds list”For managed runs.
commandchain-runner creds listcommandchain-runner creds list --json| Flag | Default | Does |
|---|---|---|
--json | off | Print the same records as JSON, for scripts |
--url <url> | COMMANDCHAIN_URL, else the hosted CommandChain API | Which paired instance to ask |
Output is metadata only. No token material is ever returned by the server, so none can be printed.
$ commandchain-runner creds listAGENT AUTH EXPIRES UPDATEDclaude-code oauth 2026-08-17T09:14:22.000Z 2026-07-18T09:14:25.881Zcreds rm
Section titled “creds rm”For managed runs.
commandchain-runner creds rm claude-code| Argument | Does |
|---|---|
<agentKind> | One of claude-code, codex, gemini |
| Flag | Default | Does |
|---|---|---|
--url <url> | COMMANDCHAIN_URL, else the hosted CommandChain API | Which paired instance to remove it from |
version
Section titled “version”$ commandchain-runner version0.9.5commandchain-runner --version prints the same string. Release history is in release notes.
Next steps
Section titled “Next steps”- The runner screen: the same steps, one key at a time.
- Runner environment variables: everything the runner reads from its environment.
- Install a runner: the installer’s own flags, which are separate from these.
- Runner troubleshooting: symptom-first fixes.