If you’ve been using Claude through chat for the last year, Claude Code feels like a different product. It is.

Claude Chat is a conversation. You paste code, ask a question, get an answer, paste it back into your editor. You stay in the loop — literally — for every action. The model never touches your filesystem, never runs a command, never sees more than what you choose to copy over. It’s powerful, but it’s a copilot that only works when you manually drive.

Claude Code is an agent. You give it a task — “refactor the auth module to use zod schemas” — and it reads the relevant files itself, drafts a plan, edits the code, runs your tests, reports back. It has tools: Read, Edit, Bash, Grep. It persists state across multiple turns. It can run for minutes or hours on a single instruction, pausing only to ask clarifying questions or when something looks wrong. The same underlying model is doing the reasoning, but the interface and guardrails are built for autonomy instead of dialogue.

Who this guide is for. Senior engineers who want to move past chat-based AI coding and actually ship production software with an agent in the loop. Team leads evaluating whether to adopt Claude Code as a shared tool across a 5-person or 50-person team. Solo builders who are tired of manually copy-pasting between editors and want the agent to hold the whole repo in context. If you’ve never written code professionally, the rest of our blog is a better starting point.

The promise. Thirty minutes with this guide and you’ll know how to install Claude Code, configure it so it doesn’t do anything stupid, extend it with hooks and plugins, orchestrate subagents for large tasks, and ship it to your team without burning money on runaway sessions. I’m writing from eighteen months of using Claude Code daily on production codebases — including a 50,000-line legacy Kotlin refactor and a full indie SaaS build — and the mistakes I made so you don’t have to.

Table of Contents

Jump to any section:

  1. What Is Claude Code?
  2. Setup & Configuration
  3. The Command Lifecycle
  4. Hooks Deep Dive
  5. Subagents & Orchestration
  6. Plugins & the Extension Story
  7. Production Patterns
  8. Troubleshooting & FAQ
  9. Where to Go Next

Last updated: April 30, 2026. This guide is living — we refresh it every quarter as Claude Code evolves.


What Is Claude Code?

Claude Code is Anthropic’s command-line coding agent. That one sentence undersells it.

At the surface, it’s a CLI you run in a terminal. You type a prompt, it does things to your files. But underneath, it’s a full autonomous loop: the agent plans, reads files, edits them, runs shells, observes output, adjusts, and keeps going until the task is done or it runs out of budget. It ships with VS Code, Cursor, and JetBrains plugins that share session state with the CLI, so you can switch between terminal and IDE mid-task. It also runs entirely in the background as a GitHub Action, in CI pipelines, or inside scheduled workflows.

The important shift is that Claude Code is the first Anthropic product explicitly built around an agent loop, not a chat turn. Everything we discuss in this guide — hooks, subagents, plugins, CLAUDE.md, permissions — only makes sense once you internalize that the agent is the one making decisions, and you’re shaping the environment it operates in. That’s also the platform argument we’ve been making: Claude Code isn’t a chatbot with file access; it’s the start of a developer-tool ecosystem, with the same shape WordPress took fifteen years ago.

Claude Code vs Claude Chat — the mental model shift

The single biggest source of confusion for developers coming from chat is expecting Claude Code to behave the same way. It doesn’t.

DimensionClaude ChatClaude Code
InteractionOne question, one answerMulti-turn agent loop
File accessOnly what you pasteFull repo (bounded by permissions)
Session lengthSeconds to minutesMinutes to hours
ExecutionNoneBash, Edit, Write, Grep, Glob
StatePer-messagePersistent per-session + CLAUDE.md
Safety model”Don’t paste secrets”Permissions + hooks + audit logs

A good rule of thumb: reach for chat when you need a specific piece of information or a short code snippet, and reach for Code when you need something done in your actual repo. Chat is better at dialogue, nuance, and explaining why. Code is better at reading six files, finding the right one, editing it, and running the test suite.

You’ll still use both. Most senior devs I talk to end up with a two-window workflow: Claude Code running the agent loop in a terminal, Claude Chat open in a browser tab for the “wait, what does this obscure library do” questions that would otherwise pollute the agent’s context.

Architecture Overview

At a high level, Claude Code looks like this:

Claude Code architecture diagram showing terminal and IDE plugin feeding into the Claude Code runtime, which issues tool calls such as Read, Edit, and Bash and receives observations back from the model

Figure 1: The Claude Code runtime sits between your terminal or IDE and the model. Tool calls and observations loop through the runtime; hooks intercept at the tool boundary; subagents spawn as child runtimes.

A session starts when you invoke claude in a terminal or open the IDE plugin. The runtime assembles initial context: your CLAUDE.md file, the current working directory’s file listing, any files you’ve explicitly attached, and the system prompt that tells the model what tools it has. The model then enters a loop:

  1. Plan. Decide what tool to call next, or respond and stop.
  2. Call. Invoke the tool — Read("src/auth.ts"), Bash("npm test"), and so on.
  3. Observe. Read the tool result.
  4. Repeat. Until the task is done or a stop condition fires.

Every tool call passes through a permissions layer (which asks you before dangerous operations) and through any hooks you’ve configured (which can block, modify, or log the call). Subagents, when spawned, are their own runtime instances — isolated context, their own tool access, their own hooks.

That four-step loop is the whole product. Everything else in this guide is configuration around it.

The Three Things Claude Code Does Better Than Anything Else

After eighteen months of daily use, I’ve landed on three categories where Claude Code is meaningfully better than any other AI coding tool I’ve tried — Cursor, Aider, Continue, Copilot, Windsurf, Cline.

