Build with Claude Code

Complete reference for extending, automating, and integrating Claude Code. Work through the learning path, then explore any section.

Learning Path

Recommended order — click any step to jump there. Green = marked as read.

All Sections

🤖 Sub-Agents

Specialized AI assistants that handle specific tasks in their own context window, returning only a summary.

What & Why

Built-In Agents

AgentModelToolsPurpose
ExploreHaikuRead-onlyCodebase search. Levels: quick / medium / very thorough
PlanInheritRead-onlyResearch during plan mode (prevents infinite nesting)
General-purposeInheritAllComplex multi-step tasks needing exploration + action
statusline-setupSonnetRead, EditAuto-invoked by /statusline
Claude Code GuideHaikuWeb, Glob…Auto-invoked for feature questions

Creating Sub-Agents

/agents command
Recommended — guided UI or Claude generation
Markdown file
YAML frontmatter + body in .claude/agents/ or ~/.claude/agents/
--agents CLI flag
JSON on launch, session only, not saved
Managed settings
Org-wide admin deployment
Plugins
Distributed agents (no hooks/mcpServers support)

Scope & Priority (higher wins on name conflict)

#LocationScope
1Managed settingsOrg-wide
2--agents CLI flagSession only
3.claude/agents/Project (check into git!)
4~/.claude/agents/All your projects
5Plugin agents/Where plugin enabled

All Frontmatter Fields

FieldReq?Values
nameUnique lowercase-with-hyphens
descriptionWhen Claude should delegate — clarity = better delegation
toolsAllowlist. Omit = inherit all. Agent(name) restricts spawning
disallowedToolsDenylist. Applied before tools. Tool in both = removed
modelsonnet / opus / haiku / inherit / full model ID
permissionModedefault / acceptEdits / auto / dontAsk / bypassPermissions / plan
maxTurnsMax agentic turns
memoryuser / project ✓ / local
backgroundtrue = always async
isolationworktree = isolated git copy
effortlow / medium / high / xhigh / max
skillsList of skill names, preloaded into context
mcpServersInline or reference MCP servers
hooksPreToolUse / PostToolUse / Stop
colorred/blue/green/yellow/purple/orange/pink/cyan
initialPromptAuto first turn when run as main session agent

Invocation Methods

MethodExampleGuarantee
AutoClaude decides based on description
Natural language"Use the code-reviewer agent…"Claude decides
@-mention@"code-reviewer (agent)"Forces delegation
--agent flagclaude --agent code-reviewerWhole session
settings.json{ "agent": "code-reviewer" }Project default

8 Key Rules

👥 Agent Teams Experimental

Coordinate multiple Claude Code instances working together — each with its own context window, communicating directly with each other via shared task list.

Enable with: CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in settings.json or environment. Requires Claude Code v2.1.32+

Sub-Agents vs Agent Teams

Sub-AgentsAgent Teams
ContextOwn window; results return to callerOwn window; fully independent
CommunicationReport back to main agent onlyTeammates message each other directly
CoordinationMain agent manages all workShared task list with self-coordination
Best forFocused tasks where only result mattersWork requiring discussion and collaboration
Token costLower — results summarized backHigher — each teammate is a separate Claude

Best Use Cases

Architecture

Team Lead
Main session that creates the team, spawns teammates, coordinates work
Teammates
Separate Claude Code instances, each working assigned tasks
Task List
Shared work items; teammates claim and complete them. Uses file locking.
Mailbox
Messaging system for direct communication between agents

Display Modes

ModeHowNotes
in-process (default)All teammates in main terminal. Shift+Down to cycle.Works in any terminal
split panesEach teammate gets own pane. Click to interact.Requires tmux or iTerm2

Key Controls

Hook Events for Teams

EventCan Block?Use for
TeammateIdleYes (exit 2)Keep teammate working; send feedback
TaskCreatedYes (exit 2)Validate task before it's created
TaskCompletedYes (exit 2)Quality gate before marking done

Best Practices

Limitations

🔌 Model Context Protocol (MCP)

Connect Claude Code to external tools and services — databases, APIs, GitHub, Slack, and more — through a standardized protocol.

What is MCP?

Installation Methods

