Claude Code subagents and skills

Two related but distinct primitives let you extend Claude Code without modifying the core engine: subagents are specialized AI workers that handle focused subtasks in their own context window with their own system prompt and tool set; skills are reusable markdown procedures (formerly slash commands) that Claude can invoke when relevant or that you can call with /skill-name. They compose: a skill can be configured to run in a forked subagent (context: fork), and a subagent can preload skills as background knowledge (skills: [...]).

See also

1. Subagents

Per code.claude.com/docs/en/subagents. A subagent is a specialized AI worker with:

  • Own context window (separate from main conversation)
  • Own system prompt
  • Specific tool access (subset of available tools)
  • Independent permission mode
  • Optionally: persistent memory, own model, own hooks

When Claude encounters a task matching a subagent’s description, it delegates via the Agent tool (formerly Task tool); subagent works independently, returns a summary.

Why use them:

  • Preserve context — exploration / log analysis happens in subagent context, main thread sees only summary
  • Enforce constraints — read-only research subagents can’t write
  • Reuse configs — user-level subagents work across projects
  • Specialize — focused system prompts for specific domains
  • Control cost — route to Haiku for cheap tasks, Opus for hard tasks

1.1 Built-in subagents

NameModelToolsPurpose
ExploreHaiku (fast)Read-only (denied Write/Edit)File discovery, code search, codebase exploration. Skips CLAUDE.md and parent git status for speed.
PlanInheritsRead-onlyUsed in plan mode to gather context. Same skip.
General-purposeInheritsAllMulti-step tasks needing both exploration + action
statusline-setupSonnet(specific)Auto-invoked when you run /statusline
claude-code-guideHaiku(specific)Auto-invoked when you ask about Claude Code features

1.2 Subagent scopes (highest priority first)

LocationScopePriority
Managed settingsOrg-wide1 (highest)
--agents CLI flagSession2
.claude/agents/<name>.mdProject3
~/.claude/agents/<name>.mdUser (all projects)4
<plugin>/agents/<name>.mdWhere plugin enabled5

Plugins use namespacing: <plugin-name>:<agent-name> (or <plugin>:<subfolder>:<agent> for nested). No conflicts with other scopes.

.claude/agents/ is walked recursively. Project subagents are discovered by walking up from cwd. --add-dir does NOT scan for subagents (file access only).

Plugin subagents ignore hooks, mcpServers, and permissionMode frontmatter for security.

1.3 Subagent file format

.claude/agents/code-reviewer.md:

---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
color: blue
---
 
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.

Body becomes the subagent’s system prompt. Subagent receives only this prompt + basic environment details (cwd, etc.) — not the main Claude Code system prompt.

1.4 Supported frontmatter fields

FieldRequiredDescription
nameYesUnique ID, lowercase + hyphens. Hooks see this as agent_type. Filename doesn’t have to match.
descriptionYesWhen Claude should delegate. The router uses this.
toolsNoAllowlist (e.g. Read, Glob, Grep). Inherits all if omitted.
disallowedToolsNoDenylist. Applied first, then tools resolved.
modelNosonnet, opus, haiku, full ID, or inherit (default).
permissionModeNodefault, acceptEdits, auto, dontAsk, bypassPermissions, plan. Plugin-ignored.
maxTurnsNoCap agentic turns before stopping.
skillsNoSkills preloaded into subagent context at startup (full content, not just description).
mcpServersNoMCP servers — by name (reuse session) or inline. Plugin-ignored.
hooksNoLifecycle hooks scoped to this subagent. Plugin-ignored.
memoryNouser, project, or local — enables persistent memory dir.
backgroundNotrue to always run as background task.
effortNolow/medium/high/xhigh/max for this subagent.
isolationNoworktree — run in temp git worktree branched from default branch. Auto-cleaned if no changes.
colorNored, blue, green, yellow, purple, orange, pink, cyan. UI hint.
initialPromptNoAuto-submitted as first user turn when run via --agent or agent setting.