1. Multi-file refactoring with full context. When I need to rename a concept across twenty files, update seven config files to point at a new service, or migrate a whole module from one pattern to another, Claude Code is the only tool that keeps the whole operation coherent. Cursor can do single-file edits brilliantly; it struggles when the change spans a directory. Claude Code’s agent loop naturally handles the read-plan-edit-verify pattern across files. Our legacy refactor field guide is a worked example of this at 50,000-line scale.

2. Long-running task chains. Build the schema, generate the migration, update the ORM model, rewrite the two affected endpoints, update the four tests, run the suite, fix whatever broke. That’s a thirty-minute task for a human and a one-command task for Claude Code. The agent can chain that many steps without losing the thread because it maintains its own working memory across turns. Chat can’t; IDE-first tools struggle when a step requires running a shell command and interpreting the output.

3. Safe production-grade execution. Claude Code is the only agent I trust to run commands on a real repo on a real machine, because the safety model is actually real: permissions ask before anything destructive, hooks let me enforce policy without touching the agent’s core, and every action is observable. If you want the model to run rm for you, it won’t happen silently — which matters the first time you leave an agent running unattended for an hour. For a grounded take on why this kind of engineering discipline matters more than raw model capability, we’ve written about the broader industry shift elsewhere.

These aren’t the only things Claude Code does, and for small tasks any of the competing tools will work. But the reason we’ve built our entire stack around Claude Code — courses, toolkit, community, this guide — is that these three capabilities are what shipping production software actually requires.


Setup & Configuration

You’ve installed thousands of CLI tools. Installing Claude Code is the easy part. Configuring it so it respects your team’s conventions, doesn’t blow out your token budget on the first session, and doesn’t run a destructive command you haven’t pre-approved — that takes a little care. This section is the fifteen-minute checklist I give anyone on day one.

Install

Claude Code runs on macOS, Linux, and Windows (via WSL2). The canonical install is a single curl:

Terminal window
curl -fsSL https://claude.ai/install.sh | sh

On mac you can also brew install anthropic/tap/claude — same binary, different distribution. The installer puts claude on your PATH and registers a post-install hook that asks you to authenticate the first time you run it. Don’t skip that — trying to debug a missing OAuth token later is miserable.

IDE plugins ship separately:

IDEInstallShares CLI session?
VS CodeExtensions marketplace → “Claude Code”Yes
CursorBuilt-in, enable in Settings → AI ProvidersYes
JetBrains (IntelliJ, WebStorm, etc.)JetBrains Marketplace → “Claude Code”Yes

The “shares session” column is the thing that actually matters: if you start an agent run in the terminal, you can attach from VS Code mid-task, see what Claude is doing in a side panel, and accept or reject proposed edits inline. That cross-surface continuity is unique to Claude Code right now.

Auth options: a Claude Pro or Team subscription (web-style billing) or an API key from the developer console. Subscriptions are simpler and fine for most solo devs; API keys let you pin usage to a specific cost center for companies.

The First 10 Minutes

The first thing to do in a fresh Claude Code install — before you let it touch a real repo — is create a project-level .claude/settings.json in your working directory. The empty install defaults are deliberately loose; the settings file is how you tighten them.

Here’s the minimum I start with on every new project:

{
"model": "claude-sonnet-4-6",
"planningModel": "claude-opus-4-6",
"permissions": {
"deny": ["Bash(rm -rf *)", "Bash(git push --force *)"],
"ask": ["Bash(git commit *)", "Bash(npm publish *)"]
},
"env": {
"CLAUDE_MAX_TOKENS_PER_SESSION": "200000"
}
}

Four things, all pulling their weight:

  • model + planningModel. Opus for planning (expensive but worth it for the task decomposition), Sonnet for grunt execution. Roughly halves your token spend vs. running Opus on everything without visibly slower output.
  • permissions.deny. A literal list of glob patterns that must never run unattended. Even if you trust the model, add rm -rf and force-push here. The day you step away from the terminal mid-session, you’ll be glad.
  • permissions.ask. Patterns that require confirmation. git commit and npm publish are the two I put on every repo; everything else I approve on first occurrence and let ride.
  • env. Session-level environment variables. The token budget line gives you a hard ceiling before you’ve even thought about billing.

One productivity trick worth knowing early: you can pipe shell output directly into Claude Code via claude -p "fix this" < errors.log. Skips the copy-paste step entirely for error triage.

CLAUDE.md — Your Project’s Memory

CLAUDE.md is a plain markdown file at your repo root that Claude Code reads at the start of every session. It’s the difference between an agent that knows your codebase and one that guesses. If you skip setting this up, you will spend the first ten minutes of every session re-explaining the same context, forever.

What goes in it:

  • Coding conventions. TypeScript strict mode? Tabs or spaces? Naming patterns (e.g. “repository methods use findBy*, not getBy*”)? This is the biggest single win.
  • Architecture decisions with rationale. “Auth lives in src/lib/auth and uses zod schemas, not class-validators — see ADR-0003 for why.”
  • Build and test commands. Exact invocations: npm run test:unit, pnpm build:prod. Save the agent from guessing.
  • Taboo patterns. “Never introduce a new ORM; we use Drizzle. Never add a new auth provider; we use Clerk.”
  • Active constraints. “This branch is mid-migration from Express to Hono; don’t edit anything in src/legacy/.”

What does NOT go in it:

  • Secrets, API keys, credentials — CLAUDE.md is checked into git, and Claude will happily quote it back at you in a log.
  • Temporary session notes — those belong in the prompt or a scratch file, not the project memory.
  • Overly long style guides — if it’s more than ~500 lines, the token cost on every session start adds up. Link out to the full style guide instead.

We’ve written a deep-dive on CLAUDE.md covering what makes a great one and how to evolve it over a project’s lifetime, so I’ll stop here.