/mcp command
Interactive UI for adding, removing, and managing servers
.mcp.json file
Project-level servers at repository root. Requires one-time approval.
settings.json
User-level (~/.claude/settings.json) or project servers
--mcp-config flag
Pass JSON or file path on CLI launch
Plugins
Plugin's .mcp.json — available when plugin is enabled
Managed settings
Org-wide admin deployment (managed-mcp.json)

Server Config Format (stdio)

# .mcp.json at repository root
{
  "mcpServers": {
    "my-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@my/mcp-server"],
      "env": { "API_KEY": "${MY_API_KEY}" }
    }
  }
}

Connection Types

TypeUse when
stdioLocal process; Claude spawns and communicates via stdin/stdout
httpRemote HTTP server with MCP endpoint
sseServer-Sent Events streaming from remote server
wsWebSocket connection to remote server

Scope & Priority

LocationScopeNotes
Managed settingsOrg-wideAlways loaded; admin controlled
~/.claude/settings.jsonUserAll projects
.mcp.json (repo root)ProjectRequires one-time approval per project
Plugin .mcp.jsonPlugin scopeLoaded when plugin enabled
Subagent mcpServersThat subagent onlyDisconnects when subagent finishes

Popular Official Marketplace MCP Plugins

CategoryPlugins
Source controlgithub, gitlab
Project managementatlassian, asana, linear, notion
Infrastructurevercel, firebase, supabase
Communicationslack
Designfigma
Monitoringsentry

Key Commands

🧩 Plugins

Self-contained directories that extend Claude Code with skills, agents, hooks, MCP servers, LSP servers, and monitors. Share across teams or distribute via marketplaces.

Standalone Config vs Plugins

Standalone (.claude/)Plugin
Skill names/hello/plugin-name:hello
Best forPersonal, project-specific, experimentsSharing, teams, multiple projects, distribution
Version controlPer projectOwn repo + semantic versioning

Plugin Structure

my-plugin/
├── .claude-plugin/
│   └── plugin.json     # manifest (name, description, version)
├── skills/
│   └── my-skill/SKILL.md
├── agents/
│   └── my-agent.md
├── hooks/
│   └── hooks.json
├── .mcp.json
├── .lsp.json           # language server config
├── monitors/
│   └── monitors.json   # background monitors
├── bin/                # executables added to PATH
└── settings.json       # default settings (agent, subagentStatusLine)
⚠ Don't put skills/, agents/, hooks/ inside .claude-plugin/ — only plugin.json goes there!

Plugin Manifest (plugin.json)

{
  "name": "my-plugin",       # namespace for skills: /my-plugin:hello
  "description": "...",
  "version": "1.0.0",
  "author": { "name": "..." }
}

Discovering & Installing Plugins

Marketplace Commands

CommandWhat it does
/plugin marketplace add owner/repoAdd GitHub marketplace
/plugin marketplace add https://urlAdd from URL
/plugin marketplace update nameRefresh plugin listings
/plugin install name@marketplaceInstall a plugin
/plugin disable name@marketplaceDisable without uninstalling
/plugin uninstall name@marketplaceRemove plugin

Plugin Components

Skills
Add /plugin:skill slash commands. Namespace prevents conflicts.
Agents
Specialized subagents Claude can delegate to
Hooks
Event handlers in hooks/hooks.json
MCP Servers
External tools in .mcp.json
LSP Servers
Code intelligence in .lsp.json
Monitors
Background watchers in monitors/monitors.json

Code Intelligence Plugins (LSP)

LanguagePluginRequired binary
TypeScript/JStypescript-lsptypescript-language-server
Pythonpyright-lsppyright-langserver
Gogopls-lspgopls
Rustrust-analyzer-lsprust-analyzer
Javajdtls-lspjdtls
C/C++clangd-lspclangd

LSP gives Claude: auto diagnostics after every edit + code navigation (jump to def, find refs, type info)

⚡ Skills

Create SKILL.md files to add reusable instructions, workflows, and domain knowledge. Invoke with /skill-name or let Claude trigger automatically.

Skills vs CLAUDE.md

Where Skills Live

LocationPathScope
EnterpriseManaged settingsAll org users
Personal~/.claude/skills/name/SKILL.mdAll your projects
Project.claude/skills/name/SKILL.mdThis project
Pluginplugin/skills/name/SKILL.mdWhere plugin enabled

Skill File Structure