1.5 Model resolution order

  1. CLAUDE_CODE_SUBAGENT_MODEL env var
  2. Per-invocation model parameter (when Claude invokes the subagent)
  3. Subagent definition’s model frontmatter
  4. Main conversation’s model

1.6 Restricting which subagents can spawn other subagents

When an agent runs as main thread via claude --agent, it can spawn subagents using the Agent tool. Restrict with Agent(name1, name2) syntax in tools:

tools: Agent(worker, researcher), Read, Bash

This is an allowlist. Omitting Agent entirely disables subagent spawning. Bare Agent (no parens) allows all.

Subagents themselves cannot spawn subagents — no nesting.

(Task was renamed to Agent in v2.1.63; Task(...) still works as an alias.)

1.7 Inline MCP servers per subagent

mcpServers:
  - playwright:
      type: stdio
      command: npx
      args: ["-y", "@playwright/mcp@latest"]
  - github   # reference an already-configured server

Defining inline here keeps the MCP tools out of the parent context entirely — useful for keeping context lean.

1.8 What loads at startup (per docs)

Every subagent receives:

  • Its own frontmatter prompt (markdown body)
  • Basic environment details (cwd)
  • Plus, unless it’s Explore or Plan: CLAUDE.md + parent git status

The Explore + Plan agents deliberately skip CLAUDE.md and git status to keep their context small.

1.9 Forked subagents (context: fork on skills)

A skill can fork into a subagent. See §2.5 below.

1.10 Persistent memory (memory: field)

memory: user   # `user`, `project`, or `local`

Enables a persistent memory directory at ~/.claude/agent-memory/<name>/ (user scope) or .claude/agent-memory/<name>/ (project / local). Subagent accumulates insights across conversations.

1.11 Dispatching subagents

Three ways:

  1. Implicit — Claude reads descriptions, decides when to delegate
  2. Explicit by name — “Use the code-reviewer agent to …”
  3. Via --agent <name> at session start — agent runs as the main thread
  4. Via SDK Task/Agent tool — programmatic

2. Skills

Per code.claude.com/docs/en/skills. A skill is a markdown file with YAML frontmatter that Claude can invoke automatically (when description matches) or you can invoke explicitly via /skill-name.

Skills follow the Agent Skills open standard. Claude Code extends it with invocation control, subagent execution, and dynamic shell injection.

Custom commands have been merged into skills. A file at .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy with identical semantics. Skills add: directory for supporting files, frontmatter to control invocation, model-invocation.

2.1 Bundled skills (ship with Claude Code)

Listed in / menu:

SkillPurpose
/runLaunch and drive your app to verify a change works
/verifyBuild + run app to confirm change without tests
/run-skill-generatorGenerate per-project /run and /verify skills
/code-reviewCode review skill
/security-reviewSecurity review
/debugDebugging skill
/batchBatch operations
/loopRepeat a prompt or command on an interval
/claude-apiBuild / migrate Claude API code

Plus the built-in commands /help, /clear, /compact, etc. listed in claude-code-cli.

2.2 Skill scopes

LocationScopePath
ManagedOrg-widePer managed settings
PersonalAll your projects~/.claude/skills/<name>/SKILL.md
ProjectThis project.claude/skills/<name>/SKILL.md
PluginWhere plugin enabled<plugin>/skills/<name>/SKILL.md (namespaced <plugin>:<name>)

Precedence: enterprise > personal > project. Skills override identically-named commands.

Live change detection: editing ~/.claude/skills/ or project .claude/skills/ is picked up within the session. Creating a top-level skills dir that didn’t exist at session start requires restart.

Discovery is recursive — .claude/skills/ walks up from cwd, plus nested ones when working in subdirectories of --add-dir’d paths (handy for monorepos).

2.3 Skill file structure

my-skill/
├── SKILL.md           # Main instructions (required)
├── reference.md       # Detailed reference loaded on demand
├── examples.md
└── scripts/
    └── helper.py      # Executable script

SKILL.md:

---
name: my-skill
description: What this skill does
disable-model-invocation: true
allowed-tools: Read Grep
---
 
Your skill instructions here...

2.4 Frontmatter