Global vs Project vs Enterprise Settings

Three scopes, resolved in cascading order:

ScopeFile locationUse case
Global~/.claude/settings.jsonYour personal defaults across every project
Project.claude/settings.json (repo root)Per-project policy, checked into git
Local.claude/settings.local.jsonPersonal overrides for this project, gitignored
InvocationCLI flags (--model, --max-tokens, etc.)One-off overrides for a single run

Later scopes override earlier ones. Use global for your personal preferences (default model, editor integration, theme). Use project for team-wide policy that must be consistent across everyone’s local checkout — permissions, model pinning, taboo patterns. Use local for things only you want (your personal API key alias, your preferred verbosity). Use invocation for the “I just want to try this once without touching config” moments.

The real reason this hierarchy matters: when a new hire on your team runs Claude Code on the repo, they inherit the project settings automatically. No onboarding doc needed for “which model do we use, what commands are off-limits, where’s our CLAUDE.md.” It’s just there.

For enterprise deployments, there’s a fourth tier at /etc/claude/settings.json that overrides everything and is typically managed by your security or platform team. You’ll rarely touch it directly, but knowing it exists helps when a command mysteriously gets blocked despite your project config allowing it.


The Command Lifecycle

Claude Code looks like a chat box that accepts a sentence and returns a diff. Under the hood, every command you type kicks off a predictable loop: parse, plan, act, observe, repeat. Once you can mentally model that loop, debugging weird behavior becomes trivial.

What Happens When You Type a Command

Say you type: refactor auth.ts to use zod schemas instead of the custom validator. In the next two seconds, Claude Code does this:

  1. Tokenize and assemble context. The prompt gets bundled with your CLAUDE.md, the current working directory’s file listing, any files you’ve previously attached, and the system prompt that describes the available tools. This is what goes to the model.
  2. Plan. The model doesn’t start editing immediately — it decides what tools to call first. In this case, it will almost certainly call Read("src/auth.ts") and Grep("customValidator") to understand the scope of the change before touching anything.
  3. Tool call. The runtime executes the tool, returns the result, and sends it back to the model.
  4. Observe and iterate. The model reads the result and plans the next step. It reads package.json to check if zod is installed, reads the two files that import auth.ts, writes the refactored version, runs npm test to verify.
  5. Respond and stop. When the model decides the task is done, it returns a summary and stops.

A decent refactor like this takes ten to fifteen tool calls over maybe ninety seconds. You see every call in the terminal UI, with the tool name and arguments, so nothing is hidden. If you’re using the agent as a code reviewer — which is a workflow I highly recommend — you’ll notice it reads a lot more than it writes, which is exactly what you want.

Tool Usage — the 6 Core Tools

Every Claude Code action ultimately routes through one of six primitives. Knowing them and their failure modes is the fastest way to write a good CLAUDE.md.

ToolWhat it doesCommon failure
ReadLoads a file (or slice of one) into the agent’s contextSkipped before Edit — agent edits stale content
EditSurgical string replacement in a file already Readold_string not unique → edit bails out
WriteFull-file overwrite or createUsed when Edit would have been safer → lost changes
GlobFind files by pattern (src/**/*.test.ts)Wrong base path → returns empty
GrepSearch file contents by regexUnescaped regex metacharacters → silent no-match
BashExecute a shell commandMissing timeout on long-running command → session hangs

Two rules I enforce with hooks on every project:

1. Always Read before Edit. This is the single biggest source of agent frustration. The model has a stale mental model of the file, tries to Edit, the old_string doesn’t match, it retries with slightly different indentation, fails again, and burns a hundred tokens before giving up. Force a Read first via a PreToolUse hook and the failure rate on Edits drops by more than half.

2. Bash always has a timeout. npm test hangs, docker compose up is meant to run indefinitely, a Python script has a bug. Without a timeout, your whole agent session stalls waiting on nothing. Default to 60 seconds unless you know better.

These aren’t quirks — they’re the same failure modes that show up across every other agentic coding tool I’ve used. The difference is that Claude Code gives you the hook system to enforce the fixes automatically, instead of hoping the model gets better over time.

Planning Mode vs Execution Mode

There are two distinct modes Claude Code can run in. By default it’s in execution mode: plan and execute interleave, the agent ships changes as it goes. That’s the right default for small tasks.

For anything bigger — a database migration, a framework upgrade, anything that touches more than three files — switch to planning mode first. Either start the session with claude /plan or pass the --plan-only flag:

Terminal window
claude --plan-only "migrate the Sessions module from Redis to Postgres"

Planning mode runs the Plan → Read → Grep → Glob steps but refuses to call Edit, Write, or mutating Bash. The agent produces a step-by-step plan with file-level detail, you review it, you approve it (or edit the plan and re-plan), and only then do you execute.

The cost argument alone justifies this: a wrong execution on a ten-file refactor costs you fifteen minutes of token spend plus whatever git gymnastics you do to revert. A wrong plan costs you thirty seconds to say “no, don’t touch the migration runner, do X instead.”

There’s also a budget control set: --max-turns, --max-tokens-per-run, and /budget at runtime for adjusting limits mid-session. Useful when the agent goes down a rabbit hole and you want to stop it before it burns another 50k tokens on the wrong approach.

Context Management

Claude Code’s effective context is around 200,000 tokens per session. That sounds enormous until you realize a mid-sized TypeScript file is 3,000 tokens, and a Bash session that ran npm install with verbose output can be 5,000 tokens by itself. A long session easily hits the ceiling.