my-skill/
├── SKILL.md        # required — frontmatter + instructions
├── reference.md    # detailed docs loaded on demand
├── examples.md     # example outputs
└── scripts/
    └── helper.py   # scripts Claude can execute

Frontmatter Reference

FieldNotes
nameBecomes /name. Lowercase, hyphens, max 64 chars
descriptionRecommended. Claude uses this to auto-invoke. Front-load key use case.
when_to_useExtra triggers. Combined with description, capped at 1,536 chars.
disable-model-invocationtrue = only you can invoke (not Claude). Use for /deploy, /commit
user-invocablefalse = only Claude can invoke. Hidden from / menu.
allowed-toolsTools auto-approved while skill is active (no per-use prompt)
argument-hintShown in autocomplete, e.g. [issue-number]
contextfork = run in isolated subagent context
agentWhich subagent when context: fork. Default: general-purpose
modelOverride model for this skill's turn only
effortOverride effort level for this skill
pathsGlob patterns — Claude auto-loads only when working with matching files
hooksLifecycle hooks scoped to this skill

Invocation Control

FrontmatterYou can invokeClaude can invoke
(default)YesYes
disable-model-invocation: trueYesNo
user-invocable: falseNoYes

String Substitutions

VariableValue
$ARGUMENTSAll text after skill name
$ARGUMENTS[N] or $NNth argument (0-based)
$nameNamed arg from arguments: frontmatter list
${CLAUDE_SESSION_ID}Current session ID
${CLAUDE_SKILL_DIR}Directory containing SKILL.md

Dynamic Context Injection

🪝 Hooks

User-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle. Automate workflows, enforce policies, validate actions.

Hook Configuration Structure

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",         # tool name, regex, or pipe-separated list
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/validate.sh",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

Where to Configure

LocationScope
~/.claude/settings.jsonAll projects
.claude/settings.jsonProject (shareable)
.claude/settings.local.jsonProject (not committed)
Managed policy settingsOrg-wide
Plugin hooks/hooks.jsonWhen plugin enabled
Skill/agent frontmatter hooks:While skill/agent active

All Hook Events

PreToolUse
Before tool executes. Can block.
UserPromptSubmit
User submits prompt. Can block.
PermissionRequest
Permission dialog appears. Can block.
Stop
Claude finishes responding. Can block.
TaskCreated
Task created (teams). Can block.
TaskCompleted
Task completed (teams). Can block.
TeammateIdle
Teammate idles. Can block.
ConfigChange
Config file changes. Can block.
PreCompact
Before compaction. Can block.
WorktreeCreate
Worktree created. Can block.
SessionStart
Session begins/resumes. Once per session.
SessionEnd
Session ends. Once per session.
PostToolUse
Tool succeeds. No blocking.
PostToolUseFailure
Tool fails. No blocking.
SubagentStart
Subagent spawns.
SubagentStop
Subagent finishes.
Notification
Claude sends notification.
PostCompact
After compaction.
InstructionsLoaded
CLAUDE.md/rules loaded.
CwdChanged
Working directory changes.
FileChanged
Watched file changes.
StopFailure
Turn ends with API error.

✋ = can block with exit code 2

Handler Types

TypeUse when
"command"Shell script. Receives JSON via stdin. Exit code controls behavior.
"http"HTTP endpoint. 2xx = success. JSON response for control.
"prompt"LLM evaluation with a prompt. Slower but more flexible.
"agent"Spawn a subagent to evaluate.

Exit Codes (command hooks)

CodeMeaningEffect
0SuccessParses JSON output; proceeds normally
2BlockIgnores stdout; blocks action + shows stderr to Claude
otherNon-blocking errorShows stderr in transcript; continues anyway
Exit code 1 is treated as NON-blocking. Use exit code 2 to enforce policies.

Matcher Patterns

ValueMeaning
"*", "", omittedMatch all occurrences
Letters/digits/underscore/|Exact match or pipe-separated list: "Edit|Write"
Other charsJavaScript regex: "^Bash", "mcp__.*"

Common Patterns

Common Mistakes

⏰ Automation

Run Claude Code programmatically, schedule recurring tasks, and push external events into sessions.

Scheduling Options Comparison

