If Claude Code is where you work, cpb is how you run more than one of it.
One ~/.claude holds one setup: one set of settings and hooks,
one memory, one login, one environment, all with full access to your machine.
cpb gives you as many Claude Codes as you need, each behind
its own command, each isolated as far as you choose, and each described in a file you
can apply anywhere.
$ cpb CREATE PLAYBOOK work # a playbook, and a `work` command that opens it
$ cpb CREATE PLAYBOOK side ISOLATED LOGIN # a second account, running beside the first
$ cpb CREATE PLAYBOOK sre SANDBOX # every launch inside a microVM
$ work # Claude Code, bound to that playbook
Four layers
Isolation, as far as you choose
Each playbook gets its own config, and can go further: its own environment, its own login, or its own process boundary. You decide per playbook.
Config home
Its own CLAUDE.md, settings.json,
hooks, memory, history, sessions, plugins, MCP servers and skills.
Your ~/.claude never moves.
every playbook, always
Environment
Its own variables, set or blocked at launch: another model backend, another token, another proxy. Your shell stays as it is.
USE ENV · SET VAR · BLOCK VAR
Login
Its own Anthropic account, sharing nothing with ~/.claude.
ISOLATED LOGIN
Process
A microVM with its own kernel, filesystem and network. It sees only your working directory and its own config; your machine's login never enters it. By default a host-side proxy injects backend API keys, so the sandbox never holds them.
SANDBOX · --sandbox
Try it
Try things without touching your daily setup
A scratch playbook, used and dropped. ~/.claude is
never touched.
$ cpb CREATE PLAYBOOK scratch
Created playbook "scratch" at /home/you/.claude-playbooks/scratch
Command: scratch (launcher at /home/you/bin/scratch)
Run it now:
'scratch'
$ cpb SHOW PLAYBOOK scratch
Name: scratch
Version: (none)
Path: /home/you/.claude-playbooks/scratch
Source: (none)
Launcher: (none)
Env sets: (none)
Variables: (none)
Sandbox: no
Pilot profile: imported (CLAUDE.md imports ~/.pilot-profile/)
$ cpb DROP PLAYBOOK scratch --yes
Removed command "scratch"
Deleted playbook "scratch".
A throwaway session in a throwaway folder works the same way:
cpb start /tmp/x --delete.
Environment & models
Route one playbook to another model
An env set is a named group of variables, attached to one playbook or to all of
them (DEFAULTS). EXPLAIN shows
what a launch sets and which layer set it — and a custom /model
list travels with the playbook too.
$ cpb CREATE ENV router SET ANTHROPIC_BASE_URL=http://localhost:4000/v1
Created ENV router
set ANTHROPIC_BASE_URL
$ cpb CREATE PLAYBOOK glm NO PILOT PROFILE ISOLATED LOGIN
Created playbook "glm" at /home/you/.claude-playbooks/glm
Login isolated: it shares no login with ~/.claude; run /login once in it.
$ cpb ALTER PLAYBOOK glm USE ENV router SET VAR ANTHROPIC_MODEL=glm-5.3
Altered PLAYBOOK glm
env sets router
set ANTHROPIC_MODEL
$ cpb ALTER PLAYBOOK glm BLOCK VAR ANTHROPIC_API_KEY
Altered PLAYBOOK glm
blocked ANTHROPIC_API_KEY
$ cpb ALTER PLAYBOOK glm ADD MODEL 'glm-5.3' LABEL 'GLM 5.3' DESCRIPTION 'via the router'
Altered PLAYBOOK glm
model glm-5.3
$ cpb ALTER PLAYBOOK glm ADD MODEL 'glm-5.3-flash' LABEL 'GLM 5.3 Flash' BEHAVES AS 'claude-sonnet-5'
Altered PLAYBOOK glm
model glm-5.3-flash
$ cpb ALTER PLAYBOOK glm SET MODEL PICKER ONLY
Altered PLAYBOOK glm
picker only
$ cpb EXPLAIN PLAYBOOK glm
VARIABLE VALUE FROM
-------- ----- ----
ANTHROPIC_API_KEY (blocked) PLAYBOOK glm
ANTHROPIC_BASE_URL http://localhost:4000/v1 ENV router
ANTHROPIC_MODEL glm-5.3 PLAYBOOK glm
Secret helper: (none)
Plugins: (none)
Agent: (none)
Model: glm-5.3 (ANTHROPIC_MODEL); a launch's --model and /model still win
Model picker: only: glm-5.3 (GLM 5.3), glm-5.3-flash (GLM 5.3 Flash)
Login: isolated: no link to ~/.claude's login and no machine token; /login once in it
ISOLATED LOGIN keeps your Anthropic login away from that
provider, and NO PILOT PROFILE keeps a local profile import
(such as ~/.pilot-profile/) out of the playbook's
CLAUDE.md — cpb warns once if a playbook that already
imports one is later routed to a non-Anthropic host.
Process isolation
Let an agent loose without letting it near your machine
With --sandbox, Claude Code runs in a microVM that sees
your working directory and the playbook's own directory — not your home,
~/.claude, your shell's environment, or your other
playbooks.
$ cpb run --sandbox work # this folder is the workdir
$ cpb run --sandbox --sandbox-fresh --clone --workdir ~/untrusted-repo work # a private clone; your tree is untouched
$ cpb run --sandbox --mount ~/shared-libs:ro work # one more directory, read-only
$ cpb run --sandbox-host me@buildbox work # the same launch, sandboxed on another machine
By default your backend API keys stay on the host: the sandbox sees a placeholder
that a host-side proxy swaps for the real key, for that endpoint only. If a key can't
be registered with the proxy, the launch refuses rather than fall back to sending it in
plain (v3.26.0); [sandbox] secrets = "env" is the only way
to pass one in as a variable instead. A SANDBOX playbook is
sandboxed on every launch.
On Linux with Docker, --sandbox=openshell runs the session
in NVIDIA OpenShell
instead of sbx — experimental, Linux with Docker
only, opt-in (v3.27.0).
The DDL grammar
Put the whole setup in a file
Every statement above can live in a .cpb file: a
recipe, since its ALTER PLAYBOOK names no
playbook. APPLY checks all of it before writing anything,
--dry-run shows every change, and applying twice changes
nothing.
-- reviewer.cpb: a recipe (it names no playbook)
ALTER PLAYBOOK
ADD MCP SERVER files COMMAND 'npx' ARGS '-y' '@modelcontextprotocol/server-filesystem' '/srv/notes'
ALLOW TOOL 'Bash(gh pr *)' DENY TOOL 'Bash(git push *)'
ADD SKILL review FROM '/home/you/skills-src/review'
SET MODEL 'claude-opus-5-5';
$ cpb APPLY reviewer.cpb TO reviewer --dry-run
reviewer.cpb:2 created CREATE PLAYBOOK reviewer
reviewer.cpb:2 changed ALTER PLAYBOOK reviewer (would run: claude mcp add-json files --scope user; link skills/review to /home/you/skills-src/review)
Would apply reviewer.cpb: 1 created, 1 changed, 0 unchanged, 0 dropped
$ cpb APPLY reviewer.cpb TO reviewer
Applied reviewer.cpb: 1 created, 1 changed, 0 unchanged, 0 dropped
$ cpb SHOW CREATE PLAYBOOK reviewer --skip-secrets
CREATE PLAYBOOK IF NOT EXISTS reviewer;
ALTER PLAYBOOK reviewer
ALLOW TOOL 'Bash(gh pr *)'
DENY TOOL 'Bash(git push *)'
SET MODEL 'claude-opus-5-5';
ALTER PLAYBOOK reviewer
ADD MCP SERVER files COMMAND 'npx' ARGS '-y' '@modelcontextprotocol/server-filesystem' '/srv/notes'
ADD SKILL review FROM '/home/you/skills-src/review';
Secrets are references, resolved at launch by your helper; SHOW CREATE
never prints a value. A recipe applies to any playbook or to ~/.claude
itself. cpb SHOW CREATE ALL > playbook.cpb exports the whole
machine; cpb APPLY playbook.cpb rebuilds it on the next one.
Configuration
MCP servers, with secrets by reference
ADD MCP SERVER builds the config and runs Claude Code's own
claude mcp add-json for the playbook. A credential must come
FROM '<ref>': Claude's config gets only a placeholder,
and a configured secret helper resolves it into the session at launch.
$ cpb ALTER PLAYBOOK researcher ADD MCP SERVER sentry URL 'https://mcp.sentry.dev/mcp' HEADER 'Authorization' FROM 'keychain:pilot/sentry-auth'
Altered PLAYBOOK researcher
MCP server sentry
$ cpb EXPLAIN PLAYBOOK researcher
VARIABLE VALUE FROM
-------- ----- ----
CPB_MCP_SENTRY_H_AUTHORIZATION_32770652 <from keychain:pilot/sentry-auth> PLAYBOOK researcher
Secret helper: (none)
Plugins: (none)
Agent: (none)
MCP servers: files, sentry
$ cpb SHOW CREATE PLAYBOOK researcher --skip-secrets
CREATE PLAYBOOK IF NOT EXISTS researcher
NO ALIAS;
ALTER PLAYBOOK researcher
ADD MCP SERVER files COMMAND 'npx' ARGS '-y' '@modelcontextprotocol/server-filesystem' '/srv/notes'
ADD MCP SERVER sentry URL 'https://mcp.sentry.dev/mcp' HEADER 'Authorization' FROM 'keychain:pilot/sentry-auth';
The value never appears in a file, in argv, or in any SHOW/EXPLAIN
output. Claude's own config gets only ${CPB_MCP_SENTRY_H_AUTHORIZATION_…},
which the secret helper expands at launch.
Sessions & SQL
See everything that is running
cpb sessions lists every live Claude Code session, in every
playbook. SELECT queries the same state as tables —
built in for plain column lists, or through clickhouse local
for WHERE, ORDER BY and functions.
$ cpb sessions
PLAYBOOK PID TTY KIND STATUS AGE ACTIVE MODEL SESSION CWD
-------- --- --- ---- ------ --- ------ ----- ------- ---
worker 246892 - interactive idle 0s 0s claude-opus-5-5 0e5c1a2b-0000-4000-8000-000000000001 /home/you/project
$ cpb "SELECT name, envs, sandbox FROM PLAYBOOKS"
NAME ENVS SANDBOX
---- ---- -------
glm router false
researcher - false
reviewer - false
side - false
sre - true
work - false
$ cpb "SELECT playbook, key FROM VARS WHERE effective ORDER BY playbook, key"
PLAYBOOK KEY
-------- ---
glm ANTHROPIC_API_KEY
glm ANTHROPIC_BASE_URL
glm ANTHROPIC_MODEL
researcher CPB_MCP_SENTRY_H_AUTHORIZATION_32770652
cpb RESUME starts this folder's latest session, in its own
playbook, and never resumes one that's already live — two processes on one session
id would corrupt it.
cpb tui (v3.25.0)
Browse playbooks, sessions and env sets on one screen
A read-only terminal UI over the grammar: every screen names the
cpb … --json statement it reads, on its last line. No
screen ever holds a secret value. The blocks below are the real screens, from cpb's own
test goldens.
cpb [1 Playbooks] 2 Sessions 3 Env sets 4 Defaults 5 Log ? help
────────────────────────────────────────────────────────────────────────────────
NAME LAUNCHER ENV SETS LOGIN SESSIONS MODEL
▸ kommander-dev kd - shared 1 claude-opus-5-5
router k9 9router isolated 1 glm-5.3
────────────────────────────────────────────────────────────────────────────────
2 playbooks · 2 live sessions · read 0s ago
enter open s sessions c SHOW CREATE e export y copy / filter q quit
reads: cpb SHOW PLAYBOOKS --json · cpb SHOW SESSIONS --json
cpb 1 Playbooks 2 Sessions 3 Env sets 4 Defaults 5 Log ? help
────────────────────────────────────────────────────────────────────────────────
router (launcher k9 · ~/.claude-playbooks/router)
[Overview] Env Vars Plugins MCP Skills Status line Model Sessions
Version -
Source (none)
Login isolated
Pilot profile not imported
Env sets 9router
Tools -
Live sessions 1 · newest 2d ago in ~/DEV/claude-playbooks
────────────────────────────────────────────────────────────────────────────────
2 playbooks · 2 live sessions · read 0s ago
←→/1-9 tab c SHOW CREATE e export .cpb y copy r refresh esc back q quit
reads: cpb SHOW PLAYBOOK router --json · cpb SHOW SESSIONS --json
cpb tui in a terminal opens it; a script reads the same
state with the statement named on the screen's last line.
Built to be relied on
Stable since v3.24.0
Breaking changes wait for a major version. Every change is tested the same way, on the exact commit a release tags.
Get it
Install
$ curl -fsSL https://raw.githubusercontent.com/ramazanpolat/claude-playbooks/main/install.sh | sh
$ cpb --version
claude-playbook version v3.27.0
Linux and macOS, amd64/arm64 (no native Windows — WSL works). devbox, Nix, npx and source builds →