Three techniques in order of preference:

  1. Auto-compaction. Claude Code auto-summarizes old turns when context fills past roughly 80%. This is mostly transparent, but the summarization loses nuance — variable names, specific line numbers, exact error messages. The first sign it’s happening: the agent starts asking about things it already did earlier in the session.
  2. Manual /compact. Run this before you hit the wall, not after. Compaction is summary-lossy either way, but you get to choose when, and the summary quality is better while there’s still room to write a coherent one.
  3. Start a fresh session. The nuclear option, but often the right one for multi-hour refactors. Dump the current state to a file with /save plan.md, start a new session, /load plan.md. You lose turn history but keep structured state. For long-running work, this is the pattern harness engineering for Claude Code wraps in a more disciplined form.

The counterintuitive lesson: a long session is not a productive session. The best agent-assisted workflows I’ve seen finish tasks in five to twenty focused turns, then either ship or start fresh. Pushing a session past an hour almost always means the task should have been split.


Hooks Deep Dive

Hooks are Claude Code’s secret weapon. They’re the difference between “interesting AI tool” and “agent I can trust on production.” If you install nothing else from this guide, install hooks.

Why Hooks Matter

Without hooks, you have a model that can execute arbitrary shell commands on your machine — which is terrifying if you think about it for more than a minute. With hooks, you have a tool boundary where every intent passes through your code first.

Three arguments for hooks:

  • Safety. Every tool call passes through hooks before it runs. You can veto dangerous commands, force a Read before Edit, or quarantine specific paths with a ten-line bash script. Unlike prompt-level instructions (“don’t run rm”), hooks enforce the rule at runtime — a prompt injection can’t bypass them.
  • Productivity. Auto-format code on every edit. Auto-run affected tests after every change. Log every action to a file you can grep later. These are the kinds of tiny automations that would be annoying to remember manually; hooks make them invisible.
  • Policy. Larger teams need to enforce rules that shouldn’t depend on every developer reading a contributing doc. Hooks let you codify “commits must have a Jira ticket,” “no hardcoded credentials,” “test coverage can’t drop” into scripts that run automatically. The rules become executable instead of aspirational.

Hook Events — the 3 Lifecycle Points

Claude Code’s hook system exposes three events, each firing at a different moment in the tool execution loop:

Hook event timeline showing PreToolUse fires before a tool call, PostToolUse fires after a successful tool call, and Stop fires when a session ends

  • PreToolUse — fires before a tool call. Can block the call, modify arguments, or pass through. This is where you enforce safety policy.
  • PostToolUse — fires after a tool call completes. Can’t block (the action already happened), but can observe, log, or trigger follow-up automation — formatters, test runs, notifications.
  • Stop — fires when a session ends. Useful for cleanup, summary, or audit log finalization.

For the full hook reference including every matcher pattern, payload shape, and exit code semantics, see the complete hooks guide. Here’s the minimum to start:

Hooks are declared in .claude/settings.json under the hooks key. Each entry specifies an event, a matcher pattern (which tool calls trigger it), and a command to run:

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/pre-bash.sh" }
]
}
]
}
}

The matcher uses literal tool names (Bash, Edit, Write) or the wildcard *. Hooks receive a JSON payload on stdin describing the intent: the command string for Bash, the file path and old/new content for Edit, and so on. The script reads stdin, decides what to do, and signals back via exit code — 0 means allow, 2 means block with stdout as the reason, any other non-zero signals an error.

Four Hooks Every Serious User Should Install

These are the four I copy into .claude/hooks/ on every new project. Each is under forty lines of bash; combined they’ve saved me from at least three separate incidents that would have taken an hour to recover from.

1. Dangerous command blocker. A PreToolUse hook on Bash matching risky patterns:

.claude/hooks/block-dangerous.sh
#!/usr/bin/env bash
cmd=$(jq -r '.tool_input.command // ""')
case "$cmd" in
*"rm -rf /"*|*"rm -rf ~"*|*"git push --force"*|*"DROP TABLE"*)
echo "Blocked: command matches dangerous pattern"
exit 2
;;
esac
exit 0

Install by declaring it under PreToolUse with matcher: "Bash".

2. Auto-formatter on PostToolUse Edit. Runs Prettier, Black, gofmt — whatever your repo uses — on any file Claude just edited:

.claude/hooks/auto-format.sh
#!/usr/bin/env bash
file=$(jq -r '.tool_input.file_path // ""')
case "$file" in
*.ts|*.tsx|*.js|*.jsx) npx --no-install prettier --write "$file" 2>/dev/null ;;
*.py) black --quiet "$file" 2>/dev/null ;;
*.go) gofmt -w "$file" ;;
esac

The agent never has to remember your formatting rules. They happen automatically.

3. Slack notifier on long-running session Stop. For async agent runs where you’re not watching live:

.claude/hooks/notify-slack.sh
#!/usr/bin/env bash
duration=$(jq -r '.session_duration_ms // 0')
if [ "$duration" -gt 300000 ]; then
summary=$(jq -r '.summary // "Session complete"')
curl -sX POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "{\"text\":\"Claude Code: $summary\"}"
fi

Fires only on sessions longer than five minutes, so you’re not spammed on quick runs.

4. Token budget tracker. A PreToolUse inspection hook that warns when a session has burned more than you expected:

.claude/hooks/budget-warn.sh
#!/usr/bin/env bash
tokens=$(jq -r '.session_tokens_used // 0')
if [ "$tokens" -gt 150000 ]; then
echo "Warning: session has used $tokens tokens (limit 200k)" >&2
fi
exit 0

Non-blocking (exit 0), but the warning shows up in the terminal — a good nudge to /compact or wrap the session up.

Wire all four into .claude/settings.json and commit it. Every team member gets the same safeguards the day they clone the repo.

Writing Your Own Hook

A hook is a script that reads JSON from stdin and returns an exit code. That’s the whole API.

Environment variables your hook receives:

