Claude Code Subagents: Examples Worth Copying

Four subagent files you can drop into .claude/agents/ today: a reviewer that cannot edit, a test runner that only reports, a docs checker, and a board recorder that can read and comment and nothing else. Each with the reasoning behind its tool list.

6 min read

The Claude Code subagents worth copying are small and narrow: one job, a description that tells Claude when to use it, and a tools list that makes the wrong actions impossible rather than merely discouraged. Below are four complete files for .claude/agents/: a code reviewer, a test runner, a docs checker and a board recorder. Each comes with why its tool list and model are what they are, so you can adapt them instead of pasting them blind. If you are collecting subagents from repositories on GitHub, the same reasoning is the checklist for reading someone else’s.

This post assumes you know what a subagent is and how Claude hands work to one; Claude Code Task tool vs subagents covers that. A larger worked example, a project manager subagent with a hook that stops it moving cards, is in building a project manager subagent.

The fields that matter

A subagent is a Markdown file with YAML frontmatter; the body is its system prompt. The subagents documentation (opens in a new tab) lists many fields, but four do most of the work:

  • name and description are the only required ones. Claude reads the description to decide when to delegate, so write it as an instruction: when to use it, and when not to.
  • tools is an allowlist. Leave it out and the subagent inherits every tool the main conversation has, MCP tools included. List tools and it gets only those.
  • model takes an alias such as sonnet, opus or haiku, a full model ID, or inherit. Match it to the job: reading and summarising rarely needs the largest model.
  • maxTurns stops a subagent after that many agentic turns and hands back its output marked as partial. A cheap guard against one that wanders.

Others are useful in particular cases: disallowedTools to remove a tool from an inherited set, permissionMode, memory for notes that persist across sessions, isolation: worktree for a private checkout, and hooks for rules a tool list cannot express.

1. A code reviewer that cannot edit

.claude/agents/code-reviewer.md
---
name: code-reviewer
description: Reviews a change for bugs, missing tests and unsafe patterns. Use after a feature or fix is written and before it is committed. Does not fix anything.
tools: Read, Grep, Glob
model: sonnet
memory: project
---

You review code changes. You were given the changed files or the diff.

For each problem, report: file:line, what is wrong, why it matters, and the
smallest fix. Order by severity. Say plainly when you found nothing serious.

Check: error handling, input validation, tests that cover the change, and
anything that contradicts the conventions in your memory.

When you learn a convention of this codebase, add it to your memory.

Why it is built this way. Read, Grep, Glob and nothing else: no Edit, no Write, no Bash. A reviewer that can also fix things tends to fix things, and then nobody reviewed the fix. With this list it cannot change a file however it is prompted. Because it has no shell it cannot run git diff itself, so ask the main conversation to pass the diff or the changed files in the delegation. memory: project gives it a notes folder under .claude/agent-memory/ that it reads at the start of each run, so the conventions it learns in March are still known in May.

2. A test runner that only reports

.claude/agents/test-runner.md
---
name: test-runner
description: Runs the test suite and reports failures. Use whenever tests need running. Never use it to change code.
tools: Read, Grep, Glob, Bash
model: haiku
maxTurns: 15
---

Run the tests with the project's test command. Do not edit any file.

Report, in at most fifteen lines:
- the command you ran and the pass/fail counts
- for each failure: test name, the assertion or error line, and the file
  that most likely holds the cause

Leave out passing tests, stack frames from libraries, and progress output.

This is the single most useful subagent to have. A full test run can print thousands of lines; in the main conversation they crowd out everything else, and in a subagent they stay in its context while fifteen lines come back. It needs Bash to run the tests, which is the one real grant here, so the prompt keeps it to the test command and maxTurns keeps it from turning a failure into a debugging session. A small, fast model suits a job that is mostly reading output and summarising it. Fixing is a separate job, with a separate subagent or the main conversation.

The limit of this design is worth stating: with Bash granted, “run only the tests” is an instruction, not a control. If you need it enforced, add a PreToolUse hook to the frontmatter that exits with code 2 for any command that is not your test command; the hooks reference (opens in a new tab) explains the exit codes, and the project manager example above shows the pattern.

3. A docs checker

.claude/agents/docs-checker.md
---
name: docs-checker
description: Checks that README, docs/ and code comments still match the code after a change. Use after changing a public function, a CLI flag, a config key or an endpoint.
tools: Read, Grep, Glob
model: sonnet
---

You check documentation against code. You do not edit.

For the change you were given, find every mention of the changed names in
README.md, docs/ and comments (use Grep). For each one that is now wrong,
report: file:line, what it says, what is true now.

