Herdr, Caprock and ccdeck compared: keeping track of several coding agents (November 2026)
Four agents running and one has been waiting for you for twenty minutes. Herdr, Caprock and ccdeck each see it from a different place. What they can do, what they measure and send, what OSC 7501 changes, and which to pick.

When I opened Claude Code in this website's folder tonight, the session came with a note I had not written: a summary of where the previous session had stopped three days earlier, including the three Search Console requests that were still open. The note came from Caprock, which has been keeping track of my Claude Code sessions since mid-October. That is useful, and also a little uncomfortable, because it means something is reading along with everything Claude Code does.
Caprock is one of three tools that answer the same question. You have four agents running and one of them has been sitting at a permission prompt for twenty minutes. Which one? Herdr, Caprock and ccdeck all answer it, each from a different position. That position decides what they can see, whether you can answer from the tool and what they take from your machine. Below: how each one works, what the new terminal standard OSC 7501 changes, and who each tool is for.
Caprock has been running on my laptop since 16 October and Herdr since 4 November. ccdeck was installed from 22 to 29 October. For this article I went through the documentation, the source of the ccdeck package and the files on my own disk. All figures are from 8 November 2026.
Short answer. Herdr is a terminal multiplexer for agents, similar to tmux. Sessions keep running when you close the window, also on other machines over SSH, and every pane shows whether its agent is working or waiting for you. Caprock and ccdeck are dashboards that read along with Claude Code (and Codex) through hooks and show what is happening and what it costs. Caprock also has its own terminal tabs and tracks cost, plan limits and pull requests. ccdeck draws each session as a tree of subagents and tool calls. If you run one or two sessions at a time, you need none of the three.
What problem do they solve?
A coding agent in a terminal is hard to keep an eye on. It works on its own for minutes and then stops at a question. May I run git push? Which of the two fixes do you want? From the outside, a tab that is waiting looks exactly like a tab that is working. With one session you notice. With four sessions in four tabs, or two repositories and a server over SSH, you click around until you find the stalled one. Usually it is the agent that was nearly done.
Two more questions come with it that the terminal does not answer. The first is cost. On a subscription you do not pay per token, but you do run into a five-hour and a weekly limit. The second is what the agent actually did. By default, Claude Code cleans up its transcripts after 30 days, and what is gone can no longer be searched.
Each tool puts its weight somewhere else. Herdr is about the first question and about keeping sessions alive. Caprock is mostly about money and history. ccdeck shows what is happening right now, down to every tool call.
Three places to watch from
The difference comes down to one architectural choice: which program owns the terminal the agent runs in?

