Agent
An agent beside you, on the page.
casebook never calls a model. A coding-agent session you already run joins through casebook channel: your messages from the page arrive in the session, and the agent answers, proposes and works through casebook's tools. It works with pi and with Claude Code. The agent never decides; that tool does not exist.
the channel
How a message reaches the agent.
casebook channel is an MCP server, one per agent session, over stdio. It learns the session's id from the harness, reports the session to casebook serve every 30 seconds so it appears in the page's session picker, and holds a long poll open for anything addressed to it.
- Turn-aware. Each session has a queue and at most one delivery in flight. A message you send while the agent is busy is
queued, and goes out when its turn ends, together with everything else queued so far, in order. There is no interrupt. - Read together. A delivery tells the agent how many messages it holds and when they were written, asks it to read all of them before acting, and to follow the latest where they conflict. Each message carries what you had attached: the selection, the open item, rule or job.
- Settled by the agent. The agent settles every message with
casebook_reply. A turn that ends without a reply leaves the messageunanswered, but only once the agent was actually shown it, so a delivery that arrived after its last tool call waits for the next turn. - Stuck and moved. A delivery with no activity for 10 minutes is marked stuck on the page, where you can release it or move it to another session. A session that disappears keeps its queue, and the panel offers to move it.
- No live view. The agent does not watch your page. What you were looking at travels with each message, and
casebook_statustells it what you did with its proposals since it last looked.
Message states
| state | meaning |
|---|---|
| draft | in the batch tray, not sent |
| queued | waiting for the agent's turn to end |
| delivered | sent to the session |
| received | the agent picked it up |
| working | the agent is on it |
| answered · declined · failed | settled by the agent |
| unanswered | the turn ended without a reply |
| interrupted | serve restarted while it was in flight |
The end of a turn comes from the harness. pi-casebook reports it on pi's agent_settled; in Claude Code, the Stop hook runs casebook settled --harness claude, which reads the session's transcript to see which deliveries the agent was shown.
pi
Set it up in pi.
pi gets channels from the channels.tools extension. Install it and pi-casebook, then name casebook channel in ~/.pi/agent/channels.json.
$ pi install npm:channels.tools $ pi install npm:pi-casebook
{ "channelServers": { "casebook": { "command": "casebook", "args": ["channel"] } } }
casebook's kempt manifest writes that channels.json entry for you. A new pi session spawns the channel itself; there is no launch flag.
pi-casebook
The extension connects a pi session to casebook in four ways:
- Journals git and gh calls. Bash tool calls that run
gitorghgo tocasebook record --harness piwith the session's id. casebook keeps verbs and targets, never the command line. - Briefs the first turn. The first agent turn of a session gets
casebook brieffor its repo as hidden context. - Syncs in the background.
casebook sync --no-githubruns at session start and shutdown; the scheduled sync does the GitHub refresh. - Reports settled turns. When the agent settles, it runs
casebook settled --session <id> --shown <deliveries>, naming the casebook deliveries the agent was shown that run.
Without the casebook binary the extension registers nothing and has no effect. CASEBOOK_BIN points it at a binary other than ~/.local/bin/casebook.
claude code
Set it up in Claude Code.
Register the channel as an MCP server named casebook, add the hooks, and launch Claude with the channel enabled. casebook's kempt manifest writes all of this; by hand it is:
In ~/.claude.json:
{ "mcpServers": { "casebook": { "type": "stdio", "command": "casebook", "args": ["channel"], "env": {} } } }
In ~/.claude/settings.json, three hooks:
| hook | command | does |
|---|---|---|
| Stop | ~/.local/bin/casebook settled --harness claude | ends the turn for casebook, so queued messages go out |
| PostToolUse (Bash) | ~/.local/bin/casebook record --harness claude | journals git and gh calls |
| SessionStart (startup, resume) | ~/.local/bin/casebook brief | briefs the session on its repo |
Channels are a Claude Code research preview, and casebook is not on Anthropic's approved list, so on your own you name it at launch with the development flag, as for galley:
$ claude --dangerously-load-development-channels server:casebook
Without the flag the tools still work, but page messages are not pushed into the session. Channels need Anthropic authentication; the galley docs cover the team and enterprise settings, which work the same way.
tools
The agent's tools.
Every tool goes through casebook serve, starting it when it is not running. A channel outside a pi or Claude Code session has no session id and can only read.
| tool | arguments | does |
|---|---|---|
| casebook_status | none | The attention counts, whether the page is open, and what changed since the agent last looked: how many of its proposals you accepted, and each one you changed or rejected, with your reason. |
| casebook_open | key or view | Open the page in your browser at one item, or at an Attention view (waiting, new, due, proposed, all, board), or at the front. Only when you ask, or to hand you something to review. |
| casebook_attention | view, kind, repo, q, offset, limit | The attention list, with the page's views and filters. q matches a substring of the key or title. |
| casebook_show | key | One item: its observation, decision, pending proposal, evidence and recent history. |
| casebook_history | key | Every journaled action and decision commit for an item. |
| casebook_propose | keys, disposition, until, note | Propose a decision for one or more items. You accept, change or reject it on the page. A newer proposal from the same session for the same item replaces the older one. |
| casebook_evidence | key, text | Attach a finding to an item, shown under evidence and attributed to the agent. |
| casebook_rule_draft | id, name, match, propose, note | Create or update a draft rule. Setting it active is refused. A draft with an unknown condition, a disposition its kind does not allow, or an until that does not parse is refused with the reason, and nothing is written. |
| casebook_progress | text, n, total | Set the agent's live progress line, with a bar when it reports n of total. |
| casebook_reply | ids, state, text | Settle your messages by id: received, working, answered, declined or failed, with the reply shown in the thread. A late answer to an unanswered or interrupted message still counts. |
| casebook_job_step | job, step, state, detail | Report an apply step: started, reported (casebook then verifies it), paused or failed, with the reason. |
| casebook_job_ask | job, step, question, text | Draft the public text for a step that posts, or ask you something mid-job. It opens a needs-you card; nothing is posted until you choose. |
There is no decide tool. The channel's standing instructions tell the agent the same: answer the page only through these tools, settle every message, post progress on long work, never decide, and open the page only when you ask or to hand you something to review.