Out of the box, Claude Code is already a capable pair programmer: it reads your files, runs your commands, and writes code. But a stock setup treats every repository the same way. It doesn’t know that you build in Release, that your solution file is off-limits, that “create a PR” means a very specific dance with your source-control host, or that your team has a hard rule about never committing to the integration branch.
The difference between Claude-as-autocomplete and Claude-as-coworker is configuration. And as of mid-2026 — the Opus 4.8 era — the surface area for that configuration is broad: layered memory, deterministic hooks, an open Agent Skills standard, a plugin marketplace, MCP servers, and first-class git worktrees.
This guide walks through each layer in the order you should build it, with generic, copy-pasteable examples plus notes on how we applied each one to a large .NET codebase (Clean Architecture, EF Core, CQRS, Azure DevOps for source control).
Docs moved. The canonical Claude Code documentation now lives at code.claude.com/docs/en (the old
docs.claude.com/en/docs/claude-code/*URLs 301-redirect there). All links in this post point at the new host.
The mental model: the harness has layers
Anthropic frames Claude Code’s extensibility as a small set of “extension points,” and the order in which you adopt them matters. Their guidance for large codebases lays them out roughly like this:
- CLAUDE.md — always-on context and instructions.
- Hooks — deterministic automation that fires every time, no exceptions.
- Skills — packaged, reusable expertise loaded only when relevant.
- Plugins — a way to bundle and distribute a working setup to a team.
- MCP servers — connections to your internal tools, data, and APIs.
- Subagents — isolated context windows for exploration or review.
Underneath all of them sits one constraint that explains nearly every best practice you’ll read:
“Claude’s context window fills up fast, and performance degrades as it fills.”
— Claude Code best practices
Read that as the thesis of this whole post. Every layer below is, at its core, a way to get the right context in front of the model at the right time — and to keep everything else out. A CLAUDE.md that tries to say everything ends up saying nothing; a skill that loads only when invoked costs you almost nothing until you need it. Keep “spend context deliberately” in mind and the design choices in each layer start to feel obvious.
Layer 1 — CLAUDE.md and memory
Start here, because it’s the cheapest, highest-leverage thing you can do. As of 2026 there are actually two memory systems, and it’s worth keeping them straight.
CLAUDE.md is written by you: instructions, rules, conventions — loaded every session. Auto memory is written by Claude: learnings and patterns it accumulates across sessions (since v2.1.59), stored under ~/.claude/projects/<project>/memory/ with a MEMORY.md index.
Both load at the start of a conversation. Crucially, Claude treats them as context, not enforced configuration — if you need something to happen no matter what the model decides, that’s a hook’s job (Layer 2), not a CLAUDE.md line.
Getting started
Run /init in your project to generate a starter CLAUDE.md, then prune it. The files load in a hierarchy, broadest to most specific:
| Scope | Location | Shared with |
|---|---|---|
| User | ~/.claude/CLAUDE.md | Just you, all projects |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | Team, via source control |
| Local | ./CLAUDE.local.md (gitignore it) | Just you, this project |
| Managed | OS-level policy path | Whole organization |
Claude walks up the directory tree from where you launched it and concatenates every CLAUDE.md it finds, so a file in a subdirectory only loads when Claude actually works in that subdirectory. That’s the key to keeping the root file lean: push specialised guidance down to where it’s relevant.
You can pull in other files with the @ import syntax (up to four hops deep), and a newer addition — .claude/rules/ — lets you scope rules to file globs via frontmatter, so they only enter context when Claude touches matching paths:
---
paths:
- "src/Api/**/*.cs"
- "src/**/*.cs"
---
# API development rules
- Every endpoint validates input with the shared FluentValidation validator.
- Never log request bodies; they may contain PII.
Writing one that works
The official litmus test is the best editing rule I know:
“Would removing this cause Claude to make mistakes? If not, cut it.”
Include the things Claude can’t infer: build commands and flags, test runners and how to filter them, code style that differs from the language default, branch/PR etiquette, and the genuinely non-obvious gotchas. Exclude anything derivable from the code, standard conventions, long API docs (link them instead), and file-by-file tours. Keep it under roughly 200 lines; Anthropic is blunt about the failure mode:
“Bloated CLAUDE.md files cause Claude to ignore your actual instructions!”
How we did it. On our .NET platform the root CLAUDE.md carries the things that bite you if you don’t know them: always build with the Release configuration so you don’t clobber a developer’s Debug lock files; always exclude integration tests (tagged with a category trait) from solution-wide runs; never push directly to the integration branch — branch and open a PR. Then each major area gets its own nested CLAUDE.md — the data/persistence layer documents EF Core migration mechanics, the test project documents conventions, the legacy web portal documents its on-prem hosting quirks. None of that belongs in the root file, because Claude only needs it when it’s actually editing those areas.
We also lean on auto memory for the cross-session “scar tissue”: confirmed root causes of tricky bugs, decisions that were dropped and why, the fact that a particular CLI is available on this machine despite first appearances. The MEMORY.md index keeps each of those to a one-line pointer so the startup cost stays tiny.
Layer 2 — Hooks as guardrails
CLAUDE.md is advice. Hooks are law. A hook is a shell command (or, newer, an HTTP call, a prompt, or an agent evaluation) that Claude Code runs at a defined point in the lifecycle — and some of those points can block what’s about to happen. Anthropic’s framing:
“Use hooks for actions that must happen every time with zero exceptions.”
The lifecycle has grown well past the original nine events; there are now around two dozen, including PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, SessionStart, Stop, SubagentStop, PreCompact, and worktree/config-change events. For guardrails, the one you’ll reach for most is PreToolUse, which fires before a tool runs and can deny it.
Hooks are configured in settings.json. A blocking hook either exits with code 2 (its stderr is fed back to Claude as the reason) or prints a structured decision on stdout. Here’s a generic guardrail that refuses edits to sensitive files:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-protected-files.sh",
"timeout": 5
}
]
}
]
}
}
…where the script inspects the tool input and exits non-zero for paths you want to protect. The newer JSON form is more expressive — you can return permissionDecision: "deny" with a reason, or even "ask" to force a prompt:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Solution and lock files are edited by hand only."
}
}
A nice touch: you don’t have to write these by hand. You can ask Claude to do it — “write a hook that runs dotnet format after every file edit,” or “block writes to the Migrations folder” — and it will generate and wire up the config. Browse what’s active with /hooks.
New in 2026. Beyond
command, hooks now supporthttp(call a service),prompt(have a model evaluate a condition and return a decision), andagent(delegate the check to a subagent). AStophook with apromptevaluator is a popular way to enforce “don’t end the turn until the tests pass.”
How we did it. Our single most valuable hook is a PreToolUse guard on Write|Edit that blocks edits to the solution file, the central package-management file (Directory.Packages.props), and lock files. These get regenerated or are deliberately hand-curated, and an over-eager edit there causes confusing build breakage. With the hook in place it simply can’t happen by accident — and because it’s deterministic, we don’t have to repeat the rule in prose and hope it sticks. That’s the whole point of the layer: the things that must never happen get enforced by code, not by reminders.
Layer 3 — Skills, slash commands and subagents
This layer saw the biggest change in the last year. Custom slash commands and Skills have merged. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create a /deploy command and behave the same way. Old command files still work, but Skills are now the recommended authoring model — and in late 2025 Agent Skills became an open standard (launched October 16, 2025; opened up December 18, 2025), the same way MCP did.
Anatomy of a skill
A skill is a directory with a SKILL.md entrypoint plus any supporting files. The frontmatter controls what it is and who can invoke it:
---
name: create-pr
description: Open a pull request with our standard template and checks.
argument-hint: "[target-branch]"
allowed-tools: Bash(git:*), Write
disable-model-invocation: false
---
Open a pull request for the current branch.
## Steps
1. Summarise the diff against $0.
2. Run the test suite and confirm it passes.
3. Create the PR with the team template.
Two things worth flagging for anyone with older muscle memory: argument indexing is now 0-based ($0 is the first argument, $1 the second), alongside $ARGUMENTS for the whole string; and you can inject live context with the !`command` syntax, which runs a shell command and substitutes its output before Claude ever sees the prompt.
Progressive disclosure — why this scales
At startup, only each skill’s name and description load into context (a small budget by default). The full body loads only when the skill is invoked, and any supporting files (reference.md, scripts) load only when Claude follows the links. So a 2,000-line reference document costs you almost nothing until the moment it’s needed. This is the same “spend context deliberately” principle from Layer 1, applied to expertise instead of rules.
Skills can be invoked two ways: explicitly by you (/create-pr) or automatically by Claude when your description matches the task. For side-effecting workflows you want to trigger yourself, set disable-model-invocation: true so Claude can’t fire them on its own.
Subagents — borrowed context
A subagent runs in its own context window with its own allowed tools and its own system prompt. They live in .claude/agents/ as markdown files with frontmatter:
---
name: query-auditor
description: Reviews data-access code for performance and correctness issues.
tools: Read, Glob, Grep, Bash
model: sonnet
---
You are a database-query reviewer. Inspect the changed data-access code
for N+1 patterns, missing async usage, and incorrect EF Core tracking behaviour.
Report findings with file and line references.
(Note: the tool that spawns subagents was renamed from Task to Agent in v2.1.63; Task still works as an alias.) The classic high-value pattern is the writer/reviewer split: let one session write, then have a fresh subagent review. A clean context isn’t biased toward the code it just produced, so it catches things the author misses.
How we did it. Our skills encode the rituals that are easy to get subtly wrong: opening a PR against a non-GitHub source-control host with the right CLI and template, kicking off a structured intake for new work, running a review pass with our conventions baked in. Each one restricts its tools via allowed-tools, so a documentation command can’t suddenly start running arbitrary shell. We also keep a dedicated subagent for auditing EF Core queries — a focused, read-mostly reviewer that we point at a branch diff before merge. Because it has its own context, it can read widely without polluting the main session.
Layer 4 — MCP servers
The Model Context Protocol is how Claude Code reaches outside your repository — into your cloud provider, your docs, a browser, your ticketing system. Adding a server is a one-liner; HTTP is the recommended transport for remote servers, and stdio for local ones:
# Remote HTTP server
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Local stdio server (flags before the name, then -- before the command)
claude mcp add --transport stdio --env API_KEY=xxx mytool -- npx -y my-mcp-server
Servers have three scopes: local (just this project, just you), project (committed to .mcp.json and shared with the team), and user (all your projects). A project .mcp.json supports environment-variable expansion, so you can share the wiring without sharing secrets:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${API_KEY}" }
}
}
}
Tool Search is on by default. To stop dozens of MCP tools from eating your context budget, Claude Code now defers them: only their names load up front, and a
ToolSearchmechanism pulls in full schemas on demand (it needs a Claude 4-class model). If you’ve noticed tools described as “deferred” or “still connecting” at session start, that’s this at work. You can exempt a server withalwaysLoad: trueif it really must be present immediately.
A word of caution that Anthropic itself raised when it launched the official plugin directory in May 2026: every server you add costs context and carries trust implications. Prefer vetted servers, and don’t run one you don’t actually use. The community version of this advice is blunt and correct: “the plugin you don’t add is the plugin you don’t have to debug.”
How we did it. We enable a small, deliberate set of servers via enabledMcpjsonServers: our local orchestration tool (so Claude can read live traces and logs from the running app), our cloud provider’s MCP server (resource lookups, diagnostics), and the official documentation server (so framework questions get grounded in current docs rather than the model’s training cut-off). Three servers, each earning its place. We resisted the urge to wire up everything that could connect — that’s just context tax and more surface to trust.
Layer 5 — Worktrees and parallel work
Once Claude is doing real work, you’ll want more than one task in flight without them stepping on each other. Git worktrees are now first-class. The headline is a single flag:
claude --worktree feature-auth # or: claude -w feature-auth
claude --worktree # auto-generates a name
claude --worktree "#1234" # branch from a PR
By default these land in .claude/worktrees/<name>/ on a dedicated branch, and clean ones are cleaned up automatically when you’re done. Two configuration points are worth knowing. .worktreeinclude is a project-root file (gitignore syntax) listing otherwise-untracked files to copy into every new worktree — this is how you get your appsettings.Development.json or local secrets into an isolated workspace without committing them. And worktree.baseRef in settings lets you choose whether worktrees branch from a fresh origin/HEAD or your current local HEAD.
You can also ask Claude to “work in a worktree” mid-session (it uses an EnterWorktree tool), and subagents can be given isolation: worktree so a fleet of them can edit files in parallel without conflict. The desktop app takes this further and spins up a worktree for every new session automatically.
How we did it. We standardised the worktree parent directory in a small project config so every isolated task lands in the same predictable place, and we keep a worktree per in-flight PR. The practical payoff: a long-running refactor can sit in one worktree while a quick bug-fix happens in another, and neither touches the main checkout. For larger features this beats juggling branches in a single working copy — there’s no “wait, what was I in the middle of” when you switch tasks.
What’s new in mid-2026 (and where this is heading)
If you set Claude Code aside for a few months, here’s what changed — and why it affects how you configure it.
Models: Opus 4.8, fast mode, and effort control
Claude Opus 4.8 shipped on May 28, 2026 as the flagship, posting a 69.2% score on SWE-Bench Pro at the same standard price as its predecessor. Alongside it, fast mode got roughly 2.5× faster and about three times cheaper than on previous models, and effort control (introduced as an API parameter with Opus 4.5 in November 2025) is now exposed across the consumer surfaces — you choose how much thinking to spend per task. The configuration takeaway: model and effort are now things you tune per session (--model, --effort, the /model command, and the model setting), not a single global pick.
Agents at scale: agent teams and dynamic workflows
Opus 4.6 (February 5, 2026) introduced agent teams — multiple agents splitting a task, each owning a piece and coordinating directly — and a 1M-token context window (beta). Then Opus 4.8 added dynamic workflows (research preview): Claude plans the work, fans out to hundreds of parallel subagents in one session, and verifies their output before reporting back. It’s aimed at things like migrations across hundreds of thousands of lines of code. The trigger keyword for that mode is now /ultracode (the word “workflow” no longer kicks one off on its own).
Surfaces: desktop redesign and Routines
On April 14, 2026 the Mac/Windows desktop app was rebuilt around multi-session work — a session sidebar, drag-and-drop panes, an integrated terminal and file editor, a side-chat for quick questions that never pollute your main context. Shipping alongside it: Routines (research preview), automations that run on Anthropic’s web infrastructure so scheduled tasks fire even with your laptop closed. And Claude Code on the web (since October 2025) runs async agents in isolated cloud sandboxes straight from the browser.
Distribution: an open standard and an official marketplace
Agent Skills becoming an open standard (December 2025) and the launch of the official plugin directory (claude-plugins-official, May 2026) mean the layers in this post are increasingly things you can install rather than hand-roll — official integrations for common SaaS tools, language-server plugins for symbol-level navigation, a security-guidance plugin that watches diffs in real time. Plugins bundle skills, commands, agents, hooks, and MCP servers into one installable unit, which is how teams now distribute a working setup instead of passing around tribal knowledge.
The throughline: the harness you build today scales up cleanly. A well-structured CLAUDE.md, a few sharp hooks, and a handful of skills are exactly what a single fast session, a 1M-context agent team, and an overnight Routine all draw on. Anthropic’s own org-level advice is to review your configuration every three to six months, because instructions tuned for today’s models can quietly constrain newer ones.
Your starter checklist
If you want to go from stock to tuned this week, do it in this order — each step is useful on its own, and later steps build on earlier ones:
- Run
/init, then ruthlessly prune the generated CLAUDE.md to things Claude can’t infer. Keep it under ~200 lines. Push area-specific guidance into nested CLAUDE.md files. - Add one
PreToolUsehook for the thing that must never happen in your repo (protected files, forbidden commands). Let Claude write it for you. - Turn your two most-repeated rituals into skills under
.claude/skills/, each with a tightdescriptionand a restrictiveallowed-tools. - Add a read-only review subagent in
.claude/agents/and use the writer/reviewer split before merging. - Enable only the MCP servers you’ll actually use; lean on Tool Search to keep the context cost down.
- Adopt
--worktreefor any task that’ll run longer than a coffee break, and add a.worktreeincludefor your local-only files. - Put a reminder on your calendar: in three to six months, re-read your CLAUDE.md and hooks against the current model and cut what’s no longer needed.
None of this is exotic. It’s the same move you’d make onboarding a sharp new colleague: write down the non-obvious rules, automate the things that must never go wrong, hand them the playbooks for your common tasks, and give them access to the systems they need. Do that, and Claude Code stops being autocomplete and starts being a coworker who already knows how your shop runs.
Sources
Official documentation — Best practices, Memory & CLAUDE.md, Hooks reference, Skills, Subagents, MCP, Worktrees, Settings, Plugins.
Anthropic announcements — Opus 4.8 (May 28, 2026), Opus 4.6 & agent teams (Feb 5, 2026), Opus 4.5 & effort (Nov 24, 2025), Agent Skills, Desktop redesign & Routines (Apr 14, 2026), Claude Code on the web (Oct 20, 2025), Sonnet 4.5, checkpoints & the Agent SDK (Sep 29, 2025).
Living references — How Claude Code works in large codebases (May 14, 2026); the official changelog for exact version numbers.
Verify version-specific details against the current changelog before relying on them — the CLI ships frequently and feature-to-version mappings drift.