AI Development & Agents11 min readshipped

Claude Code Best Practices: Setup, Skills, Subagents, Hooks

Updated June 2026

I first wrote this in early 2025 as a summary of Anthropic's engineering tips. Since then Claude Code grew a real platform underneath it: skills, native subagents, hooks, plan mode, and a permissions model that actually matters. This is the rewrite, from running Claude Code in production for over a year, including inside a Fortune 500. The patterns that earn their place are the ones I still use daily; the ones that didn't, I cut.

The single biggest mistake people make with Claude Code is treating it like a faster autocomplete. It is a harness, a programmable agent that inherits your shell, reads your repo, and runs tools on your behalf.

Most of what follows is about that configuration. As you read, audit your own setup against it: tick the layers you already run, and the one with the most leverage left will surface itself.

Interactive · audit your harness0 / 6 layers

Tap the layers you actually run today.

Faster autocomplete

No configuration. You are typing prompts into a tool that could be running your harness.

Highest-leverage next move

Add CLAUDE.md

The file that pays back most. Build/test commands, where code lives, the traps, pulled into every session so Claude stops rediscovering them.

CLAUDE.md: your project's memory

A CLAUDE.md file is pulled into context automatically at the start of every session. It is the file that pays back the most, and the one people under-invest in. Put in it what Claude would otherwise rediscover every session: the build and test commands, where the important code lives, the conventions you actually enforce, the project-specific traps.

Claude Code reads CLAUDE.md from the repo root, any parent or child directory of where you launch, and your home folder (~/.claude/CLAUDE.md) for cross-project defaults. The newer cross-tool convention is AGENTS.md as the canonical filename with CLAUDE.md symlinked to it, so the same context file works across editors.1The AGENTS.md convention is recognized across Claude Code, Cursor, and other agentic editors. Keep CLAUDE.md as a symlink to it so tools that still look for the old name keep working. Nested files compose: a CLAUDE.md in a subdirectory layers on top of the root one when you work in that subtree.

Two shortcuts pay for themselves. Type /init once to generate a first draft from your codebase. While you work, prefix a message with # and Claude writes that instruction into the relevant CLAUDE.md for you, so the memory grows as you correct it. If you want a worked starting point instead of a blank file, I keep my production-tested CLAUDE.md files and rules open-source in slopless, and a longer write-up on the memory side in I Built a Personal Memory System for Claude.

The counterintuitive part

Bigger is not better. Every standing instruction spends attention on every turn, and a bloated memory file measurably degrades output.2Anthropic's own ablation work measured a small but real quality cost from each extra always-on instruction. The discipline is load-bearing, not cosmetic. Treat CLAUDE.md like a product: prune by relevance, push topic-specific detail into separate files you load on demand, and keep the always-on file short. A tight 40-line file beats a 400-line one.

Permissions: change these defaults first

By default Claude asks before any action that could change your system. That is the right floor, but the per-prompt approvals get tedious fast, and the fix is not to disable them blindly. Open .claude/settings.json (project) or ~/.claude/settings.json (global) and set a real permissions policy with allow, deny, and ask lists. Allowlist the read-only and obviously-safe commands you run constantly. Keep destructive ones (rm -rf, force-push, curl to arbitrary hosts) on deny or ask. Those rules now match tool parameters, not just tool names, so you can scope one to a specific argument, Agent(model:opus) or a deny on a particular command shape, instead of going all-or-nothing per tool.