Claude Code injects a handful of environment variables into every hook invocation, so your script can branch on context without parsing stdin:

  • CLAUDE_SESSION_ID — unique per session, useful for log correlation.
  • CLAUDE_WORKING_DIR — the project root Claude was invoked in.
  • CLAUDE_EVENT — the hook event name (PreToolUse, PostToolUse, Stop).
  • CLAUDE_TOOL_NAME — the tool being invoked (Bash, Edit, etc.), empty for Stop.

Exit code semantics:

Exit codeMeaningWhat happens
0AllowTool call proceeds; stdout ignored
2BlockTool call cancelled; stdout becomes Claude’s error message
Other non-zeroHook errorSession continues; logged as hook failure

Use 2 for policy decisions (the agent tried to do something disallowed). Use other non-zero only for bugs in the hook itself.

Stdout behavior. On exit 0, stdout is discarded. On exit 2, stdout becomes the visible reason Claude sees. Don’t use stdout for logging — the agent can see it, which can confuse later turns. For logging, write to a file or to stderr.

Testing hooks. Run them directly with a sample payload piped in. No Claude Code needed:

Terminal window
echo '{"tool_input":{"command":"rm -rf /"}}' | .claude/hooks/block-dangerous.sh
# → prints "Blocked: ..." and exits 2

A ten-line test harness in your test/hooks/ directory catches 90% of hook bugs before they fire on a real session. Worth the investment.

That’s enough to build your first hook. From here, the complete hooks guide covers the extended event catalog, alternate handler types (AI handlers, HTTP webhooks), and multi-language examples.


Subagents & Orchestration

Subagents are the feature most devs underuse. They’re not “parallel Claude’s” — they’re isolated sessions your main agent spawns for a focused subtask and then absorbs the summary back from. Once you internalize that mental model, a whole class of large-scale tasks becomes tractable.

What Subagents Actually Are

A subagent is a second Claude Code session that your main agent spawns with a specific task and narrow tool access. It runs in isolation — its own context window, its own tools, its own hooks. When it finishes, it returns a summary. Only the summary comes back to the parent; the subagent’s turn-by-turn history is discarded.

This matters for three reasons:

  • Context preservation. The main agent’s 200k-token window isn’t consumed by the subagent’s work. You could read fifty files in a subagent and only the fifteen-word summary lands back in the parent.
  • Task isolation. The subagent can’t accidentally touch files outside its scope if you restrict its tool set. Pair a subagent with permissions.deny: ["Edit", "Write"] and you have a read-only researcher that literally cannot mutate your repo.
  • Parallelism. Multiple subagents can run concurrently. If three files need to be deeply analyzed, you spawn three subagents, wait for all three summaries, and decide what to do. Real wall-clock parallelism, not just concurrent tool calls inside one session.

The classic use case: reviewing a fifty-file PR. The main agent reads the PR description and the diff summary, then spawns one subagent per file with a focused prompt (“review this file against our CLAUDE.md conventions, report issues”). Each subagent works with clean context on its one file. The main agent receives fifteen summaries and synthesizes them into a final review comment.

Try doing that in a single-agent loop and you’ll watch the token counter spiral past 200k by file twelve.

Built-in Subagents

Claude Code ships with three subagent types you can invoke by name:

SubagentPurposeTool access
ExploreFast, parallelizable codebase searchRead, Grep, Glob
PlanArchitecture-first planning modeRead, Grep, Glob, planning-model
AgentGeneric subagent — full tool setAll (configurable)

Explore is the one you’ll reach for most. “Find all call sites of authenticate() and report their context” is a perfect Explore task: no mutation, parallelizable, summary-friendly. The main agent sees the aggregated result without paying the per-file Read cost.

Plan runs the planning phase of a task as its own subagent. Useful when the plan itself is expensive to derive — e.g., “design the data model for multi-tenancy given our current schema.” The planner thinks in isolation, returns a structured plan, and the main agent executes against it.

Agent is the catch-all. When you need a subagent with a specific mix of tools for a specific task — say, “run the test suite, analyze any failures, report root cause” — Agent is what you reach for. You can pin its model, its tool set, and its prompt.

The Orchestration Pattern — Pillar → Cluster

The single most effective agentic workflow I’ve found is what I call the pillar-cluster pattern, borrowed from content SEO:

  1. Main agent holds the pillar. It maintains the high-level task, the plan, and the accumulated findings. It never reads raw source files if a subagent can do it better.
  2. Subagents handle clusters. Each narrow question becomes a subagent with read-only tools and a focused prompt. They return summaries, not raw content.
  3. Synthesis stays in the pillar. The main agent reads the returned summaries, decides what to do, and maybe spawns a new cluster or proceeds to execution.

A concrete workflow for a large refactor:

# Main agent prompt
"Migrate the user-preferences module from class-validator to zod.
Step 1: Spawn three Explore subagents in parallel.
- Subagent A: list every file that imports class-validator
- Subagent B: list every file that defines a UserPreferencesDTO or variant
- Subagent C: find the API contract for /preferences endpoints
Step 2: Synthesize the three reports. Produce a migration plan with
per-file tasks and risk flags.
Step 3: Execute the migration one file at a time, running tests after
each change. Commit after every green test run."

The key move is Step 1’s parallelism. Three Explores running concurrently finish in roughly the time of one. The main agent synthesizes three concise reports, not three thousand lines of source. By the time execution starts in Step 3, the agent knows exactly what it’s touching.

This is the pattern that made the 50,000-line legacy Kotlin refactor tractable in three weeks instead of two months. The main agent never loaded a full file into its own context; it orchestrated a rotating team of Explores and executed only after a plan was in hand.

