Everything you have written so far runs inside your session. A skill’s body lands in your context, which is the block of text the model can see while it answers you. An output style rewrites the standing instructions Claude Code puts above that text. A rule sits above the whole conversation. A subagent is the first artifact that runs somewhere else.
When Claude hands work to a subagent, a second copy of Claude starts up with an empty transcript, meaning it holds no record of anything said in your conversation. It gets a system prompt, which is the name for those standing instructions, built from the file you wrote. It also gets one message describing the task and a small set of session facts. Then it works, and when it is done, one summary comes back into your conversation. The intermediate reads, the failed greps, the eighty lines of stack trace it waded through: none of that arrives. That is the whole point, and it is also the thing that surprises people.
What crosses the boundary
A fresh subagent, meaning one that is not a /subtask fork, receives five things at startup:
- Its own system prompt, which is the body of your agent file.
- The delegation task message Claude wrote when it decided to hand off.
- The
CLAUDE.mdhierarchy, meaning everyCLAUDE.mdfound from your project upward, with the built-in Explore and Plan agents excepted. - A git status snapshot, again except Explore and Plan.
- Any skills named in the
skillsfield of the frontmatter, the settings block fenced by two lines of three dashes at the top of the file. Those skills arrive with their full bodies rather than their descriptions alone.
It does not receive the conversation history. It does not receive your output style. It does not receive the main session’s auto memory. So an instruction you gave in message four does not reach it, a tone you set with an output style does not apply to it, and a file it needs to know about has to be named in the task message or reachable from CLAUDE.md.
This is why a subagent description is doing more work than it looks like. It is both the trigger for automatic delegation and, indirectly, the thing that shapes the task message Claude writes.
The smallest one that works
name and description are required. Everything else is optional, and the useful minimum is two fields plus a body.
.claude/agents/reviewer.md ships to your plugin The version you ship. Read-only tools, an explicit model, and a colour so you can spot it in the transcript.
---
name: reviewer
description: Reviews a diff or a set of files for correctness bugs,
missing error handling, and anything that will fail under load.
Use after a feature is written and before it is committed.
tools: Read, Grep, Glob, Bash
disallowedTools: Bash(git push:*)
model: sonnet
color: yellow
skills:
- changed
---
You review code. You do not write it.
Work from the diff first. Run the changed skill to see what moved,
then read the files it names in full, because a diff hides the
context that makes a change wrong.
Report findings in severity order. For each one give the file, the
line, what breaks, and the smallest change that fixes it. If you
find nothing, say so in one line rather than padding the report.
Never edit a file. Never commit. Your output is the review. Read more
The tools list is an allowlist. Omit it and the subagent inherits everything the parent session can reach, Bash and Write included. For a reviewer that is a hazard rather than a convenience: it can decide to fix what it found, and you get edits you did not ask for back in a summary that says "reviewed".
.claude/agents/minimal.md The true minimum: two frontmatter fields and a body. This loads and runs.
---
name: changelog-writer
description: Turns a range of commits into user-facing release notes.
---
Read the commit range you are given. Group the commits by what a
user would notice, not by which file changed. Drop anything that is
purely internal. .claude/agents/broken.md Skipped at load. The name is the reason, and nothing tells you in the session.
---
name: review:security
description: Audits changed code for injection and auth mistakes.
---
You audit code for security problems. Read more
A colon in name is reserved for plugin scoping, so the file is skipped and an error goes to the debug log. Files with no name at all are treated as documentation and skipped without any log line, which is the quieter version of the same failure.
The optional fields worth learning
| Field | What it does |
|---|---|
tools | An allowlist, so only what is on the list is permitted. Omitted means inherit everything the parent can use. |
disallowedTools | A denylist, so everything is permitted except what is on the list. Applied on top of whatever tools resolved to. |
model | sonnet, opus, haiku, fable, a full model ID, or inherit. Defaults to inherit. |
permissionMode | default, acceptEdits, auto, dontAsk, bypassPermissions, plan, manual. |
skills | Preloads named skills at startup, full body and all. |
isolation | Set to worktree to give the agent its own checkout of the repository, separate from yours. |
color | One of red, blue, green, yellow, purple, orange, pink, cyan. Transcript label only. |
Four of those have sharp behaviour behind them.
tools fails hard when it resolves to nothing. If no entry in your list matches a real tool, the subagent does not launch tool-less; it fails to launch at all. A typo in a tool name is therefore loud rather than silent, which is the opposite of how the rest of this surface behaves.
model: inherit is the default, which means a subagent you write without thinking about it runs on whatever the main conversation is running on. Pinning a cheap model on a mechanical agent is one of the few real cost levers in this course. Four things can set the model, and the first one present wins: the CLAUDE_CODE_SUBAGENT_MODEL environment variable, then a model parameter passed when the agent is invoked, then your frontmatter, then the main conversation model.
permissionMode loses to the parent when the parent is more permissive. A session running with bypassPermissions or acceptEdits does not get tightened up by a subagent asking for default. Permission is module 11, and this is the first place you meet a rule that runs one way and not the other.
isolation: worktree gives the agent a separate checkout of the repository in its own folder, called a worktree, so its edits cannot land on top of yours. It branches from your default branch, not from the parent session’s HEAD. If you are three commits deep on a feature branch and you hand work to a worktree-isolated agent, it starts from main and will not see those commits. The worktree is cleaned up automatically if the agent leaves it unchanged.
Precedence inverts here
When the same name is defined in two places, one of them wins, and the fixed order that decides which is called precedence. Read the two orders below together rather than one at a time.
Skills resolve enterprise > personal > project. Personal beats project.
Subagents resolve managed > --agents > project > user > plugin. Project beats user.
Same repository, same two files, opposite winner. A personal changed skill overrides the project’s copy, and a project reviewer agent overrides your personal one.
The way to hold it: a skill is a capability you carry between projects, so the version you chose for yourself wins. A subagent is a worker doing this repository’s job, so the version the repository specifies wins. That reasoning is a mnemonic rather than a documented rationale, but it produces the right answer both times, and generalising from module 5 does not.
| Location | Scope | Priority |
|---|---|---|
| Managed settings | Organization-wide | 1 |
--agents flag, given on the command line (JSON) | Current session only | 2 |
.claude/agents/ | Current project | 3 |
~/.claude/agents/ | All your projects | 4 |
Plugin agents/ | Wherever the plugin is enabled | 5 |
Project agents are discovered recursively, meaning Claude Code looks inside subdirectories as well as the top level. Across nested project directories, the definition closest to your working directory wins.
Plugin subagents lose three fields
Three frontmatter fields are ignored when a subagent arrives from a plugin: hooks, mcpServers, and permissionMode. The reason is security. Installing a plugin should not silently hand a third party the ability to run commands at the fixed moments in a session that Claude Code calls lifecycle events, point you at a tool server of their choosing, or relax your permission mode.
You will feel this in module 12 when the agent you write here ships inside your plugin. The file is the same file. Those three fields stop applying. If you need them, the fix is to copy the agent into .claude/agents/, where it is yours and the fields take effect.
Loading and restarts
Both ~/.claude/agents/ and .claude/agents/ are watched, and edits apply within seconds. You need a restart in three cases only: creating the first agent file in a brand new agents directory, adding or editing agents inside an --add-dir folder, and sessions started with --disable-slash-commands.
Invoke deliberately with @agent-reviewer. Automatic delegation happens off the description, so if delegation never fires, the description is where to look before anything else.
Write .claude/agents/reviewer.md. Start with name and description only, and a body that says what a review is and is not. Run @agent-reviewer against a real diff and read what comes back.
Then constrain it. Add tools: Read, Grep, Glob, Bash, set model explicitly rather than leaving it on inherit, and preload the changed skill from module 5 with skills: [changed]. Run it again on the same diff. The second run should be unable to edit anything, and the skill body should be in its context from turn one without you invoking it.
Last, prove the boundary. Tell the main session a fact it could not guess, something like a variable naming convention you use in this repo, then invoke the agent and ask it to apply that convention. It will not know. Put the fact in CLAUDE.md and try again. That difference is the module. This file ships to agents/ in your plugin.
You write a security reviewer and name it review:security, because that reads well and you have seen colons in agent identifiers before. You save, you type @agent-review:security, and nothing happens. No error in the session, no warning, no listing entry. The file exists, and the frontmatter at the top of it is valid YAML, the indented name-and-value format those blocks are written in.
A colon in name is reserved for plugin scoping. Claude Code skips the file and writes an error to the debug log, a separate file of diagnostic output that you are not watching. Use review-security, or nest the file in a plugin subfolder in module 12 and let the scoping happen to you.
The same silence has a second cause worth checking at the same time. Two files in one directory declaring the same name load exactly one of them, chosen by filesystem read order, which is not alphabetical and not stable across machines. Your teammate can be running a different agent than you from an identical checkout. Run /doctor to find duplicates, and claude plugin validate .claude/agents to catch the malformed files before you ship them.
The concept is everywhere and the file almost never moves. Copilot CLI is the exception: it reads .claude/agents/ .agent.md files directly, alongside .github/agents/ and ~/.copilot/agents/, with a default nesting depth of 4 rather than 6.
Gemini CLI is a copy-and-adjust job rather than a rewrite. It wants .gemini/agents/ or ~/.gemini/agents/, markdown with YAML frontmatter carrying name, description, and tools, the body as the system prompt, invoked with @agent_name. The shape is the same; the path and a couple of field names are not.
Codex CLI is a rewrite. Its agents are TOML, a different plain-text settings format, in ~/.codex/agents/ or .codex/agents/, requiring name, description, and developer_instructions, plus any config.toml key. Cursor has .cursor/agents/ as of Cursor 2.4. OpenCode takes .opencode/agents/*.md or inline definitions in opencode.json with a mode field and a per-agent permission map. Cline has subagents that are on by default and cannot be user-defined at all, so there is no file to port. Amp ships built-ins and allows custom ones only through plugins. Aider, Windsurf, and Zed document no user-authored subagent format.
What travels regardless of harness is the judgment: knowing when a task deserves its own context window, the fixed amount of text a model can hold at once, and knowing that the cost of separating it out is everything the parent knew.
Check yourself
- Your main session has been debugging for twenty minutes and you delegate to a subagent. Which of what you learned in those twenty minutes reaches it?
- A
revieweragent exists in both.claude/agents/and~/.claude/agents/. Which runs, and would your answer be the same for a skill? - You set
permissionMode: defaulton an agent and launch it from a session already running underbypassPermissions. Which one wins?