Cloud RoutinesDesktop Tasks/loop (Session)
Runs onAnthropic cloudYour machineYour machine
Requires session openNoNoYes
Local file accessNo (fresh clone)YesYes
Min interval1 hour1 minute1 minute
PersistentYesYesOn --resume if <7 days

/loop — Session Scheduling

CommandBehavior
/loop 5m check the deployFixed schedule every 5 minutes
/loop check the deployClaude picks interval dynamically each iteration
/loopBuilt-in maintenance prompt (finish work, tend PR, cleanup)
/loop 15mMaintenance prompt on fixed 15-min schedule
/loop 20m /review-pr 1234Re-run another skill every 20 min
Press Esc to stop a /loop while it's waiting. Tasks scheduled via CronCreate are unaffected by Esc.

One-Time Reminders

Task Management Tools

ToolPurpose
CronCreateSchedule new task. 5-field cron expr + prompt + recurring flag.
CronListList all tasks with IDs, schedules, prompts
CronDeleteCancel a task by ID

Cron Expression Reference

ExampleMeaning
*/5 * * * *Every 5 minutes
0 * * * *Every hour on the hour
0 9 * * *Every day at 9am local
0 9 * * 1-5Weekdays at 9am
30 14 15 3 *March 15 at 2:30pm

Fields: minute hour day-of-month month day-of-week. All times = local timezone. Max 50 tasks per session. Recurring tasks expire after 7 days.

Programmatic Usage (CLI -p)

PatternCommand
Basicclaude -p "What does the auth module do?"
Bare mode (CI)claude --bare -p "Summarize" --allowedTools "Read"
JSON outputclaude -p "..." --output-format json
Stream JSONclaude -p "..." --output-format stream-json --verbose
Structured outputclaude -p "..." --output-format json --json-schema '...'
Auto-approve toolsclaude -p "..." --allowedTools "Bash,Read,Edit"
Continue conversationclaude -p "Follow up" --continue
Resume by IDclaude -p "..." --resume "$session_id"
Custom system promptclaude -p "..." --append-system-prompt "You are..."

--bare Mode (Recommended for CI)

Permission Modes for Automation

ModeUse in automation
dontAskLocked-down CI — denies anything not explicitly allowed
acceptEditsCI that needs to write files — auto-accepts file edits + common filesystem commands
bypassPermissionsFull automation (use carefully)

loop.md — Custom Default Loop

Disable Scheduling

CLAUDE_CODE_DISABLE_CRON=1 — disables scheduler entirely. CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 — disables background tasks.

🔧 Troubleshooting & Debug

Diagnose installation issues, configuration problems, and unexpected behavior.

Diagnostic Commands

CommandShows
/doctorInstallation health, invalid settings, schema errors, plugin errors
/contextEverything in current context window (system prompt, memory, skills, MCP tools)
/memoryWhich CLAUDE.md files loaded + auto-memory entries
/skillsAvailable skills from all sources
/agentsConfigured subagents and settings
/hooksActive hook configurations for current session
/mcpConnected MCP servers, status, approval state
/permissionsResolved allow/deny rules currently in effect
/statusActive settings sources, managed settings state

Debug Flags

FlagShows
claude --debug hooksHook evaluation live: each event, matchers checked, exit codes
claude --debug mcpMCP server stderr output if tools not showing up
claude --versionInstalled version

Common Config Problems

SymptomCauseFix
Hook never firesMatcher is JSON array ["Edit","Write"]Use string: "Edit|Write"
Hook never firesLowercase tool name "bash"Capitalize: "Bash", "Edit"
Hook never firesHooks in standalone hooks.jsonPut in "hooks" key in settings.json
Global config ignoredAdded to ~/.claude.jsonUse ~/.claude/settings.json (different file!)
settings.json value ignoredSame key in settings.local.jsonlocal overrides project, project overrides user
Skill not appearingFile at .claude/skills/name.mdNeeds folder: .claude/skills/name/SKILL.md
Subagent ignores CLAUDE.mdSubagents don't inherit project memoryPut rules in agent file body (system prompt)
MCP server not loadingFile under .claude/Project MCP goes at repo root as .mcp.json
MCP server fails from some dirsRelative path in command/argsUse absolute paths for local scripts
MCP env vars missingVars in settings.json envSet env in .mcp.json per-server section
Subdirectory CLAUDE.md ignoredLoads on demand onlyLoads when Claude reads a file there with Read tool