Once you start thinking in pillar-cluster, you stop writing prompts like “do the whole refactor” and start writing prompts like “plan the refactor by spawning three Explores, then execute per-file.” Output quality on large tasks improves noticeably.

Pitfalls

Three failure modes to watch:

  • Subagent amnesia. Subagents see only what you pass them. They don’t inherit your CLAUDE.md, your open files, or your previous turns. If a subagent needs the repo’s coding conventions, pass them explicitly in the prompt or via a hook. Forgetting this is the number-one cause of “my subagent wrote code that doesn’t match the rest of the codebase.”
  • Token bloat from too many subagents. Each subagent loads its own system prompt and initial context, so spawning ten to parallelize ten files can cost more in aggregate than doing it sequentially. Rule of thumb: fewer than three independent subtasks, skip subagents and stay in the main loop.
  • Recovery from subagent failure. If a subagent crashes or times out, the main agent sees an error summary and must decide how to proceed. Design prompts to handle partial success — “summarize findings from completed subagents, flag the failed one, continue.”

Plugins & the Extension Story

Hooks and CLAUDE.md cover per-project customization. Plugins cover shareable customization — the patterns and tools you want across projects, or want to publish for other teams. They’re what makes Claude Code an ecosystem instead of a tool.

What Plugins Do

A plugin is a bundle of things you can reuse across projects. Inside a single plugin you can ship:

  • Skills. Named capabilities the agent invokes on demand (/skill blog-write, /skill migrate-sql).
  • Commands. Slash-commands that run a canned prompt or script (/review, /deploy-check).
  • Agents. Pre-configured subagent definitions with their own prompts, tool sets, and hooks.
  • Hooks. The PreToolUse/PostToolUse/Stop hooks from the previous section, now shareable.
  • MCP servers. Model Context Protocol servers that give Claude access to external systems (your database, your observability platform, your issue tracker).

The distinction from .claude/settings.json is about reach. Settings.json customizes one repo. A plugin is portable — install it once on your machine and every project sees it, or publish it to a marketplace and every team that uses Claude Code can install it with one command.

Plugins are how you stop re-implementing the same five hooks and slash-commands on every new project. Build the bundle once, /plugin install shipwithai/claude-essentials, and you’re done. They’re also how the broader ecosystem compounds: the Jira integration one team builds becomes installable by every other team on Jira.

Plugin Anatomy

A plugin is a directory with a specific layout:

my-plugin/
├── plugin.json # manifest: name, version, description, author
├── skills/
│ ├── write-blog-post/
│ │ ├── SKILL.md # skill description + invocation instructions
│ │ └── templates/ # optional: support files the skill uses
│ └── migrate-sql/
│ └── SKILL.md
├── commands/
│ ├── review.md # slash-command: /review
│ └── deploy-check.md # slash-command: /deploy-check
├── agents/
│ └── reviewer.json # subagent definition
├── hooks/
│ └── pre-bash.sh # hook script
└── mcp/
└── jira-server.json # MCP server config

The plugin.json manifest is the entry point:

{
"name": "@shipwithai/essentials",
"version": "1.2.0",
"description": "The hooks, skills, and commands we use on every Claude Code project",
"author": "ShipWithAI",
"repository": "https://github.com/ShipWithAI/claude-essentials",
"skills": ["write-blog-post", "migrate-sql"],
"commands": ["review", "deploy-check"],
"hooks": { "PreToolUse": ["./hooks/pre-bash.sh"] }
}

Each skill is its own folder with a SKILL.md that describes what the skill does, when Claude should invoke it, and any required arguments. Skills are lazy-loaded — their contents only hit the context window when the skill fires, so a plugin can ship dozens without paying the token cost upfront.

Commands are simpler: a markdown file with YAML frontmatter (name, description, optional tool restrictions) and a body containing the prompt template. /review on a PR spawns a Claude turn with the body as the initial message.

Agents and hooks follow the patterns from earlier sections. MCP servers are declared via a JSON config pointing at a runnable binary or HTTP endpoint — we’ve covered the setup separately in the MCP server guide.

How to Install + Discover Plugins

Installation is a one-liner:

Terminal window
/plugin install @shipwithai/essentials
# or from GitHub directly
/plugin install github:user/repo-name
# or from a local directory during development
/plugin install ./my-plugin/

Plugins live either on your machine (~/.claude/plugins/) or pinned per-project (.claude/plugins/ and referenced in settings). Global gives you ambient capabilities everywhere; project install locks the team to a specific version for reproducibility.

Discovery has three main channels:

  • Official marketplace. Anthropic’s curated list at the Claude Code docs portal — limited but vetted.
  • Community marketplaces. Third-party aggregators (ShipWithAI’s toolkit being one; there are others) that catalog community plugins with ratings and verified install counts.
  • GitHub search. Search topic:claude-code-plugin on GitHub for the long tail. Noisier, but wider.

Trust model. Installing a plugin is installing code that runs inside your Claude Code session with whatever permissions you grant. Read the source before install — at minimum plugin.json, the hook scripts, and any binaries referenced by MCP configs. If the author is anonymous and the repo has three stars, don’t run their auto-formatter on your client’s codebase. For a step-by-step walkthrough including auditing and publishing, the plugin install guide has the practical deep-dive.

When to Build vs Install

A decision tree:

  • Install when: the need is generic (Slack notifier, auto-formatter, git commit linter), a credible plugin already exists, and you’re willing to read its code. Don’t reinvent.
  • Build when: the need is team-specific (your internal API client, your deployment script, your in-house style guide) or no equivalent plugin exists.

Red flags before installing:

  • Plugin author not verifiable (no GitHub history, no personal website).
  • Plugin requests broad MCP permissions without explaining why.
  • Hook scripts with obfuscated code or curl | sh patterns.
  • Last commit older than six months when Claude Code has had major API updates since.