FieldDescription
nameDisplay name. Defaults to directory name. Lowercase + hyphens, ≤64 chars.
descriptionWhen to use the skill. Claude uses this to decide automatic invocation. Combined description + when_to_use truncated at 1,536 chars in skill listing.
when_to_useExtra trigger phrases. Appended to description.
argument-hintAutocomplete hint, e.g. [issue-number].
argumentsNamed positional args for $name substitution (space-sep string or YAML list).
disable-model-invocationtrue → only user can invoke via /name. Also prevents preloading into subagents.
user-invocablefalse → hide from / menu (Claude can still invoke).
allowed-toolsTools auto-approved while skill is active.
modelOverride model for this skill’s turn. Or inherit.
effortOverride effort level.
contextfork → run in forked subagent.
agentWhich subagent type when context: fork (default general-purpose).
hooksHooks scoped to this skill’s lifecycle.
pathsGlob patterns — auto-load only when working with matching files.
shellbash (default) or powershell for !backtick` injection.

2.5 String substitution

In the skill body:

VariableResolves to
$ARGUMENTSFull argument string
$ARGUMENTS[N] / $NSpecific argument by 0-based index
$nameNamed arg from arguments:
${CLAUDE_SESSION_ID}Current session UUID
${CLAUDE_EFFORT}low/medium/high/xhigh/max
${CLAUDE_SKILL_DIR}Directory containing this SKILL.md

Indexed arguments use shell-style quoting: /my-skill "hello world" second$0 = "hello world", $1 = "second". $ARGUMENTS always = full unquoted typed string.

2.6 Dynamic context injection (!backtick`)

---
name: pr-summary
description: Summarize a PR
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
 
## PR diff
!`gh pr diff`
 
## Comments
!`gh pr view --comments`
 
## Your task
Summarize.

The !gh pr diff lines execute before the skill content is sent to Claude; output replaces the placeholder. Claude sees the rendered prompt with live data inline.