Permission modes are the other lever. Press Shift+Tab to cycle between the default (ask), acceptEdits (auto-approve file edits, still prompt for shell), plan mode, and auto mode, where a classifier runs the safe actions and blocks the risky ones for you (it now refuses destructive git commands like git reset --hard when you didn't ask to throw work away). For genuinely untrusted code, /sandbox runs the session in an isolated environment. The realistic threat with a broad allowlist is not a fat-fingered command; it is an injected instruction from a web page or a repo file chaining an allowed command to do something you did not intend. A PreToolUse hook (below) is the deterministic backstop the allowlist alone does not give you.

Skills: the biggest addition since 2025

A skill is a folder under ~/.claude/skills/<name>/ with a SKILL.md file: frontmatter (a description that tells Claude when to fire it, plus a pinned model or agent) and a body of instructions. When a task matches the description, Claude loads the skill and follows it. You invoke one explicitly with /name, or Claude reaches for it on its own when the trigger matches.

Skills are how you stop re-explaining the same workflow. A deploy procedure, a house style for commit messages, a research-then-write pipeline, a status report that always pulls the same five sources: each becomes a skill you write once and trigger by name. I run more than fifty of them, and keep a sampling of the real ones (skills, rules, worked examples) public in rundatarun. The discipline that keeps them useful is the same as CLAUDE.md: progressive disclosure. Keep the always-loaded description short, put the heavy how-to in the body that loads only when the skill fires, and prune skills that stop earning their slot.

Dispatch-only pattern

For skills that send or post something (an email, a tweet, a deploy), keep the drafting in your main session and let the skill only dispatch the approved content. The skill should refuse to invent the message itself. That one rule keeps voice and judgment in the loop where they belong.

Subagents: parallelism without the terminal juggling

The old advice was to open three or four terminals and run a Claude in each. That still works, but it is now the manual version of something native. Claude Code can spawn subagents directly through its Task tool, and you can define reusable ones as ~/.claude/agents/*.md files, each with its own system prompt, tool access, and model.

Two patterns matter. First, fan-out: when a task means reading across many files or searching a codebase several ways, hand it to a parallel explorer agent and keep only the conclusion in your main context, not the raw file dumps. Launch several at once by putting multiple tool calls in a single turn and they run concurrently. Second, model selection per agent: cheap discovery and summarization go to a fast model, voice-sensitive writing and hard reasoning stay on the frontier model.3Pinning the model per agent is where a lot of the cost and speed control lives. A discovery sweep on a fast, cheap model and a final synthesis on the frontier model is a different bill from running everything on the frontier. Pinning the model per agent is where a lot of the cost and speed control lives.

As of mid-2026 subagents also nest: a subagent can spawn its own subagents, with background chains running up to five levels deep, so a parent can decompose a job and let each child fan out again. The flip side is cost, and /usage now breaks your plan limits down by skill, subagent, plugin, and MCP server, so when a run gets expensive you can see which agent actually spent it.

The judgment call is when not to delegate. With a large context window, reflexively forking everything is its own failure mode; reasoning-heavy work often belongs inline where you can see and steer each step. Fork for breadth (scan, discover, summarize), stay inline for depth. I went deeper on the routing logic and the when-to-delegate thresholds in Making Claude Code More Agentic.

Hooks: deterministic automation the model can't skip

Hooks are shell commands the harness runs at fixed points in a session, configured in settings.json. PreToolUse fires before a tool runs and can block it. PostToolUse fires after. SessionStart, UserPromptSubmit, and Stop cover the rest of the lifecycle. The key property is that the harness executes them, not the model, so they are reliable in a way a CLAUDE.md instruction never is. If you need something to happen every single time, it is a hook, not a request.

Real uses: a PreToolUse guard on Bash that blocks rm -rf and flags injected-looking commands, an auto-formatter on PostToolUse after every edit, a SessionStart hook that injects the current branch and recent context. A memory or preference can ask Claude to do something; only a hook guarantees it.

MCP: connect your own tools

The Model Context Protocol lets Claude Code talk to external tools and data: a database, an internal API, a search index, a browser driver. Add servers with claude mcp add --scope user|project|local <name> -- <command>, or --transport http for a hosted one. User scope makes a server available everywhere; a checked-in .mcp.json shares it with everyone working in the repo. For ones behind auth, claude mcp login authenticates a server straight from the shell instead of the interactive menu. Once connected, the server's tools appear alongside the built-ins. This is how you give Claude access to the systems your work actually lives in, instead of copy-pasting between them.

The core loop: explore, plan, code, commit

The workflow that holds up across almost every problem is still the same four beats, and the first two are the ones people skip:

  1. Explore. Have Claude read the relevant files, issues, or docs first. No edits yet.
  2. Plan. Ask for a plan before any code. Press Shift+Tab into plan mode and Claude works read-only, then hands you a plan to approve. For harder problems, raise the reasoning with /effort xhigh, or drop the word ultrathink into a single prompt for one deep turn.
  3. Code. Now let it implement against the agreed plan.
  4. Commit. Have it write the commit and open the PR.

Skip explore and plan and Claude jumps straight to code, which is exactly when it builds the wrong thing confidently. The other durable variants: test-driven (write failing tests, confirm they fail, then code until green) for anything verifiable, and visual-driven (give it a screenshot tool and a mock, let it iterate until they match) for UI.

Course-correct early

Press Escape to interrupt mid-action. Double-tap Escape to rewind the conversation to an earlier point and take a different path; /rewind does the same and can even reach back to before a /clear. Catching a wrong turn in the first thirty seconds beats letting it run and untangling the result.

Context discipline

A long session fills with stale file contents and dead ends, and quality drifts with it. Run /clear between unrelated tasks to reset. Use /compact to summarize a long thread down to what still matters when you want to keep going. Even with a million-token window on the higher plans, more context is not free: past a heavy fill, retrieval gets worse, not better.4The intuition that a bigger window means you can stop pruning is wrong. Past a heavy fill, the model retrieves the relevant detail less reliably, not more, so a focused working set beats a stuffed one even when you have the room. Keep the working set focused. Reference files precisely with @ and tab-completion so Claude reads the right thing instead of grepping the whole tree.

Headless mode and automation

claude -p "<prompt>" runs non-interactively, which is how Claude Code goes into CI, pre-commit hooks, and scheduled jobs. Add --output-format stream-json for machine-readable output. The Agent SDK wraps the same engine for building your own tools on top. This is the path from "I run Claude in my terminal" to "Claude runs as part of my pipeline": triage incoming issues and label them, review diffs for the things linters miss, regenerate docs on merge. The same harness, no human in the chair.

Dynamic workflows: many agents, with a referee

The most recent capability is orchestration. Claude can write a script that fans work out across parallel subagents and then runs adversarial verifiers before returning an answer, so a finding has to survive a skeptic before you see it. It is gated behind an opt-in setting because it can burn through tokens fast, with hard caps (sixteen agents at once, a backstop ceiling far above any real run). Reach for it on genuine fan-out work: a codebase audit, a framework migration, multi-attempt verification of an uncertain result. For everyday editing, one careful pass still beats fifty parallel guesses. The skill is knowing which task is which. I wrote up what shipping Opus 4.8 and dynamic workflows on the same day changed about the unit of work in One Careful Pass Is No Longer the Default.

Go deeper: the harness, in the open

Much of the year's work behind this is public, if you want worked examples instead of principles:

  • claudelicious: a full Claude Code cookbook, the why and the wiring behind an entire harness (skills, hooks, memory, agents). The direct companion to this article.
  • slopless: the production-tested CLAUDE.md files and rules I run to make Claude Code write better, more human code.
  • rundatarun: skills, rules, and worked examples pulled straight from production.
  • mneme: semantic search over your Claude Code session history, for when the answer is in a conversation you had three weeks ago.

And a few posts that go deeper on individual pieces:

Is Claude Code just a faster autocomplete?

No, and treating it like one is the most common way to underuse it. Autocomplete finishes the line you are typing. Claude Code is a harness that reads your repo, runs your tools, and acts across a whole task, so the leverage lives in what you configure once (the memory file, the skills, the hooks, the permissions) rather than in any single prompt. The people getting the least out of it are the ones who never move past the prompt box.

The takeaway

The teams getting the most out of Claude Code are not writing better prompts. They are building better harnesses: a tight memory file, a real permissions policy, a library of skills, a few hooks that enforce the non-negotiables, and the judgment to fork for breadth and stay inline for depth. The prompt is the cheap part. The configuration is the moat, and it compounds every day you invest in it.


  • Making Claude Code More Agentic: Subagents and Routing
  • Syncing Claude Code Config Across Machines (Mac, Pi, DGX)
  • Mastering .clinerules: Advanced Configuration for AI-Assisted Development
  • Pruning Your AI Agent Skills Library: A Practical Guide to Skill Consolidation

Follow the lab

Get the next experiment

Enjoyed the breakdown on Claude Code Best Practices: Setup, Skills, Subagents, Hooks? New entries land roughly weekly. No digest, no roundup. Just the next build log, when it ships.

Links to this entry