Building your own takes an afternoon for a simple plugin (a few commands + a hook) to a week for something with MCP servers. The ROI kicks in on the second project you install it on.


Production Patterns

Four patterns I’ve watched pay back their setup cost within a month. They’re not the only ways to use Claude Code in production, but they’re the ones where the ROI is obvious and measurable.

The CI Companion Pattern

The CI companion is a Claude Code instance that runs on every PR and leaves structured review comments. You’ve probably seen the shape — Codex reviews, Copilot review, Aider-CI. The pattern is identical; the implementation is a GitHub Action:

.github/workflows/claude-review.yml
- name: Claude Code review
run: |
claude -p "Review the diff in this PR. Check null safety, security,
and conventions from CLAUDE.md. Post inline comments via gh api."
env:
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}

Three discipline rules make this pattern not-annoying:

  • Tests must pass first. Run npm test before the review turn. A review of broken code wastes everyone’s time and generates noise.
  • Scope the diff. Review the PR diff only, not the whole repo. That keeps context small and comments actionable.
  • Hard cost ceiling. Set CLAUDE_MAX_TOKENS_PER_SESSION to 50k per PR. A renegade session that burns 200k on a one-file change shows up on the bill eventually.

A production setup I’ve seen: Claude Code review runs in parallel with the test job, posts comments within ninety seconds of PR open, and auto-dismisses its own comments when the code changes. The code review workflow post walks through the full Action and prompt template.

The Pair-Programming Pattern

Two Claude Code sessions, one terminal window each, running in parallel. One is your “planner” — Opus model, plan-only mode, no tool mutations. The other is your “executor” — Sonnet, full tool access, acting on the plan.

The workflow:

  1. Describe the task to the planner. It returns a step-by-step plan with file-level detail.
  2. Read the plan. Edit it if you disagree — “skip step 3, that migration is already applied.”
  3. Paste the edited plan to the executor. It runs it.
  4. Review the diff. Commit. If something’s wrong, go back to step 1 with a correction.

The separation sounds like overhead but pays back immediately. The planner thinks cleanly without the noise of execution; the executor acts without thrashing on re-planning. Because the plan is a legible artifact, you can save it, reuse it, share it on Slack. The third time you do a similar migration, you’ve got a template.

Version control discipline: always commit before you run the executor, and commit again after. You want a clean “before” snapshot to diff against and an explicit “after” to point at when reviewing. No long-lived dirty working trees during agent runs.

The Maintainer-at-Rest Pattern

Claude Code doesn’t just work on the task in front of you. It also does the boring stuff no one wants to do — but someone has to — on a schedule.

Candidates for scheduled maintenance:

  • Dependency updates. Weekly: “update all non-major deps, run tests, open a PR if green.”
  • Doc refreshes. Monthly: “re-read the README against the current code, flag anything stale, open a PR with fixes.”
  • Link checkers. Weekly: “verify every internal link in the docs folder still resolves.”
  • Dead code sweep. Quarterly: “find exports that have zero imports, propose removals.”
  • Changelog drafts. On release tag: “summarize commits since the last tag into a CHANGELOG entry.”

Wire any of these into a GitHub Action triggered on schedule. The session runs headless, opens a PR, a human reviews before merge. The human is the safety check; Claude handles the labor.

Observability matters. Every scheduled run logs its session to a bucket or database — token count, duration, outcome. When a recurring job starts getting expensive or failing consistently, you want to know before it’s been burning cash for a month.

Team Rollout — The First 30 Days

Rolling Claude Code out to a team is a four-week sprint, not a single announcement. Here’s the plan I’ve seen work at teams of five to fifty:

Week 1 — Experimenters. Pick two senior developers who are curious. Give them Claude Code licenses, the default settings, and a mandate: use it on their real work for a week, document the three workflows that paid off, document the two that wasted time. No pressure to ship anything new — the deliverable is a one-page learning report. Result: you have internal proof (or disproof) of the ROI, specific to your codebase and stack. Far more persuasive than a vendor deck.

Week 2 — Team CLAUDE.md sprint. A half-day workshop. The whole team drafts the repo’s CLAUDE.md together: coding conventions, architectural decisions, taboo patterns, build commands. The goal is consensus; the byproduct is onboarding documentation that also works for new humans. Commit the CLAUDE.md. Ship a small internal playbook derived from Week 1’s findings. Brief the rest of the team on what’s coming.

Week 3 — Pilot on one product area. Pick a single area (one service, one page, one internal tool) and make Claude Code the default for changes there. Everyone on that area uses it; everyone outside continues as normal. Two weeks of concentrated use in bounded scope produces far better feedback than diffuse trial across the whole team. Collect friction points. Log what hooks the team writes organically. Note which workflows get repeated — those are your plugin candidates.

Week 4 — Hooks and plugins standardization. Take the recurring patterns from Week 3 and codify them. Build an internal plugin (or at minimum a shared .claude/settings.json template) with the team’s essential hooks, commands, and agent configs. Pin model versions. Write the settings cascade down to the version that runs in CI.

By end of Week 4, onboarding a new hire takes an hour: install Claude Code, clone the repo, /plugin install @yourteam/claude-essentials, read CLAUDE.md. Week 1 is the test; Week 4 is the standardization. This whole sequence is an instance of the broader principle we call harness engineering for Claude Code — build the system around the model, not just the prompts. Once you’ve felt the difference, the full 5-layer harness setup guide walks through each layer with file paths and the non-sequential setup order we use (1→4→2→3→5: guardrails before capabilities).


Troubleshooting & FAQ

