Guide · Coding agents
Claude Code subagents and custom slash commands
A Claude Code subagent is a separate Claude worker with its own context window, system prompt, tools and model. Claude hands it a task, it works in isolation, and only its final answer comes back to your conversation. You define one as a Markdown file with YAML frontmatter in .claude/agents/ for a project or ~/.claude/agents/ for all your projects.
By Tahir NazirUpdated 12 min read
On this page
- What is a Claude Code subagent?
- Built-in subagents: Explore, Plan and general-purpose
- How to create a subagent: the agents folder and file format
- Tools, permissions and model for each subagent
- Three example subagents: code reviewer, test runner and researcher
- Do subagents save tokens?
- Custom slash commands are now skills
- Common subagent pitfalls
- Questions people ask
What is a Claude Code subagent?
A subagent is a helper that the main Claude conversation can delegate to. It runs in its own context window with its own system prompt, tool access and permissions. When Claude sees a task that matches a subagent’s description, or you ask for one by name, it writes a task message, the subagent does the work, and only its final reply returns:
Main conversation
- Claude Code’s system prompt and tools
- CLAUDE.md and auto memory
- Your whole conversation so far
- Every file and tool result already read
Subagent · own context window
Starts with
- Its own system prompt: the file’s Markdown body
- The task message Claude wrote
- CLAUDE.md and a git status snapshot (not Explore or Plan)
- Preloaded skills, its own tools and model
Never sees
- Your conversation history
- Files the main conversation read
- Your auto memory and output style
Stays here
Every file it reads, search it runs and log it prints
Docs example: 6,100 tokens read here, 420 returned
A fork is different. Started with /subtask, it inherits the whole conversation, system prompt, tools and model, reuses your prompt cache, and still sends back only its result.
That isolation is the whole point. The docs’ own walkthrough has a subagent read 6,100 tokens of files while the main conversation receives a 420-token answer. The price is that the subagent knows only what the task message tells it, so rules that live in your conversation, not in CLAUDE.md, need restating when you delegate.
Built-in subagents: Explore, Plan and general-purpose
Claude Code ships with subagents it uses on its own. All inherit your permission rules:
| Agent | Tools | Model | Used for |
|---|---|---|---|
| Explore | Read-only (no Write or Edit) | Your session’s model | Searching and understanding a codebase, at a thoroughness Claude picks |
| Plan | Read-only | Your session’s model | Research during plan mode |
| general-purpose | Every tool subagents can have | Your session’s model, or CLAUDE_CODE_SUBAGENT_MODEL | Multi-step tasks that explore and change code |
| claude | Every tool subagents can have | Follows the subagent model order | Catch-all when nothing more specific fits |
| statusline-setup | Not documented | Sonnet | /statusline |
| claude-code-guide | Not documented | Haiku | Questions about Claude Code itself |
From the subagents documentation, 2026-10-11. Explore and Plan skip CLAUDE.md and git status to stay small and fast. When your session runs Fable, Explore may run on Opus instead, depending on how you connect.
To run exploration on a cheaper model, create your own subagent named Explore with model: haiku: a user or project subagent with that name overrides the built-in. "permissions": { "deny": ["Agent(Explore)"] } blocks one type, and denying Agent stops all delegation.
How to create a subagent: the agents folder and file format
Save a Markdown file in an agents folder. When two definitions share a name, the higher one in this list wins:
- Managed settings deployed by your organisation.
- `--agents '{…}'` JSON passed when you launch Claude Code, for that session only.
- `.claude/agents/` in the project, shared through git. Every such folder from the working directory up to the repository root is scanned.
- `~/.claude/agents/` for all your projects.
- A plugin’s `agents/` folder.
Subfolders such as agents/review/ are fine: identity comes only from the name field, not the filename. Edits are picked up within seconds, but if the agents folder didn’t exist when the session started, restart. Since v2.1.198 /agents only prints a reminder; ask Claude to write the file, or write it yourself. These are the fields:
| Field | What it does |
|---|---|
name (required) | Unique ID, up to 256 characters, no :. Used in @-mentions and hook matchers |
description (required) | When Claude should delegate. Add “use proactively” to encourage it |
tools / disallowedTools | Allowlist or denylist of tools; omit both to inherit everything |
model | haiku, sonnet, opus, fable, a full model ID, or inherit |
permissionMode | default, acceptEdits, auto, dontAsk, bypassPermissions or plan |
maxTurns | Stop after this many agentic turns; output is marked partial |
skills | Skills whose full text is preloaded at startup |
mcpServers | MCP servers for this agent only, by name or inline |
hooks | Hooks that run only while this agent is active |
memory | user, project or local: a folder it keeps notes in across sessions |
isolation | worktree gives it a temporary git worktree |
background, effort, omitClaudeMd, color, initialPrompt | Run in background, effort level, skip CLAUDE.md, display colour, first prompt when used with --agent |
Field names must match exactly (maxTurns, not max_turns): Claude Code ignores unknown fields without a word. A file with no name, a name but no description, or YAML that doesn’t parse is skipped silently. Run claude plugin validate .claude/agents --strict before a session to catch the last two. On a broken file we got:
Validating agent: .claude/agents/broken.md
× Found 1 error:
> frontmatter: YAML frontmatter failed to parse: YAML Parse error: Unexpected EOF.
× Validation failedThe message goes on to say that at runtime such an agent doesn’t load at all. The validator didn’t flag a misspelled field such as max_turns, and a missing description was only a warning without --strict, so still check names against the table.
Tools, permissions and model for each subagent
- `tools: Read, Grep, Glob, Bash` is an allowlist: no Edit, no Write, no MCP tools.
disallowedTools: Write, Editkeeps everything else.mcp__githubin either field covers a whole MCP server. - A specifier removes the whole tool.
disallowedTools: Bash(git push *)takes Bash away entirely. To block onlygit push, add apermissions.denyrule, which also covers subagents. - Read-only means no Bash. A reviewer with Bash can still change files through the shell; leave Bash out when it must not.
- Some tools never reach subagents, such as
AskUserQuestionandEnterPlanMode. Background subagents, the default in interactive sessions, also get a smaller built-in set, and their permission prompts appear in your main session. - `permissionMode` is overruled when your main session is in
bypassPermissions,acceptEditsor auto mode: the subagent runs in that mode instead. - `mcpServers` defined inline connect only for that subagent, so their tool descriptions never take up room in your main context.
The model comes from, in order: a model Claude passes for that one call, the model field, the CLAUDE_CODE_SUBAGENT_MODEL environment variable, then your session’s model. Set CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1 as well to override every definition. On the Anthropic API the aliases currently resolve to:
| Alias | Model | Input | Output |
|---|---|---|---|
haiku | Claude Haiku 5.5 | $0.10 | $0.50 |
sonnet | Claude Sonnet 5.5 | $2 | $10 |
opus | Claude Opus 5.5 | $4 | $20 |
Claude Haiku 5.5 costs $0.50 in and $2.50 out per million tokens once a prompt passes 100,000 tokens. Prices from our daily model data; Amazon Bedrock, Google Cloud and Microsoft Foundry map some aliases to older models. On a Pro or Max plan the same choice spends your usage limits rather than dollars.
Three example subagents: code reviewer, test runner and researcher
Save each in .claude/agents/. The reviewer reads and reports; the test runner uses the cheapest model because running tests and trimming logs needs little reasoning; the researcher has web tools that the others don’t.
---
name: code-reviewer
description: Reviews uncommitted changes for bugs, security problems and unclear code. Use after editing code and before committing.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a senior code reviewer. You report problems; you never edit files.
1. Run `git diff HEAD` to see what changed, then read enough of each changed file to understand the hunk.
2. Look for bugs and missed edge cases, unvalidated input, secrets in code, missing tests for new behaviour, and names that hide intent.
3. Report by priority: Must fix, Should fix, Consider. For each finding give file:line, the problem in one sentence, and a concrete fix.
If the diff is empty, say so and stop. Keep the report under 300 words.---
name: test-runner
description: Runs the test suite and reports only the failures. Use when tests need running or a change may have broken them.
tools: Bash, Read, Grep, Glob
model: haiku
---
Run the project's tests. Find the command in package.json, Makefile or pyproject.toml. Do not change any files.
Report:
- The command you ran and the totals (passed, failed, skipped).
- For each failure: the test name, file:line, and the assertion or error, trimmed to the lines that matter.
Never paste full logs. If everything passes, reply with one line.---
name: docs-researcher
description: Answers questions about libraries, APIs and error messages from official documentation. Use for version-specific or recently changed APIs.
tools: WebSearch, WebFetch, Read, Grep, Glob
model: sonnet
---
Find the answer in primary sources: the library's own docs, changelog or source. Check the version the project uses first (package.json, lockfile, requirements.txt).
Return:
- The answer in two to five sentences, for the project's version.
- A minimal code example if one helps.
- The URLs you relied on.
Say plainly when the docs don't settle the question. Don't guess.Claude delegates on its own when a request matches a description. To choose yourself:
- Name it: “Use the test-runner subagent to check my changes.” Claude usually delegates.
- @-mention it: pick
code-reviewer (agent)from the@menu, or type@agent-code-reviewer. That subagent is guaranteed to run. - Run the whole session as it:
claude --agent code-reviewer. Its prompt replaces Claude Code’s system prompt, and its tool limits apply to the main thread.
Every subagent must be described in context so Claude can choose, and Claude Code warns at startup when the combined descriptions of your own subagents pass 15,000 tokens. Keep descriptions to a sentence or two; the token counter shows what yours cost.
Do subagents save tokens?
They save context, not necessarily tokens. Your main conversation stays small because a subagent’s file reads, search results and logs stay in its own window. But each subagent sends its own requests, which count toward the same usage limits or API bill.
| Saves | Costs extra |
|---|---|
| Verbose work you only need a summary of: test runs, log digging, broad searches | Small, targeted edits: the subagent has to rediscover context you already have |
| Long sessions, since every later turn re-sends a smaller history | Many parallel subagents that each return long reports into your context |
Routine jobs moved to a cheaper model with model: haiku | Back-and-forth work: each delegation starts from zero |
Caching matters too. A subagent’s prompt differs from yours, so its first request can’t read your prompt cache, and subagents get a five-minute cache lifetime even on a subscription unless you choose 1h with the subagentPromptCacheTtl setting or experimental: { cacheTtl: 1h } in the file (Claude Code ignores the file’s 1h while your subscription is drawing on usage credits). A fork (/subtask <task>) is different: it reuses your conversation, so its first request reads your cache. For the wider picture, see how to reduce Claude Code token usage.
Custom slash commands are now skills
In current Claude Code, “custom commands have been merged into skills”, in the docs’ words. Both of these create /fix-issue, and old command files keep working:
- Command file (older format):
.claude/commands/fix-issue.md. A subfolder becomes a prefix:commands/frontend/component.mdis/frontend:component. - Skill (current format):
.claude/skills/fix-issue/SKILL.md, or~/.claude/skills/…for every project. The folder can also hold scripts and reference files.
---
description: Fix a GitHub issue by number, with a test that proves the fix
argument-hint: "[issue-number]"
disable-model-invocation: true
allowed-tools: Bash(gh issue view *)
---
Fix GitHub issue #$ARGUMENTS.
1. Read it with `gh issue view $ARGUMENTS`.
2. Write a failing test that reproduces the problem, then change the code until it passes.
3. Ask the test-runner subagent to run the full suite, and summarise the change in three lines.Typing /fix-issue 123 replaces $ARGUMENTS with 123; $0, $1 pick single arguments. disable-model-invocation: true means only you can trigger it, and keeps its description out of context. allowed-tools pre-approves listed tools for that turn only. If a skill and a command file share a name, the skill wins; a personal skill beats a project one.
Skills and subagents combine. With context: fork and agent, a skill runs as a task for a subagent, so /review-changes here runs the code reviewer in its own context:
---
description: Review uncommitted changes in a separate context before committing
context: fork
agent: code-reviewer
disable-model-invocation: true
---
Review the uncommitted changes in this repository. Focus on $ARGUMENTS if given.| Tool | Runs in | Loads | Best for |
|---|---|---|---|
| CLAUDE.md | Main conversation | Every session | Facts and conventions |
| Skill or slash command | Main conversation, or a subagent with context: fork | Description up front, body when used | Repeatable procedures you trigger with /name |
| Subagent | Its own context window | When Claude delegates or you @-mention it | Noisy or isolated work, tool limits, another model |
| Hook | Outside the model, as a script | On lifecycle events | What must happen every time |
Common subagent pitfalls
- Vague descriptions. “Helps with code” never gets picked. Say what it does and when: “Use after editing code and before committing.”
- Assuming it knows your conversation. It doesn’t. Put lasting rules in CLAUDE.md, which most subagents load, or in its prompt.
- A skill that shares a built-in’s name. Your
code-reviewskill replaces/code-review, but the alias/reviewstill runs the bundled version. Unique names avoid the confusion. - Plugin agents with hooks or MCP servers. Plugin subagents ignore
hooks,mcpServersandpermissionMode; copy the file into.claude/agents/if you need them. - Project agent hooks that never fire. Frontmatter hooks in
.claude/agents/run only after you accept the workspace trust dialog, and never in an untrusted-prun. - Too much fan-out. Subagents nest up to three levels below the main conversation, and Claude Code refuses a new one while 20 are running. Each result lands in your context; ask for short reports.
- Resuming Explore or Plan. They return no agent ID, so they can’t be resumed. Use
general-purposeor your own agent for work you’ll continue.
If a session still runs out of room, see Prompt is too long. Subagents can also use the MCP servers you set up with the MCP config generator; MCP servers in Claude Code explains scopes and connection.
FAQ
Questions people ask
Where do Claude Code subagent files go?
In .claude/agents/ inside a project, shared with anyone who clones it, or in ~/.claude/agents/ for every project on your machine. Each subagent is one Markdown file with name and description in its YAML frontmatter; subfolders are allowed. When the same name exists in both, the project version wins. Restart Claude Code if the folder didn’t exist when the session started.
What is the difference between subagents and skills in Claude Code?
A skill is a set of instructions that loads into your current conversation when you type /name or Claude decides it’s relevant. A subagent is a separate worker with its own context window, system prompt, tools and model, which returns only a summary. A skill with context: fork bridges the two: its content becomes the task for a subagent.
Are custom slash commands deprecated in Claude Code?
They’ve been merged into skills rather than removed. A file at .claude/commands/deploy.md still creates /deploy, and supports the same frontmatter as a skill except name and paths. The docs recommend skills for new work, because a skill folder can bundle scripts and reference files and supports extra options such as running in a subagent.
Can a subagent use a different model from the main conversation?
Yes. Set model in the subagent’s frontmatter to haiku, sonnet, opus, fable, a full model ID (listed in our Claude model IDs reference), or inherit. Without it, Claude Code uses CLAUDE_CODE_SUBAGENT_MODEL if set, otherwise your session’s model. A cheap model suits mechanical jobs such as running tests; keep stronger models for review and debugging.
Can Claude Code subagents spawn other subagents?
Yes, if the subagent has the Agent tool. Nesting goes up to three layers below the main conversation by default; CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH changes the limit and 1 turns nesting off. Only the top-level subagent’s summary comes back to you. Leave Agent out of a subagent’s tools list to stop it delegating.
Why isn’t Claude using my subagent?
Check that the file loaded: it needs a valid name and description, and a broken file is skipped silently, so run claude plugin validate .claude/agents --strict. Then make the description specific about when to use it, or add “use proactively”. To force it, @-mention the agent or name it in your request.
Try it
Tools from this guide
Keep reading