Installation Quick Fixes

ErrorFix
command not found: claudeAdd ~/.local/bin to PATH
Syntax error / HTML from installRegion restriction or network issue. Try Homebrew/winget.
Killed during install (Linux)Low RAM. Add swap: sudo fallocate -l 2G /swapfile
TLS/SSL errorsUpdate CA certs. Set NODE_EXTRA_CA_CERTS for corporate proxy.
Multiple installationsKeep native ~/.local/bin/claude. Remove npm/brew duplicates.
403 after loginCheck subscription active. Console: need Claude Code/Developer role.
Model not foundStale model ID in settings. Run /model to pick from available list.

Configuration File Locations

FilePurpose
~/.claude/settings.jsonUser settings (permissions, hooks, model)
.claude/settings.jsonProject settings (committed)
.claude/settings.local.jsonLocal project settings (not committed)
~/.claude.jsonGlobal state (theme, OAuth, MCP) — NOT for hooks/permissions
.mcp.jsonProject MCP servers (at repo root)
Managed settings dirOrg-wide config by admins

Performance Issues

📡 Channels Research Preview

Push external events into a running Claude Code session from an MCP server. Requires Claude Code v2.1.80+, claude.ai login.

Research preview — CLI flag syntax and protocol may change. Requires claude.ai login (not Console/API key). Team/Enterprise: admin must enable channelsEnabled.

What is a Channel?

Supported Channels

📱 Telegram
Bot via BotFather. Token saved to ~/.claude/channels/telegram/.env or TELEGRAM_BOT_TOKEN env var.
💬 Discord
Bot via Discord Developer Portal. Needs Message Content Intent enabled. Token saved to ~/.claude/channels/discord/.env.
🍎 iMessage
macOS only. Reads Messages DB directly via AppleScript. Needs Full Disk Access granted to terminal app.
🧪 Fakechat
localhost demo on port 8787. No auth needed. Great for testing the plugin flow before connecting a real platform.

Quickstart (Fakechat demo)

Setup Pattern (Telegram/Discord)

Security

Enterprise Controls

SettingPurposeDefault
channelsEnabledMaster switch — must be true for any channel to workBlocked
allowedChannelPluginsWhich plugins can register (replaces Anthropic default list)Anthropic default list

Channels vs Other Integration Methods

FeatureWhat it doesBest for
Claude Code on webFresh cloud sandbox cloned from GitHubAsync self-contained work
Claude in SlackSpawns web session from @Claude mentionStarting tasks from team chat
Standard MCP serverClaude queries it on-demand — nothing pushedRead/query on-demand
Remote ControlYou drive local session from claude.ai or mobileSteering in-progress session
ChannelsExternal events pushed into running local sessionChat bridge, webhook receiver, CI alerts

Use Cases

Chat bridge
Ask Claude from phone (Telegram/Discord/iMessage) — answer comes back while work runs on your machine with real files.
Webhook receiver
CI results, error tracker alerts, deploy pipeline events arrive where Claude has your files open and remembers context.
Monitoring
Forward monitoring alerts so Claude can react in context — investigate logs, trigger fixes.

🚨 Error Reference

Runtime errors Claude Code displays, what each means, and how to recover. Install errors (command not found, TLS failures) are in Troubleshooting.

Claude Code auto-retries transient failures (up to 10×, exponential backoff). Spinner shows "Retrying in Ns · attempt x/y". When you see an error, retries are already exhausted. Tune: CLAUDE_CODE_MAX_RETRIES (default 10) · API_TIMEOUT_MS (default 600000ms)

Server Errors

ErrorCauseFix
API Error: 500 Internal server errorUnexpected API failure — not your prompt or accountCheck status.claude.com · retry · type "try again" for long prompts · run /feedback
API Error: Repeated 529 OverloadedAPI at capacity — not your usage limit, not counted against quotaCheck status.claude.com · wait a few minutes · /model to switch model (capacity per-model)
Request timed outHigh load or very large response (default 10 min timeout)Retry · break work into smaller prompts · raise API_TIMEOUT_MS
<model> is temporarily unavailable, auto mode cannot determine safety...Auto mode classifier overloaded — blocked action as precautionRetry after a few seconds · reads/edits/searches still work · transient only

Usage Limits