An agent such as Claude Code runs in a pseudo-terminal (pty). The program that opens the pty sees everything the agent puts on screen and can send keystrokes back. A program that only reads along through hooks receives events: a tool starts, a tool finishes, the session is waiting. It has no keyboard, though. It can see that Claude is waiting for you, but you cannot type "yes" into it.
Herdr: Herdr owns the terminal
Herdr consists of three programs, which is confusing at first. The Herdr TUI is the original: a single Rust binary that runs in your existing terminal, with panes, tmux-style prefix keys and a server in the background. You close the terminal and the agents keep working. herdr reattaches. In mid-October, herdr-core (command hc) and the Herdr app joined it. Core is a server that runs terminals and draws nothing itself. The app is a desktop program on top of that core. The TUI and the app do not share agents: what you start in the TUI does not show up in the app.
Because Herdr owns the terminal, it can do things a dashboard cannot. You simply answer in the pane. You add a machine over SSH (hc machine add), and its terminals appear in the same list as your local ones. Agents can also drive each other: one agent starts a helper, steers it and waits until it is done.
hc run --bg --name review claude "Review src/Import.php. Read-only. Report with hc send $HC_TERMINAL_ID when done."
hc send review "Focus on the error handling."
hc wait review
hc read review --lines 80 What Herdr does not know: what a session costs, how many tokens go in, which subagent called which tool. It sees the terminal, not the conversation. It is by far the largest of the three, though. On 8 November the TUI repository had 49,386 stars, and its 98 releases had been downloaded more than two million times in total. All three parts are free and licensed under Apache 2.0.
ccdeck: reading along through hooks
ccdeck, by developer Bargan Constantin, starts with npx ccdeck or as a desktop app. On first run it adds a hook to ~/.claude/settings.json for eleven events, from SessionStart to Notification. Each event starts a Node script (hook.js) that posts the JSON to the local server with a one-second timeout. That server listens on port 4317 by default and draws every session as a tree, with subagents as branches and tool calls as nodes. Sessions waiting on a human go to the top, longest wait first.
The hook writes nothing back and always exits with code 0. That is deliberate. Claude Code lets a hook allow, deny or rewrite a tool call through stdout or its exit code, and ccdeck uses neither. It cannot get in your agent's way, but it cannot answer on your behalf either. It can resume a stopped background session with Continue.
ccdeck reads Codex differently. According to the README, Codex hooks do not fire reliably on Windows, so ccdeck reads the rollout files in ~/.codex/sessions/ instead. Such a log records what happened, not what is waiting now. That is why the waiting queue is Claude Code only.
ccdeck also does a lot that has little to do with the core question: switching between several Claude and Codex accounts, sharing logins with other decks on your network, Jira, GitHub and GitLab panels, a radio player, and Browser Watch. Browser Watch checks your browser history to see whether a program drove your browser while you were away. More on that under the cost of watching. ccdeck is free and has been AGPL-3.0 since version 3.22.0. Earlier releases were MIT.
Caprock: reading along, plus its own terminal
Caprock, by the GitHub user dspv, combines both positions. A local daemon written in Go reads along with every Claude Code session through hooks and transcripts, including sessions you start in a plain terminal. On my laptop its hook sits on ten events. The desktop app also has its own terminal tabs for Claude Code, Codex, OpenCode and Gemini CLI, per project and per git worktree. A session Caprock starts itself runs in Caprock's pty (the helper is literally called caprock-pty-host.exe). Only those sessions can be answered with Yes or No from the app, a notification or your phone. For a session from your own terminal, Caprock sees that it is waiting, but you answer in that terminal.
Its focus is money and history. Caprock prices every turn at API list prices, per repository, and puts your Claude and Codex plan windows next to it. The README itself calls this "an estimate", not a bill. The author writes that in August he used $5,898 worth of API usage on a $200 Max plan and only noticed because Caprock added it up. Every session also stays searchable after Claude Code's 30-day cleanup has deleted the transcript. A Pipeline screen follows pull requests from agent to release, with the CI state per operating system.
The note from the introduction is a Caprock feature too. When you start a new session in a folder you worked in before, it is handed the last thing the previous session said there. This is on by default. If you want to know whether it helps, you can turn on a setting that leaves it out of one in four new sessions, and the Memory screen compares the two groups. I like that for a feature you would otherwise judge by gut feeling.
The core is free and licensed under Apache 2.0. Premium costs $30 a year or $100 once and adds features that act, such as a daily spend cap and pausing sessions when the plan limit is close. According to the README, Caprock never makes a request to its maker to verify the licence key.
How does a tool know an agent is waiting for you?
There are three ways, and all three show up in these tools.
Reading the screen. The Herdr TUI finds the agent process in each pane and reads the bottom of the screen. Rules per agent decide whether that screen means "working", "blocked" or "idle". That way it works for over twenty agents without their makers doing anything. It is still guessing from text, though: if an agent changes its prompt, the rule stops matching.
Hooks. Claude Code starts a command on every event and passes it JSON on stdin. A Notification event means Claude is waiting for you. That is precise, but it is Claude Code's own channel. Every agent has its own hook system, or none at all.
OSC 7501. On 6 October 2026, Mitchell Hashimoto, who created the Ghostty terminal, published the Program Status Protocol. It is an escape sequence a program writes into its own output to report how it is doing. A terminal that does not know the sequence ignores it. Claude Code has supported it since version 2.1.295. The changelog says terminals that implement it can show whether Claude Code is working, waiting on you or done. herdr-core uses only this route. It does not read screen text and does not recognise brand names. A program that reports no status has none.
What does an OSC 7501 sequence look like?
You can type one into a terminal yourself:
printf '\e]7501;state=blocked:kind=question:app=demo\e\\' After ESC ] 7501 ; come key=value pairs separated by colons, and the sequence ends with ESC \. state is required and is one of idle, working, done, blocked or error. With blocked, kind says what the program is waiting for: permission, question or auth. msg is a single line of explanation in base64, so no escape characters end up in the sequence.
The nice thing about this choice is that the status travels in the same stream as the text. Over SSH, in a container, in a Herdr pane on another machine: wherever the text arrives, the status arrives too. A hook needs its own connection to a server on 127.0.0.1 for that, and on another machine there is no such server.
OSC 7501 in your own PHP script
The protocol is not just for agents. A long-running PHP script, such as an import or a migration, can report the same way that it is done or stuck. Here is a small, complete version:
<?php
declare(strict_types=1);
// Report this script's status through OSC 7501 (Program Status Protocol).
// Only to a real terminal: in a log file or a pipe it is just noise.
function programStatus(string $state, string $msg = '', string $kind = ''): void
{
if (!stream_isatty(STDOUT)) {
return;
}
$body = 'state=' . $state . ':app=csv-import';
if ($kind !== '') {
$body .= ':kind=' . $kind;
}
if ($msg !== '') {
$body .= ':msg=' . base64_encode($msg);
}
fwrite(STDOUT, "\e]7501;{$body}\e\\");
}
$file = $argv[1] ?? 'customers.csv';
$fh = @fopen($file, 'r');
if ($fh === false) {
programStatus('error', "Cannot open {$file}");
fwrite(STDERR, "Cannot open {$file}\n");
exit(1);
}
programStatus('working', "Processing {$file}");
$header = fgetcsv($fh, null, ',', '"', '') ?: [];
if (!in_array('email', $header, true)) {
programStatus('blocked', 'Column "email" is missing', 'question');
echo "Column email is missing. Continue without email? [y/n] ";
if (trim((string) fgets(STDIN)) !== 'y') {
programStatus('error', 'Aborted: no email column');
exit(1);
}
programStatus('working', 'Continuing without email');
}
$count = 0;
while (fgetcsv($fh, null, ',', '"', '') !== false) {
$count++; // the real import goes here
}
programStatus('done', "{$count} rows read");
echo "{$count} rows read\n"; Two details. stream_isatty() keeps the sequence out of a log file when you redirect the output. And the empty fifth argument to fgetcsv() turns off the outdated escape handling, so PHP 8.4 does not raise a deprecation notice. I ran the script on PHP 8.2 and 8.3 and checked the bytes of the sequence. I did not test whether the Herdr app actually shows this script's status.
Herdr, Caprock and ccdeck side by side
| Herdr | Caprock | ccdeck | |
|---|---|---|---|
| What it is | Terminal multiplexer for agents (TUI, app and core) | Desktop app and local daemon with a dashboard | Local dashboard in the browser or as a desktop app |
| Owns the terminal | Yes | Only for sessions it starts itself | No |
| Sees a waiting agent through | OSC 7501 (core and app), screen text (TUI) | Hooks and transcripts | Hooks (Claude Code); Codex log without waiting state |
| Answer from the tool | Yes, in the pane | Yes, for its own sessions, also from your phone | No |
| Cost and limits | No | Yes, API list price per repository and plan limits | Yes, per session, plus quota |
| Agents | Any terminal agent; status when it reports OSC 7501 | Claude Code, Codex, OpenCode, Gemini CLI, Hermes Agent; DeepSeek Harness read-only | Claude Code and Codex |
| Other machines | Yes, over SSH | Phone through an encrypted relay, pairing other computers | Viewing through ssh -L |
| Licence and price | Apache 2.0, free | Apache 2.0; Premium $30 a year or $100 once | AGPL-3.0, free |
| Telemetry by default | App: on, with a random install ID | None | Usage reports with IP address and device fingerprint |
| Written in | Rust | Go | TypeScript |
| Status on 8 November 2026 | TUI v0.9.5, 49,386 stars | v0.175.0, 41 stars | v3.82.2, 29 stars |
What does watching cost?
All three run locally and are open source. Each still takes something, and the defaults differ more than the websites suggest.
Time per tool call
A hook is a program Claude Code starts on every event, and Claude Code waits for it to finish. A PreToolUse hook is allowed to block a tool, after all. For Caprock that is caprock.exe hook, a 30 MB Go binary. For ccdeck it is Node running a 1,275-line script. Just starting such a process, without it doing any work, took a median of 91 milliseconds for caprock.exe version and 39 milliseconds for an empty Node process on my laptop (Windows 11, i9-13980HX), over 25 runs.
Every tool call produces two events: PreToolUse and PostToolUse. With Caprock, at least a fifth of a second per tool call goes into starting the hook. In a session with two hundred tool calls, that is over half a minute. You notice it, but it disappears next to the time the model itself needs. Processes usually start faster on Linux and macOS than on Windows, but I did not measure that. herdr-core needs no hook for status, because the status comes out of the terminal through OSC 7501.
Disk, memory and secrets
According to caprock doctor, the daemon on my laptop used 157 MB of memory and 1.8 percent CPU. The data folder was 771 MB, of which 355 MB was the database, after 584 ingested transcripts. Almost all of the rest was a backup of similar size that Caprock made before a schema upgrade. The contents matter more than the size. That database holds everything Claude Code read and wrote, including the full output of every tool call. The README warns about this itself: an API key a command printed, or a .env file that was read, ends up in there too. Treat the file like your shell history, and keep it out of bug reports.
What leaves your machine
Caprock has no account and no telemetry. Its network features (release checks, the Gemini chat on your own key, GitHub, Telegram) are off until you turn them on. For the phone, traffic goes encrypted through a relay (Noise NK with X25519 and AES-GCM). That relay sees which machine connects when, from which IP address and how many bytes pass.
The Herdr app sends a daily usage report to telemetry.herdr.dev by default, with a random install ID, versions, operating system, bucketed usage time, known agent names and command names. According to the documentation, terminal text, prompts, files and folder paths are not included. You turn it off under Settings → Privacy or with "telemetry": false in the settings.
ccdeck sends usage reports that its own FAQ describes as "no longer anonymous": version, system, your IP address, a device fingerprint and errors, unless you start it with AGENTS_DECK_NO_REPORTS=1. The sessions themselves stay on your machine. The local network feature is on by default, so the deck also listens on your LAN. Browser Watch is on by default too: every five minutes ccdeck copies the history database of each Chromium profile (Chrome, Brave, Edge, Vivaldi) and checks the visits since the deck started. For Codex quota it refreshes your token when needed and rewrites ~/.codex/auth.json.
My opinion: for a tool whose core is "which session is waiting for me", ccdeck has too much switched on by default. If you use it, turn off the reports, the local network and Browser Watch.
Also watch what stays behind. According to the README, npx ccdeck --uninstall removes only the hooks, the login item and the shell profile block. The hook.js script, the data and up to 90 days of tool history stay. --uninstall --purge also deletes the files holding the local network key. On my laptop, ~/.agents-deck and ~/.claude/agent-dag were still there a week and a half after the hooks were removed. You remove Caprock with caprock hooks uninstall, which leaves other hooks alone. caprock down plus deleting the data folder removes the rest.
What you run into on Windows
- Caprock's Windows installer is not code-signed yet, and neither are ccdeck's desktop apps. Expect a SmartScreen warning on first launch.
- On Windows, herdr-core runs over named pipes that only your own account and SYSTEM can open. Templates and quoted shell commands need
sh, for example from Git for Windows. The Herdr app needs Windows 10 version 1803 or newer, with curl and tar. - From a Claude Code session with the sandbox on,
hc lson my laptop returned "Access denied (os error 5)" on the core's pipe.hc's own hint names a core started with elevated rights as a possible cause. I did not work out which of the two it was. If you want agents to work together throughhc, first check that they can reach the core from their own environment. - Caprock says part of its OpenCode and Codex features has only been verified on macOS.
Is it useful, and which one should you pick?
If you work with one or two sessions on one machine, you need none of the three. Claude Code now reports its own status through OSC 7501, so a terminal that supports the protocol shows that Claude is waiting, with no extra software.
Pick Herdr if you run several agents at once, including on servers over SSH, and want them to keep working when you close the window. It is essentially tmux for agents, and in the app and core the status comes from a standard instead of guessed screen text. That makes it the option most likely to survive your agent's next release. Herdr says nothing about cost, the app has only been out since October, and you have to switch off the app's telemetry yourself.
Pick Caprock if you mostly use Claude Code and want to know what your sessions cost, how close you are to your limit and what an agent said last week. It collects nothing for its maker and is the only one of the three that both reads along and runs terminals itself. On the other hand, it is the work of one developer with 41 stars, who shipped 175 versions in under three months. Bugs get fixed fast, but a lot changes too. And the database holds everything.
Pick ccdeck if you want to see the tree of subagents and tool calls live, or if you switch between several Claude and Codex accounts. On that last point ccdeck goes further than the other two. Do switch off the defaults listed above.
Herdr and Caprock do not get in each other's way, because they sit in different places: Herdr owns the terminals and Caprock reads the hooks. Caprock and ccdeck together do overlap. Claude Code then starts two hook processes per event, and two programs write to the same settings.json.
Frequently asked questions
What is OSC 7501?
OSC 7501, or the Program Status Protocol, is an escape sequence a program in a terminal uses to report whether it is working, waiting, done or in error. The sequence travels with the normal output, and terminals that do not know it ignore it. Mitchell Hashimoto published the protocol on 6 October 2026, and Claude Code has supported it since version 2.1.295.
Are Herdr, Caprock and ccdeck free?
Yes. Herdr (all three parts) and Caprock's core are licensed under Apache 2.0, and ccdeck under AGPL-3.0. Only Caprock has a paid tier: Premium costs $30 a year or $100 once.
Do they work with Codex and other agents?
Herdr runs any agent that runs in a terminal, and shows status for agents that report OSC 7501 or that the TUI has rules for. Caprock supports Claude Code, Codex, OpenCode, Gemini CLI and Hermes Agent. ccdeck supports Claude Code and Codex, but its waiting queue only works for Claude Code.
How do I see which hooks my Claude Code has?
Inside Claude Code, /hooks shows them. In PowerShell, this line lists the command per event:
(Get-Content ~/.claude/settings.json -Raw | ConvertFrom-Json).hooks.PSObject.Properties |
ForEach-Object { "{0}: {1}" -f $_.Name, ($_.Value.hooks.command -join " | ") } On macOS or Linux, this does the same:
python3 -c "import json,os; h=json.load(open(os.path.expanduser('~/.claude/settings.json'))).get('hooks',{}); [print(k, [x['command'] for g in v for x in g['hooks']]) for k,v in h.items()]" Can I approve a permission prompt from the dashboard?
Only if the dashboard owns the terminal. In Herdr you answer in the pane. In Caprock you can for sessions Caprock started itself. ccdeck deliberately cannot: its hook writes nothing back to Claude Code.
One last thought. The question "which agent is waiting for me?" is moving from the dashboards into the terminal. Now that Claude Code reports its own status, nobody needs to guess from screen text or install hooks to know it. What is left for a dashboard are the questions a terminal cannot answer: what did this cost, what did the agent say last week, which pull request does it belong to? So pick your terminal first. Only then decide whether you want a dashboard, and what you let it read.
Further reading on this site
- Letting Claude Code work autonomously: auto mode, the Ralph loop and tmux
- Multi-agent AI: agents that work together, and why it goes wrong at the handoff
- Using Claude Code effectively: what actually works in 2026
- What is an agent harness, and why can it matter more than the model?
Sources
Official documentation and source code
- Herdr, herdr.dev, supported agents and add Herdr support, accessed 8 November 2026
- herdrdev, herdr (TUI, release v0.9.5 of 14 October 2026), herdr-app and herdr-core, including the security docs of app and core (telemetry, named pipes), accessed 8 November 2026
- dspv, Caprock, README and release v0.175.0 of 7 November 2026, plus the post on what Claude Code costs per month
- Bargan Constantin, ccdeck and ccdeck.dev, README and npm package 3.82.2 of 7 November 2026 (including
hook/hook.js) - Anthropic, Claude Code CHANGELOG, version 2.1.295: "Added Program Status Protocol (OSC 7501) support"
- Mitchell Hashimoto, Program Status Protocol (OSC 7501), 6 October 2026
Own observations
- Laptop running Windows 11 with an i9-13980HX, 8 November 2026: Claude Code 2.1.319, Caprock 0.175.0 (
caprock statusandcaprock doctor), herdr-core 0.1.18. Start-up times are the median of 25 runs after three warm-up runs, measured with Python'stime.perf_counter. Install dates derived from the file dates of the data folders. - The PHP example was run on PHP 8.2.35 and 8.3.36, with a CSV with and without an
emailcolumn and a file that does not exist. The OSC bytes were checked withbin2hex. Display in Herdr was not tested.