Eighteen months of daily use surfaces the same three or four failure modes on every team. Here are the ones worth naming, plus the decision matrix I use when teammates ask whether Claude Code is even the right tool for their job.

Hallucinated file paths and imports

Symptom: Claude writes an import for @/components/Button — file doesn’t exist. Or edits src/utils/config.ts — also doesn’t exist. The session looks productive, but half the generated code references paths that were never there. This is the single most common complaint on new repos.

Root cause: Claude is pattern-matching against codebases it’s seen in training, not the one in front of it. When CLAUDE.md is thin, when directory structure is unusual, or when the task description is vague, the model fills the gap with priors.

Fix: (1) CLAUDE.md must name the top-level directories and what lives in each. Two sentences per directory is enough. (2) Run /init in the repo once to generate a baseline CLAUDE.md, then edit. (3) When a session starts drifting, interrupt and say “re-read the actual file tree before continuing” — that single nudge usually fixes it. (4) Add a PostToolUse hook that runs tsc --noEmit after every Edit. Bad imports fail fast instead of propagating.

Sessions eat all my tokens

Symptom: A single “refactor this function” session burns $15 of tokens and the task still isn’t done. You look at the session log — Claude read forty files, half of which had nothing to do with the change.

Root cause: Claude re-reads context aggressively. Without scoping, it will Grep the whole repo on every uncertain step. Long-running agent loops compound this.

Fix: (1) Scope the prompt. Instead of “refactor auth”, say “refactor src/auth/session.ts — don’t touch other files”. (2) Use /clear between unrelated tasks so context doesn’t accumulate. (3) Set a maxTurns budget via CLI flag or hook — kill the session if it exceeds, say, 30 turns. (4) For legacy codebases, build a one-page architecture summary in CLAUDE.md so Claude doesn’t have to re-discover the layout every session. More on token discipline in our deep dive on sessions and budgets.

My hooks aren’t firing

Symptom: You wrote a PreToolUse hook to block rm -rf, tested it once, moved on. Three weeks later a teammate runs rm -rf node_modules and the hook never triggers.

Root cause: Four usual suspects. (1) Hook file isn’t executable (chmod +x). (2) The matcher regex is too strict — you wrote ^rm -rf but the actual command was sudo rm -rf. (3) The hook is in .claude/settings.local.json on your machine only, never committed. (4) Claude Code picks settings from the repo, the user’s home dir, and the enterprise policy — a more-specific file silently overrode yours.

Fix: (1) Run claude --debug hooks to see which hooks are loaded and from where. (2) Log every invocation to a file while developing the hook — zero log lines means the matcher never fired. (3) Commit hooks to .claude/settings.json (not .local.json) so the whole team gets them. Full debugging walk-through in the hooks guide.

Claude Code vs Cursor vs Aider vs Copilot — decision matrix

The question I get most from team leads: “we already have Cursor — do we need Claude Code?” Short answer: they’re different tools solving overlapping problems.

Use caseBest toolWhy
In-editor autocomplete and chatCursor or CopilotIDE-first UX, instant suggestions
Terminal-driven multi-file editsClaude CodeAgent loop, tool use, hooks
Git-native diff-based refactorsAiderCommits each change, small-surface
CI automation and scheduled jobsClaude CodeHeadless mode, GitHub Action
Pair-programming on a single fileCursorLower latency, visual diff
50k-line legacy refactorClaude CodeSubagents, long sessions, hooks
Free tier for solo experimentationAider + local LLMZero vendor cost

The honest answer: most serious teams end up using two — Cursor for in-editor flow, Claude Code for terminal, CI, and anything involving more than three files at once. They share no state, but they don’t conflict either.

More questions

The FAQ block at the top of this guide covers the eight most-asked questions (what is Claude Code, is it free, model versions, hooks vs subagents, and more). If your question isn’t there, reply to the newsletter — we aggregate reader questions and update this section quarterly.


Where to Go Next

You’ve just read 8,000 words on Claude Code. Here’s how to make them count.

Recap of what we covered. Claude Code is an agent, not a chatbot — the whole mental model is different from Claude Chat. You install it once, configure it once via CLAUDE.md and .claude/settings.json, and from there the leverage comes from hooks (policy), subagents (parallelism), and plugins (sharing). Production-grade use means treating Claude like a teammate on CI: reproducible environments, audit logs, budgets, and human review gates before any commit reaches main.

Three concrete next steps, in order.

  1. Write your first CLAUDE.md today. Not tomorrow, not after reading more. Open your repo, run /init, edit the output so it reflects what your codebase actually is. Twenty minutes. This is the single highest-leverage action in the entire guide — every other trick multiplies off of it. If you need a template, our why CLAUDE.md matters post walks through a complete one with annotations.

  2. Add two hooks this week. One PreToolUse hook that blocks at least one genuinely risky Bash pattern for your stack (e.g. git push --force, DROP TABLE, rm -rf on anything outside /tmp). One PostToolUse hook that runs tsc --noEmit or equivalent after every Edit. That’s it. These two hooks prevent about eighty percent of the Claude-related incidents I see on real teams. Full reference in the hooks guide.

  3. Pick one legacy module and refactor it with Claude this month. Not a greenfield feature — a module everyone on the team dreads touching. Use the archeology workflow: read, map, refactor in small verifiable steps. The experience teaches you more about Claude Code’s real strengths and limits than a dozen demos. Step-by-step in Claude Code for legacy refactoring.

Stay in the loop. We update this guide every quarter as Claude Code evolves — new models, new tools, new failure modes. The easiest way to hear about updates, plus weekly deep dives we don’t publish on the blog, is the newsletter. No fluff, one email a week, unsubscribe whenever.

The agent is only as good as the harness you build around it. Now you have the harness.