ErrorCauseFix
You've hit your session/weekly limitRolling plan quota exhaustedWait for reset time shown · /usage · /extra-usage to buy more · upgrade plan
Server is temporarily limiting requestsShort-lived throttle unrelated to your quotaWait briefly · retry
Request rejected (429)Rate limit on API key/Bedrock/Vertex projectRun /status (check credential) · check provider console · reduce concurrency (CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY)
Credit balance is too lowConsole org prepaid credits exhaustedAdd credits at platform.claude.com/settings/billing · enable auto-reload · /login for subscription auth

Authentication Errors

ErrorFix
Not logged in · Please run /login/login to authenticate · confirm ANTHROPIC_API_KEY is set+exported · for CI use apiKeyHelper script
Invalid API keyCheck for typos · run "env | grep ANTHROPIC" (direnv/.env may load stale key) · unset key and /login · run apiKeyHelper script directly
This organization has been disabledStale ANTHROPIC_API_KEY overrides subscription. Unset the env var from shell profile, relaunch.
OAuth token revoked/expired/login to re-auth · if persists: /logout then /login · system clock / macOS Keychain check
does not meet scope requirement user:profile/login to mint new token with current scopes (no logout needed)

Network Errors

ErrorFix
Unable to connect to API (ECONNREFUSED/ECONNRESET/ETIMEDOUT)curl -I https://api.anthropic.com to test · set HTTPS_PROXY for corporate proxy · set ANTHROPIC_BASE_URL for LLM gateway · check NODE_EXTRA_CA_CERTS
SSL certificate verification failed / Self-signed certificateSet NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem. Do NOT use NODE_TLS_REJECT_UNAUTHORIZED=0

Request Errors