Also report public names in the change that are documented nowhere.

Documentation drifts one change at a time, and the moment to catch it is right after the change, while Claude still knows which names moved. The checker is read-only for the same reason as the reviewer: it reports, and the main conversation, which has the context, writes the fix. Its description names the triggers, a function, a flag, a config key, an endpoint, so Claude reaches for it at the right moments without being asked.

4. A board recorder that can only read and comment

The last one does no engineering at all. It writes the outcome of work onto the task the work belonged to, so the record outlives the session. It assumes a fenbs board connected in Claude Code as an MCP server named fenbs; the MCP documentation (opens in a new tab) gives the naming rule that turns the board’s fenbs_comment tool into mcp__fenbs__fenbs_comment.

.claude/agents/board-recorder.md
---
name: board-recorder
description: Records the outcome of finished work on its fenbs task. Use when a task is done or stopped and you have a ref such as BUG-042. Never use it to change a task.
tools: mcp__fenbs__fenbs_whoami, mcp__fenbs__fenbs_get_item, mcp__fenbs__fenbs_search, mcp__fenbs__fenbs_list_items, mcp__fenbs__fenbs_comment
model: haiku
maxTurns: 8
---

You record work on the fenbs board. You were given a task ref and a summary.

1. fenbs_get_item on the ref. If it does not exist, fenbs_search for the
   title and use the match; if none, report that and stop.
2. Comment once, starting with "recorder:". Say what changed, the commit
   hash, and how it was checked (or that it was not).
3. Report the ref and the first line of your comment.

The tool list is the design. It can read tasks, search and comment; it cannot create, move, edit or delete one, because fenbs_create_item, fenbs_update_item and fenbs_delete_item are not on the list. Moving the task to Completed stays with the main conversation or with you. The “recorder:” prefix matters because every subagent in a session shares the session’s connection, so the board records them all as Claude acting for you; the prefix tells this one’s comments apart.

The board has a second gate of its own. The session’s connection holds the scopes you ticked when you approved it (read, write, comment), and fenbs checks them on every call. If you want the board itself to refuse anything but comments, connect the session with a token that has only read and comment ticked; the recorder’s tool list and the token then agree.

The same subagent without a file

For a one-off or a CI job you may not want a file in the repository. The `--agents` flag (opens in a new tab) takes the same definition as JSON for the current session only, with prompt in place of the file body:

Terminal
claude --agents '{
  "test-runner": {
    "description": "Runs the test suite and reports failures. Never changes code.",
    "prompt": "Run the tests. Report the command, counts, and each failure with its likely file.",
    "tools": ["Read", "Grep", "Glob", "Bash"],
    "model": "haiku"
  }
}'

Reading a subagent you found on GitHub

Collections of subagent files are easy to find, and a file from one is a prompt plus a set of permissions. Read it the way you would read a script before running it:

  • No tools line means it inherits everything, MCP tools included. Add one.
  • A hooks block runs shell commands with your user’s permissions while the subagent is active. Read every command it names.
  • An mcpServers block can start or connect servers you have not added yourself.
  • A description such as “use proactively for all tasks” means Claude will reach for it constantly. Narrow it to the job.
  • Check model. A file written for the largest model may not need it, and every delegation costs tokens.

Commit the ones you keep to .claude/agents/ so the team reviews changes to them like code, and put personal ones in ~/.claude/agents/. To adapt one, ask Claude to rewrite it for your project, or edit the file directly; on recent versions /agents no longer opens a creation wizard.

Related

Connect the board the recorder writes to: Claude Code integration. What each scope allows: assistant tokens and scopes. When several workers need to talk to each other rather than report back: subagents vs agent teams.

Questions people ask.

Where do Claude Code subagent files go?

In .claude/agents/ inside a project, where they can be committed and shared with the team, or in ~/.claude/agents/ for every project you open. Each is a Markdown file with YAML frontmatter, and only name and description are required.

How do I make a Claude Code subagent read-only?

List its tools and leave out anything that writes: tools: Read, Grep, Glob gives it no Edit, Write or Bash, so it cannot change a file however it is prompted. If it needs a shell, add a PreToolUse hook that blocks commands you do not allow.

Which model should a subagent use?

Match the model to the job. Summarising test output or recording a result suits a small, fast model such as haiku; reviewing code or checking documentation against it benefits from sonnet. Use inherit to run on whatever the main session uses.

Is it safe to copy subagents from GitHub?

Read them first. Check that each has a tools list, read every command in a hooks block because it runs with your permissions, look for mcpServers entries you did not expect, and narrow any description that tells Claude to use it for everything.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.