- Book: LLM Observability Pocket Guide
- Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
You ask the agent that wrote the branch to review it. It remembers why it made every change, so it agrees with itself. It also has write access, so "review" turns into "quietly fix two things and say it looks good". You end up with a third diff to read and no review.
A reviewer should be a different worker with a fresh context and no way to change the code. Claude Code gives you that as a subagent: one Markdown file with a tools allowlist. Three recent releases make it a better fit for the job. Version 2.1.292 (October 6) added an effort parameter to the Agent tool, 2.1.293 (October 7) added agentType to the subagent status line payload, and 2.1.296 (October 9) added autoCompactWindow to subagent frontmatter (changelog).
That last one is about money. Haiku 5.5 costs $0.10 per million input tokens for prompts up to 100K tokens, and $0.50 above that. The lowest value autoCompactWindow accepts is 100000.
Run claude --version first. Everything below needs 2.1.296 or later.
Step 1: write .claude/agents/reviewer.md
Project subagents live in .claude/agents/ and personal ones in ~/.claude/agents/ (docs). Use the project folder and commit the file, so every branch an agent cuts from main carries the same reviewer.
---
name: reviewer
description: Read-only reviewer for a finished branch
tools: Read, Grep, Glob
model: haiku
effort: medium
autoCompactWindow: 100000
---
You review changes that another agent made. You cannot
edit files, run commands or start other agents.
The caller gives you the base branch and the changed
files. Read each file and the code it calls.
For every finding, report:
- file:line
- severity: blocker, fix or nit
- what is wrong, in one sentence
- what to change, in one sentence
Look for: new branches with no test, error paths that
swallow errors, unvalidated input, names that no longer
match behaviour, and edits outside the stated task.
Only report what you can point to in the code. If you
are not sure, say so. End with a one-line verdict.
The tools line is what keeps it read-only. It's an allowlist, so the subagent gets those three tools and nothing else. The docs' read-only example allows Read, Grep, Glob and Bash, and says that subagent "can't edit files, write files, or use any MCP tools." This one drops Bash too, so it can't run git, sed -i or a test suite either. There's no Agent, so it can't hand the work to a subagent that has more tools. Leave tools out and the subagent inherits every tool available to subagents, which is the opposite of what you want here.
Claude Code watches both agents folders. Edit the file and the next delegation picks it up within a few seconds, with no restart. The exception: if .claude/agents/ didn't exist when the session started, restart once so the watcher sees it.
Step 2: a cheap model and a 100K compact window
model: haiku resolves to Haiku 5.5 on the Anthropic API (model config). On list price it's the cheap end of the range: $0.10 in and $0.50 out per million tokens under 100K-token prompts, against $2 and $10 for Sonnet 5.5 and $4 and $20 for Opus 5.5 (pricing). If Haiku's reviews turn out too shallow for your codebase, change one word to sonnet and keep everything else.
Haiku 5.5 runs with a 1M-token window, and models with a native 1M window auto-compact "at about 967K tokens by default" (model config). A reviewer that reads a big branch file by file can drift far past the 100K line before that happens, and every request past it is billed at the higher tier.
autoCompactWindow lowers the window for this one subagent, to any token count from 100000 to 1000000, while the main conversation keeps its own (docs). Two details from the docs bite people:
- Write a plain integer. Claude Code reads
100kin frontmatter as 100, which is out of range. - If
CLAUDE_CODE_AUTO_COMPACT_WINDOWis set in your environment, the subagent uses that instead and the field does nothing.
Setting it to 100000 should keep the reviewer's prompts close to the price break instead of letting them grow toward 967K. I haven't measured exactly where it compacts, so treat it as a lever, not a hard ceiling. The trade is real too: a compacted reviewer works from a summary of the files it read early on. Keep each review to a branch-sized change.
Step 3: raise the effort per call, and watch it in the status line
Haiku 5.5 supports effort levels from low to max and defaults to medium (model config). The frontmatter says medium anyway, so the file states what it does.
Most branches don't need more. A change to auth or billing does, and you shouldn't have to edit the file for one review. Since 2.1.292, when you ask Claude to run a subagent at a given level, it can pass effort on that one invocation (docs):
Use the reviewer subagent at high effort on src/auth/.
The per-call value overrides the frontmatter and stays in effect if the subagent is resumed. CLAUDE_CODE_EFFORT_LEVEL beats both, so unset it if you exported it for something else. It applies to normal subagents, not forks.
Note the "can" in the docs. Claude decides whether to pass the parameter, so you want to see what it actually did. That's what the subagent status line is for. Add this to ~/.claude/settings.json (statusline docs):
{
"subagentStatusLine": {
"type": "command",
"command": "~/.claude/subagent-statusline.sh"
}
}
The script gets every visible subagent row as one JSON object on stdin, with a tasks array. It writes one JSON line per row it wants to override, as {"id": ..., "content": ...}. Rows it skips keep the default name · description · token count look. Since 2.1.293 each task carries agentType, the same value hooks get as agent_type, so you can pick out your reviewer from the built-in Explore and anything else running:
#!/usr/bin/env bash
# ~/.claude/subagent-statusline.sh
# Restyle reviewer rows; leave the rest as they are.
jq -c '.tasks[]
| select(.agentType == "reviewer")
| {id: .id,
content: ("REVIEW · " + (.model // "model?")
+ " · effort " + ((.effort // "unset") | tostring)
+ " · " + (.tokenCount | tostring) + " tok")}'
model and effort are optional fields, omitted until they have a value, hence the // fallbacks. effort can also be a number (a token budget), hence tostring. Make it executable and feed it a fake row before trusting it:
chmod +x ~/.claude/subagent-statusline.sh
echo '{"tasks":[{"id":"t1","agentType":"reviewer",
"effort":"high","tokenCount":41200}]}' \
| ~/.claude/subagent-statusline.sh
When the real reviewer runs, its row shows the effort it was given. If you asked for high and it says medium, Claude didn't pass the parameter. Ask again. The @-mention form, @"reviewer (agent)", "guarantees the subagent runs for one task" (docs), but that only controls which subagent runs. Nothing in the docs says it passes effort. For a review that has to run at high, keep a second file, reviewer-deep.md, with effort: high in its frontmatter.
Step 4: review another agent's branch, then send the findings back
Say Codex or another Claude Code session has finished a task on its own branch. Git refuses to check out a branch that another worktree already has checked out (git-worktree), and you don't want to touch the author's folder anyway. Give the review its own worktree with a detached HEAD at the branch tip:
cd ~/code/app
git worktree list
git worktree add --detach ../review-login hermes/fix-login
cd ../review-login
claude
Then, in that session:
Run git diff --stat main...HEAD. Then use the reviewer
subagent on every changed file. The base branch is main.
The main session has Bash, so it runs the diff and passes the file list along. The reviewer starts with a fresh context window, without your conversation or the files the main session already read (docs), and only its report comes back. A detached checkout stays on the commit it started from, so the reviewer reads the branch as it was when you began. After the author pushes fixes, git checkout --detach hermes/fix-login moves the review copy to the new tip.