ErrorFix
Prompt is too long/compact · /clear · /context (see what's consuming) · disable unused MCP servers · trim CLAUDE.md files
Error during compaction: Conversation too longEsc×2 to go back several turns, then /compact again · or /clear (conversation preserved, reopen with /resume)
Request too large (max 30 MB)Esc×2, step back past the oversized content · reference large files by path instead of pasting
Image was too largeEsc×2, step back past the image · resize (max 8000px single, 2000px many in context) · crop screenshot
PDF too large / PDF is password protectedRead by page range instead · extract text with pdftotext · remove password and re-export
Extra inputs are not permitted (context_management...)Gateway strips anthropic-beta header. Configure gateway to forward it, or set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
There's an issue with the selected model/model to pick available model · use alias (sonnet/opus) not full versioned ID
Claude Opus not available with Pro plan/model to pick plan-compatible model · /logout then /login if recently upgraded
thinking.type.enabled not supportedclaude update to v2.1.111+ · or switch to Opus 4.6 / Sonnet
max_tokens must be greater than thinking.budget_tokensLower MAX_THINKING_TOKENS or raise CLAUDE_CODE_MAX_OUTPUT_TOKENS
API Error: 400 due to tool use concurrency issues/rewind (Esc×2) to step back to checkpoint before corrupted turn

Quality Seems Lower Than Usual

Quick Recovery Commands

/rewind (Esc×2)
Step back to checkpoint before corrupted/bad turn. Best recovery for most errors.
/compact
Summarize earlier turns to free context space. Run at natural breakpoints.
/clear
Start fresh session. Previous conversation preserved; reopen with /resume.
/status
Show which credential is active. Diagnose auth issues first.
/model
Switch model — useful for overloaded model (529) or plan limits (Opus).
/feedback
Send transcript + description to Anthropic. Includes prefilled GitHub issue link.

📄 Example Files

Annotated real-world files for every Claude Code extension type. Each comment explains why, not just what.

🤖 Sub-Agent
⚡ Skill
🪝 Hooks
🔌 MCP (.mcp.json)
🧩 Plugin (plugin.json)
👥 Agent Teams
⏰ Headless / CI
Save to ~/.claude/agents/ (user-level, all projects) or .claude/agents/ (project-level, commit to git).
~/.claude/agents/code-reviewer.md
---
name: code-reviewer             # lowercase-with-hyphens, matches filename
description: Review changed files for bugs, security issues, and style
                                   # Claude reads this to decide WHEN to delegate
model: sonnet                      # sonnet | opus | haiku | inherit | full model id
tools: Read, Grep, Glob, Bash      # allowlist — omit to inherit all tools
permissionMode: plan              # plan = read-only, never edits files
memory: project                   # project = .claude/agent-memory/, shareable via git
maxTurns: 20                      # cap to avoid runaway token usage
---

You are a focused code reviewer. When invoked you receive changed file paths.

Steps:
1. Read each changed file in full
2. Check for: bugs, security issues (injection, auth bypass, secrets), style violations
3. Return a concise review — one finding per line, with severity (critical/warn/info) and line number

Do not suggest refactors unless asked. Focus on correctness and safety only.
~/.claude/agents/debugger.md
---
name: debugger
description: Diagnose and fix errors, stack traces, and failing tests
model: inherit                     # use whatever model the parent is using
tools: Read, Edit, Bash, Grep, Glob
isolation: worktree               # isolated git copy — auto-cleaned if no changes made
maxTurns: 40
---

You are an expert debugger. You will:
1. Reproduce the error by reading logs and running the failing command
2. Trace the root cause through the call stack
3. Apply the minimal fix — do not refactor surrounding code
4. Confirm the fix works by running the test or command again

Always explain what caused the bug before showing the fix.
Save to .claude/skills/ (project) or ~/.claude/skills/ (user). Invoke with /skill-name or reference it in a prompt.
.claude/skills/deploy.md
---
name: deploy
description: Run the full deployment pipeline for this project
disable-model-invocation: true    # only YOU can trigger this — not Claude autonomously
context: fork                      # runs in isolated subagent, keeps main context clean
---

# Deploy Procedure

Run these steps in order. Stop and report if any step fails.

1. `npm run build` — build production assets, check for errors
2. `npm test` — run full test suite, report failures before continuing
3. `git tag v$(date +%Y%m%d-%H%M)` — create a timestamped release tag
4. `git push origin main --tags` — push code and tag
5. Confirm the GitHub Actions CI pipeline passes (check Actions tab)

Report: build status, test count passed/failed, tag name, CI link.
.claude/skills/pr-review.md
---
name: pr-review
description: Review open pull requests and post summary comments
user-invocable: false             # hidden from / menu — Claude uses internally
context: fork
---

Use the GitHub MCP tool to:
1. List open PRs on this repo
2. For each PR: read the diff, check CI status, read existing review comments
3. Post a short review comment summarising: what changed, any risks, suggested next step

Be concise. One paragraph per PR. Flag blockers clearly.
Hooks go under the "hooks" key in ~/.claude/settings.json (user-level) or .claude/settings.json (project). NOT in a standalone hooks.json file.
.claude/settings.json
{
  "hooks": {

    "PreToolUse": [
      {
        "matcher": "Bash",          // fire before every Bash call
        "hooks": [{
          "type": "command",
          // exit 2 = BLOCK the tool + send stderr to Claude as error
          // exit 0 = allow  |  exit 1 = log but allow
          "command": "bash -c 'cmd=$(echo $CLAUDE_TOOL_INPUT | jq -r .command); echo \"$cmd\" >> ~/claude-audit.log; if echo \"$cmd\" | grep -qE \"rm -rf|DROP TABLE\"; then echo \"Blocked: destructive command\" >&2; exit 2; fi'"
        }]
      },
      {
        "matcher": "Write|Edit",    // pipe-separate multiple tools
        "hooks": [{
          "type": "command",
          "command": "bash -c 'path=$(echo $CLAUDE_TOOL_INPUT | jq -r .path // .file_path); if [[ $path == *.env* ]]; then echo \"Blocked: .env file\" >&2; exit 2; fi'"
        }]
      }
    ],

    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{
          "type": "command",
          // auto-format every file Claude writes or edits
          "command": "bash -c 'path=$(echo $CLAUDE_TOOL_INPUT | jq -r .path // .file_path); npx prettier --write \"$path\" 2>/dev/null || true'"
        }]
      }
    ],

    "Stop": [
      {
        "hooks": [{
          "type": "command",
          // notify when Claude finishes a long task
          "command": "osascript -e 'display notification \"Claude finished\" with title \"Claude Code\"'"
        }]
      }
    ]
  }
}
Save as .mcp.json at the repository root — NOT inside .claude/. Commit to git so teammates get the same tools.
.mcp.json (repo root)
{
  "mcpServers": {

    "github": {
      "type": "stdio",            // local process via stdin/stdout
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        // put tokens in env here, NOT in args (args appear in process list)
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
      }
    },

    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@playwright/mcp@latest"]
                                 // no env needed — launches browser headlessly
    },

    "postgres": {
      "type": "stdio",
      "command": "/usr/local/bin/mcp-server-postgres",
                                 // use ABSOLUTE paths for local scripts
                                 // relative paths break when launched from different dirs
      "args": ["--connection-string", "postgresql://localhost/mydb"]
    },

    "remote-api": {
      "type": "http",             // remote HTTP endpoint (no local process needed)
      "url": "https://mcp.example.com/tools",
      "headers": {
        "Authorization": "Bearer ${MY_API_TOKEN}"
      }
    }

  }
}
A plugin is a directory. plugin.json lives inside .claude-plugin/. All other content (skills/, agents/, hooks/, .mcp.json) goes at the plugin root.
my-plugin/ (directory structure)
my-plugin/
├── .claude-plugin/
│   └── plugin.json             ← manifest lives here
├── skills/
│   └── deploy.md               ← skills at plugin root level
├── agents/
│   └── reviewer.md
├── hooks/
│   └── pre-commit.sh
└── .mcp.json                   ← MCP config at plugin root
my-plugin/.claude-plugin/plugin.json
{
  "name": "my-plugin",           // used for namespacing: /my-plugin:skill-name
  "version": "1.0.0",
  "description": "Code review + deploy tools for this monorepo",
  "author": "your-team",
  "minClaudeCodeVersion": "2.0.0" // optional minimum version gate
}
Install a plugin: /plugin install path/to/my-plugin or /plugin install repo@marketplace. After install, run /reload-plugins. Skills are then available as /my-plugin:deploy.
Agent Teams are experimental — requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 and Claude Code v2.1.32+.
.claude/settings.json (enable teams)
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}
Prompt to spawn a team (in Claude Code session)
Spawn a team to build the login feature:
- One teammate writes the backend API (Node/Express, JWT auth)
- One teammate writes the frontend form (React, form validation)
- One teammate writes the tests (Jest + React Testing Library)
Coordinate via the shared task list. Don't duplicate work.