Multi-line form (fenced block opened with ```!):

## Environment
```!
node --version
npm --version
git status --short
```

Substitution runs once — command output is plain text, not re-scanned for further ! placeholders.

Disable globally with disableSkillShellExecution: true in settings (replaces commands with [shell command execution disabled by policy]). Bundled and managed skills exempt.

2.7 Forking into a subagent

context: fork makes the skill run in an isolated subagent context. The skill body becomes the prompt; agent field picks which subagent type (default general-purpose).

---
name: deep-research
description: Research a topic thoroughly
context: fork
agent: Explore
---
 
Research $ARGUMENTS thoroughly:
1. Find relevant files
2. Read and analyze
3. Summarize with file references

The forked subagent inherits the agent type’s tools and model. Built-in Explore + Plan skip CLAUDE.md to keep small. Returns a summary to the main thread.

2.8 Pre-approving tools

allowed-tools grants permissions while skill is active:

---
name: commit
description: Stage and commit current changes
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---

Claude can run those without prompting. Doesn’t restrict — your permissions.deny rules still apply.

2.9 Controlling invocation

FrontmatterYou invoke?Claude invokes?When loaded into context
(default)YesYesDescription always; full skill on invoke
disable-model-invocation: trueYesNoNot loaded; full skill on user invoke
user-invocable: falseNoYesDescription always; full skill on Claude invoke

2.10 Skill content lifecycle

When invoked, the rendered SKILL.md enters the conversation as a single message and stays for the session. Claude does NOT re-read on later turns — write standing instructions, not one-time steps.

Auto-compaction: re-attaches most recent invocation of each skill after summary (first 5,000 tokens). Re-attached skills share 25,000 token budget total — older skills can be dropped.

Skill description budget: defaults to 1 % of model’s context window. When overflowing, descriptions for least-used skills are dropped first. Tune with skillListingBudgetFraction setting (e.g. 0.02 = 2%) or SLASH_COMMAND_TOOL_CHAR_BUDGET env var. Per-skill max description: 1,536 chars (configurable via maxSkillDescriptionChars).

2.11 skillOverrides setting

Control visibility from settings without editing the SKILL.md:

{
  "skillOverrides": {
    "legacy-context": "name-only",      // hide description
    "deploy": "off",                     // hidden everywhere
    "experimental": "user-invocable-only"  // only via /
  }
}

Values: on, name-only, user-invocable-only, off. Set via /skills menu (Space cycles state, Enter saves to .claude/settings.local.json). Plugin skills not affected.

2.12 Restricting Claude’s skill access

Three layers:

  • Disable all skills: Skill in permissions.deny
  • Allowlist / denylist specific: Skill(commit), Skill(review-pr *), Skill(deploy *) in permissions
  • Per-skill: disable-model-invocation: true in frontmatter

A few built-in commands also flow through Skill tool: /init, /review, /security-review. Others like /compact do not.

3. The Task / Agent tool

In v2.1.63 the Task tool was renamed to Agent. Task(...) still works as alias. The tool’s responsibility: dispatch a subagent. Input shape:

{
  "subagent_type": "general-purpose",
  "description": "Brief 1-line task description",
  "prompt": "Full task prompt for the subagent"
}

Claude invokes this when delegating. Each subagent dispatch is a fresh context — subagent gets only its own system prompt + the prompt field, not the main conversation.

4. Composing subagents + skills

The two work in two directions:

ApproachSystem promptTaskAlso loads
Skill with context: forkFrom agent typeSKILL.md contentCLAUDE.md (unless Explore/Plan agent)
Subagent with skills: fieldSubagent’s markdown bodyClaude’s delegation messagePreloaded skill content + CLAUDE.md

Pattern: skill = task, subagent = worker config. A pr-review skill says “review this PR thoroughly using gh CLI”; a senior-reviewer subagent says “you are a senior reviewer with 20 years of experience, here are the tools you can use”. Combine.

5. Worked example: a code-review skill that forks into a senior-reviewer subagent

.claude/agents/senior-reviewer.md:

---
name: senior-reviewer
description: Senior code reviewer — looks for security, performance, design issues
tools: Read, Glob, Grep, Bash(gh *)
model: opus
color: red
---
 
You are a senior software engineer with 20 years of production experience...
[detailed system prompt]

.claude/skills/review-pr/SKILL.md:

---
description: Reviews a PR using the senior-reviewer agent
context: fork
agent: senior-reviewer
argument-hint: [pr-number]
allowed-tools: Bash(gh *)
---
 
# PR review
 
## Diff
```!
gh pr diff $1
```
 
## Description
```!
gh pr view $1 --json title,body,labels
```
 
## Task
 
Review the PR above. Cover:
1. Security issues
2. Performance hot paths
3. Design / architecture concerns
4. Test coverage gaps
 
Return a structured markdown report with severity per issue.

Invocation: /review-pr 4521 → Claude renders the skill (executing gh pr diff 4521 first), forks into the senior-reviewer subagent with the rendered content as the prompt, subagent reviews, returns report.

6. Common gotchas

  1. Skill description too long — silently truncated at 1,536 chars; key keywords for routing get dropped. Put key use case first.
  2. Skill budget overflow — 1 % context budget; many skills → least-used dropped. Run /doctor.
  3. Subagent inherits no system prompt context — only body + env. Don’t assume CLAUDE.md is loaded (Explore/Plan skip; SDK respects setting_sources).
  4. context: fork with no task — subagent gets the body as prompt, but if body is just “here are conventions…”, subagent has nothing to do.
  5. Plugin subagents drop hooks, mcpServers, permissionMode — security.
  6. Subagents can’t spawn subagents — no nesting. Use background sessions or agent teams for parallel work.
  7. Skill body stays in context for session — wasted tokens compound. Keep body lean; move detail to reference.md / examples.md.
  8. Skill.md is not re-read mid-session — if you change it, restart (or it’ll keep old content until next invocation).
  9. disable-model-invocation: true removes from Claude’s context — Claude can’t even know the skill exists. Use sparingly.
  10. Invocation precedence: project subagent named code-reviewer shadows user-level code-reviewer. Watch out when sharing across projects.

7. Further reading