AI coding agents are great at writing code, but they're notoriously bad at managing the long-running processes that code needs: dev servers, databases, workers, and build watchers. Command Book's CLI gives any agent a reliable, machine-readable way to launch a process, poll whether it's actually up, and stop it cleanly when the work is done.
This page is the human-facing setup guide. For the terse, copy-into-your-agent reference, see the raw AI Agent CLI Reference — it's written specifically for LLMs to load into their instructions.
Why agents + Command Book
When an agent starts a server with a bare background shell (python app.py &), it has no dependable way to answer two simple questions later: Is it still running? and How do I stop it? The result is the failure mode every developer has seen an agent fall into:
- Orphaned servers that keep running after the task is "done," holding onto ports and memory.
- Port conflicts when the agent starts a second copy because it lost track of the first.
- Guessed sleep timers (
sleep 5 && curl ...) that are either too short (server isn't up yet) or wastefully long.
Command Book fixes this by being the front door for long-running processes. Every process started through Command Book — whether from the GUI or from commandbook run — is tracked in a runtime registry. So when the agent asks commandbook status, there is always a truthful answer, and when it asks commandbook stop, there is always a real handle to act on. No PID bookkeeping, no leaked processes.
Only processes Command Book launched are visible to
statusandstop. If your agent needs to manage a process, it must start it throughcommandbook run.
The loop: launch → poll → act → stop
This is the entire pattern Command Book is built around. An agent should follow these four steps for any long-running process:
- Launch the saved command with
commandbook run <slug>. Becauserunis a long-running foreground process, the agent backgrounds it (or runs it with a timeout) so it can keep working. - Wait for it with
commandbook wait <slug>— one call that blocks until the process is up and returns the instant it is. Add--http <url>or--port <n>to wait until the server actually accepts connections, not just until the process exists. No guessed sleep timers, and a built-in timeout so a failed boot can't hang the agent. - Act against the now-running process: hit its port, run a test suite, scrape a page, whatever the task requires.
- Stop it with
commandbook stop <slug>when finished. This also suppresses auto-restart, so the process stays down.
# 1. Launch (background the long-running foreground process)
commandbook run api-server &
# 2. Block until the port answers — returns the moment it's ready, or fails fast on a bad boot.
commandbook wait api-server --http http://127.0.0.1:5000
# 3. Do the work against the running server here...
# 4. Stop cleanly when done (also suppresses auto-restart)
commandbook stop api-server
The CLI in 60 seconds
These are the commands an agent needs. The full reference, with every flag and example, lives on the CLI page.
commandbook list # Discover exact slugs — never guess them
commandbook details <slug> --json # Full config + status for one command
commandbook run <slug> # Run a saved command (long-running, foreground)
commandbook run --command "<cmd>" --name <handle> # Run an arbitrary command ad-hoc (not saved)
commandbook status <slug> --json # Is it running? Machine-readable snapshot.
commandbook wait <slug> --http <url> # Block until up & the port answers (timeout ceiling)
commandbook stop <slug> --json # Stop gracefully (machine-readable result)
commandbook stop <slug> --force # Stop immediately (SIGKILL)
commandbook new --name "<name>" --command "<cmd>" # Save a command (no prompts with flags)
commandbook edit <slug> --command "<cmd>" # Change only the fields you pass
commandbook delete <slug> # Remove a saved command
Every one of these is non-interactive and safe to run with stdin closed.
status --json
Prefer the --json form when you want to parse state instead of branching on exit codes:
{
"slug": "talk-python-dev",
"state": "running",
"instances": [
{ "pid": 81234, "startedAt": "2026-06-17T10:02:00Z", "source": "app", "uptimeSeconds": 720 }
]
}
stateis"running","stopped"(known but nothing live), or"not_found".sourceis"cli"(started viacommandbook run) or"app"(started in the GUI).statussees both.- The no-arg
commandbook status --jsonreturns a JSON array, one entry per running command.
Exit codes (scriptable, HTTP-flavored)
status, stop, details, new, edit, and delete share the same exit-code vocabulary, which makes them easy to script:
| Code | Meaning |
|---|---|
0 |
Running / stopped at least one instance / command exists (details) / wrote a command |
1 |
stop matched live processes but none could be killed |
204 |
Known but not running |
44 |
Slug not found (shown as 404 in the message/JSON) |
45 |
new — a command already owns that slug (use --if-not-exists to make it a no-op) |
46 |
delete — the command is running and --force wasn't passed |
47 |
run — the command is already running (use --restart or --allow-multiple) |
244 |
Runtime registry error (shown as 500) |
64 |
Invalid arguments — a bad --dir, --icon, or --env, or a missing required flag |
Because exit code 0 means "running," commandbook status is pollable in a loop — but prefer commandbook wait (below), which does the polling for you with a timeout and an optional readiness probe.
Two states share exit 0: running and restarting. A restarting command is between auto-restart attempts — momentarily down, but still managed, still listed, and still stoppable. Don't treat it as stopped. If you need the process actually answering, use wait --http/--port rather than status.
Check status before run. run refuses to start a second copy of a live command and exits 47 — that's "already up", not a failure. It's an easy state to reach when a run was backgrounded in an earlier step or another shell, and --restart is the fix when you mean to replace it.
Waiting for a command: commandbook wait
commandbook wait <slug> blocks until a condition is met and returns the instant it is — the timeout is only a ceiling, never a fixed delay. It replaces hand-rolled until commandbook status …; do sleep 1; done loops, which have no timeout and can't tell "still booting" from "already crashed."
commandbook wait <slug> # until the process is registered and alive
commandbook wait <slug> --http http://127.0.0.1:5000 # until that URL returns 2xx/3xx
commandbook wait <slug> --port 5000 # until that TCP port accepts a connection
commandbook wait <slug> --for stopped # until it is no longer running
commandbook wait <slug> --timeout 60 --json # raise the ceiling; emit JSON
- Readiness, not just liveness. With
--http/--port, wait returns only once the server actually answers — so you can drop the separatecurl-retry loop. A server is "running" for a moment before its port binds; this closes that gap. - Fail-fast. If the process exits before becoming ready, wait returns immediately (exit
205) instead of burning the whole timeout. - Short commands. A plain
wait <slug>(no probe) also succeeds if the command has already exited cleanly (exit0); a non-zero exit is propagated as wait's own exit code. Use--for stoppedto block until a one-shot command finishes and get its exit code back.
| Code | Meaning |
|---|---|
0 |
Condition met (running / ready / clean exit / stopped) |
124 |
Timed out before the condition was met |
205 |
--http/--port target exited before becoming ready |
44 |
Slug not found (shown as 404) |
244 |
Runtime registry error (shown as 500) |
The --json output carries state (running · ready · exited · stopped · timeout), waitedSeconds, an exitCode once the command has ended, and the live instances:
{ "slug": "talk-python-dev", "state": "ready", "waitedSeconds": 0.34,
"instances": [ { "pid": 81234, "source": "cli", "uptimeSeconds": 0 } ] }
Set up your agent
There are two ways to give your agent the Command Book workflow: install the ready-made skill (the fastest path — see below), or paste a per-tool instruction block into your tool's config (Claude Code, Codex, and Cursor blocks are further down). Either way, the source of truth is the AI Agent CLI Reference — it spells out the commands, the loop, and the gotchas.
Install the Command Book bundle (skill + agent)
The same setup is packaged as a ready-made Command Book bundle so you don't have to hand-write instructions. It's two pieces: the ask-commandbook skill (the launch → wait → stop loop your main agent follows inline) and a commandbook operator agent (for multi-process orchestration). There are three ways to get it in place, from easiest to most manual.
Install from the app (easiest)
In Command Book, open Settings → AI Agents → "Install Claude Code Skill & Agent". One click installs the skill to ~/.claude/skills/ask-commandbook/ and the agent to ~/.claude/agents/commandbook.md, where Claude Code picks them up automatically across all your projects. This is the recommended path — no download, no unzip — and it keeps itself up to date: when a newer Command Book ships an updated bundle, the app refreshes your installed copy on launch.
Download the bundle
Prefer to do it by hand, or installing for a tool other than Claude Code? Download the bundle and drop it where your tool looks for instructions:
- commandbook-skill.zip — contains
skills/ask-commandbook/(withSKILL.md+reference/cli-reference.md) andagents/commandbook.md.
Then put it in place per tool:
Claude Code — unzip into
~/.claude/for a personal install (all projects), or into<project>/.claude/for a single project. Either way you'll end up with…/.claude/skills/ask-commandbook/SKILL.mdand…/.claude/agents/commandbook.md. The exact command for a personal install:unzip commandbook-skill.zip -d ~/.claude/Verify it loaded by asking Claude to "start X with Command Book," or by running
/skillsif your version supports it.Codex — Codex can't load a
SKILL.mddirectly, so add the instruction block to your project'sAGENTS.mdinstead — see the Codex block under "Per-tool setup" below.Cursor — add the instruction block to
.cursorrules(or a project rule) — see the Cursor block under "Per-tool setup" below.
Manual copy (no download)
If you'd rather not download anything, the raw skill is viewable at /static/downloads/SKILL.md and the full CLI reference at /docs/ai-guide.md. Paste the relevant block straight into your tool's instruction file.
Per-tool setup
Copy-paste instruction blocks for each tool. If you installed the skill above, Claude Code is already set up — these are the manual equivalents.
Claude Code
The skill above packages this automatically. To set it up by hand instead, add the reference URL to your project's CLAUDE.md:
## Long-running processes
Use the Command Book CLI to start, check, and stop long-running processes
(dev servers, databases, workers). Full reference:
https://commandbookapp.com/docs/ai-guide.md
The loop: `commandbook run <slug> &`, poll `commandbook status <slug>` until
it exits 0 (running), do the work, then `commandbook stop <slug>`.
Use `commandbook list` to discover exact slugs.
Codex
Add the same instruction block to your project's AGENTS.md:
## Long-running processes (Command Book)
Start dev servers and other long-running processes with the Command Book CLI
instead of bare background shells, so they can be monitored and stopped cleanly.
Reference: https://commandbookapp.com/docs/ai-guide.md
Loop: `commandbook run <slug> &` → poll `commandbook status <slug>` until it
exits 0 → do the work → `commandbook stop <slug>`.
Cursor
Add to your project's .cursorrules (or a project rule):
When you need a long-running process (dev server, database, worker), use the
Command Book CLI so it can be monitored and stopped reliably:
- Discover slugs with `commandbook list`
- Start with `commandbook run <slug> &`
- Poll `commandbook status <slug>` until it exits 0 (running)
- Stop with `commandbook stop <slug>` when done
Full reference: https://commandbookapp.com/docs/ai-guide.md
Generic / any agent
Any agent that can load a URL or a markdown file can use Command Book. Point it at:
- The reference: https://commandbookapp.com/docs/ai-guide.md
- The discovery file: https://commandbookapp.com/llms.txt
Both are plain text written for machine consumption.
Worked example: run a dev server, test it, stop it
Suppose you have a Flask app saved in Command Book as talk-python-dev. Here's how an agent would start it, wait for it to come up, run work against it, and tear it down — all with real commandbook commands.
# Confirm the slug exists (don't guess it).
commandbook list
# Launch the dev server. It's a long-running foreground process, so background it.
commandbook run talk-python-dev &
# Wait until the server actually accepts connections. Returns the instant it's ready,
# fails fast (exit 205) if the process dies during boot, and gives up after --timeout.
commandbook wait talk-python-dev --http http://127.0.0.1:5000/health --timeout 30
# The server is up — now do the work against it.
curl -fsS http://127.0.0.1:5000/health
python -m pytest tests/integration/
# Stop the server cleanly. This also suppresses auto-restart.
commandbook stop talk-python-dev
If you'd rather inspect the result yourself, add --json and branch on state:
commandbook wait talk-python-dev --http http://127.0.0.1:5000 --json
# {"slug":"talk-python-dev","state":"ready","waitedSeconds":0.3, ... }
Writing to the command book, not just reading it
An agent can create and maintain saved commands, not only run them. new, edit, and delete prompt only when you run them with no flags; pass flags and they never read stdin, so they're safe to run with stdin closed.
This is what turns "set up my dev servers" into a one-shot agent task. The agent saves the commands, and they land in your ⌘K palette where they belong — instead of the agent running everything ad-hoc and leaving you nothing to reuse tomorrow.
# Create the command, idempotently, and capture its slug.
slug=$(commandbook new --name "API Server" \
--command "uv run flask --app app.main run --port 5000" \
--dir ~/src/api --icon flask --if-not-exists --json | jq -r .slug)
# Use it immediately — no second lookup needed.
commandbook run "$slug" &
commandbook wait "$slug" --http http://127.0.0.1:5000
What an agent needs to know:
--dirdefaults to the current directory, not~, which is almost always what's meant.--if-not-existsmakes provisioning idempotent. Without it, a slug that already exists exits45and writes nothing, so a setup script run twice fails the second time.- There's no
--slugflag. Slugs are derived from--name; that's how you control them. --jsonreturns the same object asdetails --json, so create-then-inspect never needs a second call.editchanges only the fields you pass.--envmerges into the existing variables rather than replacing them;--clear-envwipes them first.deleterefuses while the command is running (exit46) so you can't orphan a live process. Pass--forceto stop it first.- Environment variable values are never printed back — only their names — on every one of these commands.
- The user sees it immediately. A running Command Book picks up commands the CLI creates, edits, or deletes as they happen; no restart needed.
Gotchas
A few behaviors are worth teaching your agent up front:
stopblocks during graceful shutdown. It escalatesSIGINT → SIGTERM → SIGKILLto the process group, which can take up to ~12s per instance (5s SIGINT + 5s SIGTERM + 2s SIGKILL). When a graceful shutdown isn't needed, usecommandbook stop <slug> --forceto skip straight to SIGKILL (~2s).- Auto-restart retry caveat. If a command has auto-restart enabled and you
stopit during its brief restart-delay countdown, the stop can be a silent no-op while the pending restart still fires. Ifstopunexpectedly returns204for an auto-restart command, pollstatusand retrystoponce it shows running. - Only Command Book–launched processes are visible.
statusandstopcan only see processes started throughcommandbook runor the GUI. The CLI cannot find or kill arbitrary processes started elsewhere — so start everything you want to manage through Command Book. - Ad-hoc for throwaway, saved for keepers. To launch something that isn't a saved slug, use
commandbook run --command "<cmd>" --name <handle>— fully managed bystatus/stop, but not added to the user's command list. Use that for one-off agent processes so you don't clutter their list. When the process is one the user will want again — their dev server, database, or worker — save it withcommandbook newinstead (see below). - Inspect before you run.
commandbook details <slug> --jsonreturns a command's full configuration (command, working directory, env var names, auto-restart) plus its current status — so you can verify exactly what a slug will do before launching it. Environment variable values are never printed. - Always pass the slug explicitly.
commandbook runwith no slug launches an interactive picker, which an agent can't drive.
Learn more
- AI Agent CLI Reference — the terse, machine-oriented reference to load into your agent instructions
- CLI documentation — full command reference with every flag and example
- Stopping Processes — the signal hierarchy behind
stop