Since I started using Claude Code, I have changed how I verify work. Instead of reading the code myself, I do two things: run it and watch the actual behavior, and have Claude write up the overall picture as a document, then read that. The reason is not only speed. At the current model level, I find this catches more errors than reviewing the code myself, and it surfaces drift in quality and direction earlier.
The same documents, screenshots and video go straight to customers and teammates. I do the engineering myself, and I handle all customer communication myself, so it suits me that what I make in order to verify is the same thing I make in order to explain.
I run LLM system development at Cognisant LLC, on contract. Each client project gets its own Claude Code session, so on a normal weekday six or more are running in parallel. The question is how to keep verification by behavior and documents running smoothly in that state. This article is the answer I have so far.
Every rule below was added after something happened. A commit landed on another branch. gh auth
had been switched back by another session. I automated Windows Terminal to record a demo and the working sessions froze along with it. None of it is dramatic, but at six sessions this kind of thing happens regularly.
Claude Code is a product of Anthropic. Nothing here is official guidance; it is one practitioner's operating procedure.
In my experience the failures collapse into four categories.
| # | Where it breaks | Symptom | Cause |
|---|---|---|---|
| 1 | Identity | ||
| You cannot tell which window belongs to which project, so you never close the finished ones | Sessions left on auto-generated names like proj-1f |
||
| 2 | git | ||
| Someone else's uncommitted work rides along in your commit; commits land on an unexpected branch | Multiple sessions sharing one working tree | ||
| 3 | Shared machine state | ||
gh auth reverts to another account; sequential IDs collide |
|||
| Several sessions rewriting the same machine-wide config | |||
| 4 | Output | ||
| You spend real time hunting for the md / pdf / xlsx a session just wrote | No human-side list of what changed |
One and two you can fix with discipline. Three is a property of the tools, so I neutralize it with a habit: switch and act in the same command. Four resisted discipline entirely and needed a tool.
claude --name mfg-aws-status
Mid-session, /rename mfg-aws-status
does the same. My convention is <project>-<task>
, ASCII lowercase, hyphen separated, around 20 characters.
Half the value is knowing which window you are looking at. The other half is that cross-session messaging, below, addresses sessions by name. Left on auto names, the roster shows proj-8e
and proj-b6
side by side and you have no idea which one to write to.
claude agents --json
lists everything running, with name and busy/idle state, across all projects. That listing is also where I decide which idle sessions to shut down.
When parallel sessions share a working tree, all four of these happen. All four happened to me.
| Pattern | What happens |
|---|---|
| Uncommitted work absorbed | Your in-progress edits get swept into a commit another session made first |
| Commit lands on the wrong branch | A commit attaches to the HEAD at commit time, not the branch you were editing on. If the other session checks out a feature branch, your commit lands there |
git add -A collateral |
|
You are halfway through editing a status file when the other session runs add -A ; your working copy is committed under their message |
|
| Stale base after a worktree push | The primary tree reports clean. You re-edit from an old base, copy into the worktree, and push a regression over the deploy that just went out |
There is one rule that covers all of it: in any project where parallel sessions can run, git worktree add first, then edit and commit inside the worktree. I relapsed once on a one-line docs change and reproduced the bug immediately.
Cut worktrees at a short path directly under the repository root, like .wt-<name>
. I put one under a long scratch directory and the Windows path length limit quietly corrupted the pnpm virtual store.
For the times you still touch the shared tree, chain the branch check into the commit itself:
[ "$(git branch --show-current)" = "feat/activity-panel" ] && git commit -m "..."
git add
takes explicit paths only; -A
is banned. Before committing, git diff --cached --name-only
confirms only the intended files are staged. I also keep a recovery procedure for when it goes wrong anyway: do not rewrite history with rebase or force push, just cherry-pick out of a temporary worktree onto your own branch.
Run gh auth switch
, then gh pr create
as a separate command, and another session may have switched the account in the gap. The PR opens under the wrong identity, with no warning.
gh auth switch --user Daichi-Kudo && gh pr create ...
Switch and act in one chain. That is the whole fix. Long-running commands like gh ... --watch
die for the same reason, so I replaced those with a hand-rolled loop that re-asserts the account on every iteration.
The same shape shows up anywhere sessions share writable state, such as sequential task IDs in a tracker. The countermeasure is also the same: writes must name an explicit ID, and anything destructive re-reads first.
This is the part that only started paying off at six sessions. Claude Code sessions can message each other directly: ListAgents
to see who is up, SendMessage
to write to one. On my machine this has worked on native Windows since v2.1.234.
A concrete example. The session that drafted this article took over an open-source Sublime plugin from another session. No human was in the handoff. I sent "I am taking this over; send me the status file path, current state, uncommitted changes, and the next steps," then got a notification when the other session went idle.
What came back included the repository HEAD, the tag, whether anything was uncommitted, whether a worktree existed, five prioritized next actions, and the tracker task ID. My contribution was one sentence asking for it.
I keep the usage narrow, to three cases.
notify_when_idle
gives you exactly one notification when the other session goes idle. No polling, no repeated "are you done yet."I skipped the declaration step recently and wrote split CI files into another session's worktree. That session had switched branches in the background, so my files landed on the wrong branch. I added the declaration rule after that.
Back to the fourth place things break: the output itself.
As I said at the top, what I verify is the deliverable rather than the code: the research written up as markdown, the proposal built as HTML, the aggregation produced as xlsx, plus the screenshots and video of the thing actually running. Checking those by eye is faster than reading the code, and it finds more. With six sessions running, a new file appears somewhere every few minutes. Walk six terminals asking each one what it just wrote, and finding takes longer than checking.
What I wanted was a single view of what just moved, with one click to open it, outside the terminal.
I have used Sublime Text for years, so I built a Recent Activity panel there, with Claude Code's help. It is open source (sublime-claude-code, MIT), and it is an unofficial community plugin, not affiliated with or endorsed by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic, PBC.
24h · docs & media
▼ data-platform 5 ●2
● dataplat-tiles
* 14:52 STATUS.md
14:51 …/status_archive/2026-09.md
○ dataplat-seo
14:50 …/snapshots/state.json ⟨.wt-x⟩ ×3
▶ manufacturing-client 12
Files changed in the last 24 hours, grouped project, then session, then file, newest first, opening on click. It lists documents and media by default (md, txt, html, pdf, xlsx, docx, pptx, csv, images, video); c
adds code files. The filled and hollow circles are busy and idle sessions, *
marks files changed since you last looked, and worktrees fold into their parent repository. A project is the directory you launched claude
in; a tool call that cd
s into a subdirectory does not split it. Projects you do not need to watch can be hidden with h
(Shift+H
brings them back).
Picking the data source was the hard design call. Here is what I measured, including the options I rejected.
| Source | What it gives you | Measured | Verdict |
|---|---|---|---|
| Filesystem watcher over live session working directories | Every file that actually changed, including ones written by Bash, scripts, or by hand | Event-driven; node_modules and logs pruned |
|
| Primary, the "what" | |||
| Claude Code hooks (PreToolUse / PostToolUse) | Exact Edit and Write paths, Bash start and end intervals, session name | ~50 ms per call including Python startup | Primary, the "who" |
| Full mtime scan | Same, complete but expensive | 99 s on a project with 1.58 M files; another produced 10,000 changes in 24 h from the worktrees directory alone | Rejected |
git status |
|||
| Uncommitted diff | 350 to 580 ms per repository | Rejected, "uncommitted" and "recent" are different questions | |
| Tailing the transcript jsonl | Same as hooks | Tens of MB per session | Rejected |
Hooks alone miss anything Bash writes. The watcher alone cannot say who wrote it. So the panel takes both and joins them, in three steps:
Step three is the weakness I still have. Run two sessions on the same project and unattributed rows appear. I have sketched parsing output paths out of the Bash command string to break the tie, but I have not shipped it.
Hook registration is a one-time edit to ~/.claude/settings.json
(use python3
instead of py -3
on macOS and Linux):
"hooks": {
"PreToolUse": [{ "matcher": "Bash",
"hooks": [{ "type": "command", "command": "py -3 \"<path-to-package>/scripts/activity_hook.py\"", "timeout": 5 }] }],
"PostToolUse": [{ "matcher": "Bash|Edit|Write|MultiEdit|NotebookEdit",
"hooks": [{ "type": "command", "command": "py -3 \"<path-to-package>/scripts/activity_hook.py\"", "timeout": 5 }] }]
}
I chose Sublime because it fits my hands. The same structure works in Zed or Neovim. The structure is the point: keep the agents in terminals, stand up a separate window for the human to read and judge in, and connect the two with a thin protocol. The long version of that argument is Don't Switch Your Editor, Connect the Agent.
One number for scale. My editor side, two windows plus a language server plus this plugin, sits at 164 MB. An agent session is roughly 500 MB, so six of them is about 3 GB. The lighter the side that reads and decides, the more headroom you keep for the side that works.
Three failures that only show up once you are parallel.
wt -w demo
to open six panes and rewrite settings for a demo recording made the whole of Windows Terminal stop responding, including the six windows doing paid work. Automation that opens terminals now goes to a separate conhost process (CREATE_NEW_CONSOLE
).| Moment | What to do |
|---|---|
| Launch |
claude --name <project>-<task> . Never run parallel on auto names |
| Before editing | In any project where parallel sessions can run, cut a worktree at .wt-* under the repo root |
| Commit | Chain the branch check into the commit. git add by path. Verify with --cached --name-only
|
| gh and trackers | Switch and act in one chain. Writes name an explicit ID |
| Before touching a shared tree | Message the owning session: what, where, until when |
| After landing on main | One message to the live sessions on that project |
| Finding output | Open from the separate window's project, session, file list. Do not go hunting |
| Automating terminals | Do not drive Windows Terminal. Use a separate conhost process |
"More sessions, more throughput" is a common claim. In my case, running more only got easier after two things: moving verification from the code to the behavior and the documents, and putting the reviewing side's procedure and tooling in place first. Without that, search time and cleanup cancel the gain.
Every rule here was added after something happened. The one I still do not have a good answer for is attribution when two sessions run in the same project. If you have a better way to break that tie, I would like to hear it in the comments.
Daichi Kudo