Two real agent sessions side by side: Codex on orders-types after adding a RefundStatus type, and Claude Code on orders-api after a follow-up turn, each in its own hermes/ worktree, with status, context use, cost and branch in the sidebar.
The hermes/ branch name is where Hermes IDE comes in. I build it, so weigh this part with that in mind. Hermes starts each task on its own hermes/<task> branch and worktree, and runs every agent in its own real terminal. So the author can be Codex in one pane and the review session can be Claude Code in the next, with the statusline from step 3 working as usual, because it's Claude Code's own interface.
The reviewer hands you a list of file:line findings. Now they need to reach the author, and copying them into the right terminal one at a time is where review loops go wrong. Hermes saves every agent turn. Its Review Desk (⌘G, or Ctrl+Shift+G on Windows and Linux) shows the author's changes by turn or by file, and a line comment you leave there goes back to the agent that wrote that line (README).

The Review Desk (⌘G) in By turn view: two turns (T1: 3 files +69 −1, T2: 1 file +1 −0), turn 1's diff of src/db.ts, the changed-files list, and a commit message drafted from the turns.
Open the author's task there, find each line the reviewer named, and put the reviewer's "what to change" sentence on it as a line comment. Send the blockers and fixes. Read the nits and drop the ones you disagree with. You stay the filter between two models, and the by-turn view shows which turn introduced each problem. Hermes never types into a terminal on its own, so nothing reaches the author until you send it.
When the review is done, remove the review copy. Git refuses to remove a worktree with modified or untracked files, which doubles as a cheap check that nothing in the review session edited anything:
cd ~/code/app
git worktree remove ../review-login
What a read-only reviewer won't catch
It can't run anything. No tests, no type checker, no linter. Those belong in a check that runs the code. In Hermes, your own checks can decide when a task is done. Outside it, CI does that job.
Read-only isn't secret-proof. The reviewer can read any file the Read tool is allowed to open. The settings docs show deny rules such as Read(./.env) for files no agent should open.
Its findings can be wrong. A small model at medium effort will miss things and occasionally invent a problem, which is why the system prompt asks for a line number on every finding and why you check each one before it goes back. I haven't run this reviewer across a large codebase myself, so compare it with your own review on a few branches before you lean on it.
A subagent also can't review its own parent's reasoning. It sees code, not intent. If the task description matters, paste it into the prompt so "edits outside the stated task" has something to check against.
If this was useful
The status line trick is a small piece of a bigger habit: knowing what your LLM workers actually did, on which model, at which effort, for how many tokens. The LLM Observability Pocket Guide is the short read on tracing, evals and cost for LLM systems, and on picking the tools that fit your team. If you want to run the author and the reviewer side by side, Hermes IDE is free, source-available (BSL 1.1), runs on macOS, Windows and Linux, and isn't affiliated with Anthropic or OpenAI. A star on GitHub helps other developers find it.

Top comments (0)