// Each teammate gets its own context + terminal
// They message each other directly via shared task list
// Use Shift+Down to cycle between teammate terminals (in-process mode)
// Or launch with --display split-panes for tmux/iTerm2 split view
Teammate-to-teammate message syntax
// A teammate sends a message to another teammate by name:
@frontend-agent The API endpoint is POST /api/auth/login
Request body: { email: string, password: string }
Response: { token: string, user: { id, email, role } }
Ready for you to wire up the form.
Use claude -p for non-interactive automation. Add --bare for reproducible CI runs (skips hooks, skills, MCP, CLAUDE.md auto-discovery).
scripts/ai-review.sh (CI script)
#!/bin/bash
# Run Claude Code headlessly in CI to review a PR diff

# --bare: reproducible, skips local config discovery
# --output-format json: machine-readable result
# ANTHROPIC_API_KEY must be set as a CI secret

DIFF=$(git diff origin/main...HEAD)

RESULT=$(claude -p \
  --bare \
  --output-format json \
  "Review this diff for bugs and security issues. Be concise.

$DIFF")

# Parse result field from JSON output
echo "$RESULT" | jq -r '.result'

# Exit non-zero if Claude found critical issues
if echo "$RESULT" | jq -r '.result' | grep -qi "critical"; then
  exit 1
fi
Structured JSON output with schema
# Get schema-conformant output (Claude Code v2+)
claude -p "Analyse this file and return findings" \
  --output-format json \
  --json-schema '{
    "type": "object",
    "properties": {
      "severity": {"type": "string", "enum": ["low","medium","high","critical"]},
      "findings": {"type": "array", "items": {"type": "string"}},
      "safe_to_merge": {"type": "boolean"}
    },
    "required": ["severity","findings","safe_to_merge"]
  }'

# Continue a previous session by ID
SESSION_ID=$(cat .claude-session-id)
claude -p "Continue where you left off" --resume "$SESSION_ID"
0 mastered 0 to review 0 remaining
Question — click to flip
Answer
Space flip  ·  Got it  ·  Review again