TL;DR — Your Claude Code harness has 5 layers: Memory, Tools, Permissions, Hooks, Observability. Most developers only have Layer 1. Set them up in order 1, 4, 2, 3, 5: add guardrails before capabilities. Jump to the setup order →
📊 What this post maps out:
- 5 discrete layers with exact Claude Code file paths for each
- A non-sequential setup order (1→4→2→3→5) with reasoning
- A 10-item production-readiness checklist
- Code templates for permissions and observability
Two setups. Same project. Different outcomes:
# Layer 1 only (what most devs have)CLAUDE.md: "Never delete production database tables."→ LLM weighs this against 200K tokens of context. May ignore it.
# All 5 layers (production-ready)CLAUDE.md → agent knows the ruleHook → blocks "DROP TABLE" before execution (exit 2)Permission → denies write access to /prod/ pathsMCP → no database tool configured in productionLogs → alerts when destructive pattern detectedIf you deleted your CLAUDE.md right now, would your agent still work?
For most developers, the answer is no. The entire harness is one markdown file that the LLM treats as a suggestion, not a rule. That’s Layer 1 out of 5.
I introduced harness engineering in the pillar post. That post explained why the system around your agent matters more than the model. This post is the complete Claude Code harness setup guide. Five layers, each with real file paths, and a setup order that most people get backwards.
Why do you need 5 layers?
Because each layer solves a different failure mode, and no single layer covers all five. Memory solves forgetting. Tools solve capability gaps. Permissions solve overreach. Hooks solve enforcement. Observability solves blindness. Skip a layer and you leave a specific class of failures unaddressed.
LangChain proved this: +13.7 benchmark points from harness changes alone, same model (full breakdown in the pillar post). Their three improvements map directly to this model: context injection (Layer 1), self-verification loops (Layer 4), and compute allocation (Layer 4/5).
Here’s the complete map:
| Layer | Name | Failure It Solves | Claude Code File |
|---|---|---|---|
| 1 | Memory | Agent forgets your conventions | CLAUDE.md, MEMORY.md |
| 2 | Tools | Agent can’t reach external systems | MCP servers in settings.json |
| 3 | Permissions | Agent does things it shouldn’t | settings.json allow/deny |
| 4 | Hooks | Agent ignores instructions | PreToolUse/PostToolUse |
| 5 | Observability | You don’t know what happened | PostToolUse logging hooks |
Most developers live in Layer 1. Some have part of Layer 2. Production needs all five.
More compute doesn’t compensate for missing layers. LangChain’s max reasoning budget actually scored worse than their optimized harness setting, because timeouts from over-thinking killed performance (LangChain Blog, Feb 2026). Architecture beats compute.
Key insight: Each of LangChain’s three harness improvements maps to a specific layer: context injection improved Layer 1 (Memory), self-verification loops improved Layer 4 (Hooks), and compute allocation improved Layer 5 (Observability). No single layer explained the full +13.7 point gain. They needed all three (LangChain Blog, Feb 2026).
Layer 1: What does your agent always know? (Memory)
Layer 1 is persistent knowledge: everything the agent reads before writing a single line of code. In Claude Code, three files form the memory layer: CLAUDE.md for project rules, MEMORY.md for cross-session learnings, and .claude/commands/ for reusable workflows. This is the foundation every other layer builds on.
CLAUDE.md is the most important file. It holds your tech stack, naming conventions, testing requirements, and architectural constraints. Claude Code reads it automatically at session start. For a deep dive, see Why CLAUDE.md Is the Most Important File in Your Project.
MEMORY.md tracks what the agent learns across sessions: recent decisions, migration status, active work. Think of CLAUDE.md as the constitution and MEMORY.md as the changelog.
.claude/commands/ stores slash commands like /review or /deploy that encode repeatable workflows. Each is a markdown file with a prompt template.
A minimal CLAUDE.md covering the essentials:
## Tech Stack- TypeScript, Next.js 15, Prisma, PostgreSQL on Supabase
## Conventions- Use server actions for mutations, not API routes- Tests: Vitest unit, Playwright E2E. Min 80% coverage- Commits: conventional commits (feat:, fix:, chore:)
## Constraints- Never modify .env files directly- Never run migrations without explicit approval- All API responses use the Result<T> wrapper typeThe pitfall: CLAUDE.md bloat
More instructions don’t mean better compliance. An ETH Zurich study found that LLM-generated context files actually reduced task success by ~3% while increasing inference costs by over 20% (MarkTechPost, Feb 2026). HumanLayer keeps their CLAUDE.md under 60 lines for exactly this reason.
The practical rule: if an instruction applies to fewer than half your sessions, it doesn’t belong in CLAUDE.md. Move it to a .claude/commands/ file or a hook instead.
Key insight: Layer 1 alone caps your improvement at roughly 4%, even with perfectly written instructions (ETH Zurich study, Feb 2026). That’s why the 5-layer model exists. CLAUDE.md handles what the agent should know. Layers 2-5 handle what it can do, what it’s allowed to do, what it can’t break, and what you can see.
Layer 2: What can your agent do? (Tools)
Layer 2 extends what your agent interacts with beyond the local filesystem. Claude Code ships with built-in tools (Read, Write, Edit, Bash, Grep, Glob). MCP servers add external capabilities: GitHub for PR management, Brave Search for live documentation, Playwright for browser automation, databases, and more.
The concept is simple: without Layer 2, your agent lives inside your project directory. With it, the agent can check a GitHub PR, query your staging database, and search Stack Overflow, all without you copy-pasting between browser tabs.
I covered the top 5 MCP servers for daily development in the MCP setup guide. Rather than repeating that list here, the important Layer 2 question is: how many tools should you add?
The pitfall: tool overload
Every MCP server you add is another decision the agent must make on each turn. HumanLayer learned this the hard way. They used the Linear MCP server for months before realizing they only used a small subset of its tools. They replaced it with a lightweight CLI wrapper that provides context-efficient responses. Fewer tools, better focus.
| Tool Count | Effect | Recommendation |
|---|---|---|
| 0 (built-in only) | Limited to local files | Fine for solo projects |
| 2-3 MCP servers | Sweet spot for most teams | GitHub + Search + one domain tool |
| 5+ MCP servers | Agent spends tokens choosing | Audit regularly, remove unused |
The practical rule: only add tools the agent uses in most sessions. If you reach for a tool once a month, use it manually instead.
Key insight: HumanLayer found that too many MCP tools cause agent confusion. They replaced a full Linear MCP server with a small CLI wrapper providing context-efficient responses. Every tool you add is a decision the agent must make on each turn (HumanLayer Blog, 2026).
Layer 3: What is your agent allowed to do? (Permissions)
Layer 3 controls which tools, commands, and file paths Claude Code can use without prompting you for approval. It lives in settings.json, available at two levels: project (.claude/settings.json, checked into git) and user (~/.claude/settings.json, personal). Project settings apply to everyone on the team. For a broader overview of Claude Code’s component system, see Claude Code Components Explained.
The key pattern: allowlist over denylist. Start restrictive, then open specific paths. A denylist that tries to block every dangerous command will always miss edge cases. An allowlist that permits only known-safe operations is airtight by default.
A production-ready template:
{ "permissions": { "allow": [ "Read", "Edit", "Write", "Grep", "Glob", "Bash(npm run test*)", "Bash(npm run lint*)", "Bash(npm run build)", "Bash(git status)", "Bash(git diff*)", "Bash(git log*)", "mcp__github__get_pull_request", "mcp__github__list_pull_requests" ], "deny": [ "Bash(rm -rf *)", "Bash(git push --force*)", "Bash(git push -f*)", "Bash(*DROP TABLE*)", "Bash(*DROP DATABASE*)" ] }}MCP tool permissions follow the mcp__servername__toolname pattern. Use mcp__github__* to allow all tools from a server, or list specific tools for tighter control.
Two things to remember:
- Check project settings into git. Your entire team gets the same guardrails on clone. No “it works on my machine” for permissions.
- Permissions gate actions, they don’t prevent them. A denied action prompts the user for override. For actions that must never happen, you need Layer 4 (Hooks), which blocks execution entirely.
Key insight: Claude Code permissions gate actions but don’t prevent them absolutely. A denied tool prompts for user override. For hard enforcement that cannot be bypassed, you need Layer 4 (Hooks) with exit code 2, which blocks execution before the permission check runs (Claude Code docs).
Layer 4: What can your agent never break? (Hooks)
Layer 4 is deterministic enforcement. Unlike CLAUDE.md (a suggestion the model weighs against context), and unlike permissions (a gate the user can override), hooks run shell scripts at lifecycle points that cannot be bypassed. A PreToolUse hook that exits with code 2 blocks the action before it happens. No override. No “are you sure?” prompt.
Claude Code hooks have two critical events: PreToolUse (runs before a tool executes, can block it) and PostToolUse (runs after execution, can log, lint, or inject feedback). For the full decision framework on all 21 events and 4 handler types, see the Hook Decision Guide.
Hooks fall into three categories:
Guardrails block dangerous actions. Force pushes, rm -rf on project roots, DROP TABLE in production. These are PreToolUse command hooks that run in under 5ms.
Quality gates enforce standards after changes. Auto-lint on file save, run type checks after edits, validate test coverage. These are PostToolUse hooks.
Context injection adds project-specific information to tool calls. Inject environment variables, append relevant docs, or tag actions with metadata. These are PreToolUse hooks that modify input rather than blocking it.
The 3-line guardrail you saw in the opening:
#!/bin/bash# PreToolUse hook: block destructive SQLCOMMAND=$(jq -r '.tool_input.command // empty' < /dev/stdin)if echo "$COMMAND" | grep -qiE 'DROP\s+(TABLE|DATABASE)'; then echo "BLOCKED: destructive SQL command" >&2 exit 2fiexit 0Boris Cherny, creator of Claude Code, considers verification the single most important factor for agent quality. Hooks are that verification layer, built directly into the agent’s lifecycle. Every PreToolUse check and every PostToolUse log runs automatically, not at the model’s discretion (full quote in the pillar post).
The pitfall: slow hooks
Every hook runs synchronously in the agent loop. A hook that calls an external API blocks the entire session until it returns. Keep command hooks under 100ms. If you need external validation, use the http handler type, which runs asynchronously.
For more hook patterns, see the Claude Code Hooks guide and the supply chain security hooks post.
Key insight: Hooks are the verification layer that Boris Cherny calls the most important factor for Claude Code quality. PreToolUse checks prevent bad actions before execution. PostToolUse hooks verify results after. Both run deterministically outside the model’s reasoning chain (pillar post).
Want the complete .claude/ folder, pre-configured with all 5 layers? Join the waitlist. You’ll be the first to get the template repo when it ships. Join the .claude/ Template Waitlist →
Layer 5: Do you know what your agent is doing? (Observability)
Layer 5 answers three questions: what did the agent do, how much did it cost, and did anything go wrong? Without observability, you’re flying blind. You find out about problems when the invoice arrives or when production breaks. Neither is a good feedback loop.
Agent observability has three pillars:
Decision logging. A PostToolUse hook that writes JSON for every tool call: which tool, what input, what output, timestamp, session ID. This is your audit trail.
#!/bin/bash# PostToolUse hook: log every tool call as JSONINPUT=$(cat)TOOL=$(echo "$INPUT" | jq -r '.tool_name')TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")SESSION=${CLAUDE_SESSION_ID:-"unknown"}
echo "$INPUT" | jq -c \ --arg ts "$TIMESTAMP" \ --arg sid "$SESSION" \ '{timestamp: $ts, session: $sid, tool: .tool_name, input: .tool_input, duration_ms: .duration_ms}' \ >> .claude/logs/tool-calls.jsonl
exit 0Cost tracking. Monitor per-session and per-task costs. A task that normally costs $2-3 suddenly costing $47 is your anomaly signal. It usually means an infinite loop, a context explosion, or the agent pursuing a dead-end approach. For detailed cost strategies, see How I Cut My Claude Code Bill by 60%.
Anomaly detection. Cost spikes, unusually long sessions, repeated tool failures. Start simple: review .claude/logs/ after each session. Graduate to automated alerts when patterns emerge.
HumanLayer’s hard-learned lesson applies here: when they ran the full test suite after every change, 4,000 lines of passing tests flooded the context window and the agent lost track of the actual task. Now they swallow success output and only surface failures. The same principle applies to observability. Log everything, but only alert on anomalies.
This is the newest and least mature layer across the industry. Most teams start with cost logging and add decision recording later. That’s fine. Any observability beats none.
Key insight: HumanLayer found that running the full test suite after every change flooded the context with 4,000 lines of passing tests, causing the agent to lose track of its task. They switched to surfacing only failures. The same principle applies to observability: log everything, alert only on anomalies (HumanLayer Blog, 2026).
How do you set up a complete Claude Code harness?
Here’s the full file tree for a production-ready Claude Code harness covering all 5 layers. Every file maps to a specific layer:
project-root/├── CLAUDE.md # Layer 1: Memory (project rules)├── MEMORY.md # Layer 1: Memory (cross-session state)├── .claude/│ ├── settings.json # Layer 3: Permissions + Layer 4: Hooks│ ├── settings.local.json # Layer 3: Personal overrides (gitignored)│ ├── commands/ # Layer 1: Memory (reusable workflows)│ │ ├── review.md│ │ └── deploy.md│ └── logs/ # Layer 5: Observability output│ └── tool-calls.jsonl│# Layer 2: MCP servers → configured in settings.json "mcpServers" block# Layer 4: Hooks → configured in settings.json "hooks" block# Layer 5: Logging hook → writes to .claude/logs/The recommended setup order
Don’t set these up 1, 2, 3, 4, 5. Set them up 1, 4, 2, 3, 5.
| Order | Layer | Why This Position |
|---|---|---|
| 1st | Memory | Foundation. Agent needs to know the project first. |
| 2nd | Hooks | Safety guardrails BEFORE giving the agent more power. |
| 3rd | Tools | Now extend capabilities with MCP servers. |
| 4th | Permissions | Lock down what the new tools can do. |
| 5th | Observability | Monitor everything that’s now running. |
The reasoning: add guardrails before capabilities. Most people do it backwards. They install 5 MCP servers, give the agent access to their production database, then wonder why it ran a destructive query. Layer 4 (Hooks) should be in place before Layer 2 (Tools) gives the agent more reach.
Is your harness production-ready?
Score yourself against this checklist:
- CLAUDE.md under 60 lines with project-specific rules
- MEMORY.md tracking cross-session learnings
- At least 2 custom commands in .claude/commands/
- PreToolUse hook blocking destructive commands
- PostToolUse hook for quality gates (lint, test)
- MCP servers for your top 3 daily tools
- settings.json with explicit allowlist (not just defaults)
- Project-level settings.json checked into git
- PostToolUse logging hook writing JSON
- Cost alerting for sessions exceeding your threshold
8-10 checked: production-ready. You’re doing harness engineering. 4-7 checked: solid foundation. Prioritize hooks (Layer 4) next. 1-3 checked: you’re in the majority. Start with the setup order above.
For the conceptual framework behind all of this, read Harness Engineering: The System Around AI Matters More Than AI.
Try it now: Pick the lowest-numbered unchecked item from the checklist above. Implement it before your next Claude Code session. If you’re at zero, start with CLAUDE.md (10 minutes). If you already have CLAUDE.md, add a PreToolUse guardrail hook (15 minutes, copy-paste from Layer 4 above).
Building your harness layer by layer? Get weekly Claude Code tips with real configs, not theory. Subscribe to AI Developer Weekly →
FAQ
Which layer of a Claude Code harness should you start with?
Start with Layer 1 (Memory/CLAUDE.md), then jump to Layer 4 (Hooks) for safety guardrails before expanding capabilities. The recommended order is 1→4→2→3→5. Add guardrails before capabilities. This is counterintuitive but prevents the most common failure: giving the agent powerful tools before you have enforcement in place.
Does a harness slow down Claude Code?
No. Command hooks add under 5ms per tool call. Permissions are evaluated in memory with no network call. The only performance consideration is MCP servers, where each adds a connection. Install only what you use daily and the overhead is negligible. LangChain actually found that more compute (xhigh reasoning) scored worse than targeted harness optimization (LangChain Blog, Feb 2026).
What are the most important Claude Code hooks to implement first?
Three hooks cover 80% of production safety needs: (1) a PreToolUse command hook blocking destructive bash commands like rm -rf, git push --force, and DROP TABLE; (2) a PostToolUse hook for auto-linting changed files; (3) a PostToolUse hook for JSON logging every tool call. For the full decision framework across all 21 events and 4 handler types, see the Hook Decision Guide.
How many MCP servers should you install for Claude Code?
Start with 2-3 that match your daily workflow. HumanLayer found that too many tools cause agent confusion, with the agent spending tokens deciding which tool to use instead of doing the work. GitHub, a search tool, and one domain-specific server cover most teams. For setup instructions, see the MCP setup guide.
What to Read Next
- Harness Engineering: The System Around AI Matters More Than AI. The pillar post that defines harness engineering, with the LangChain benchmark data and a self-assessment checklist.
- Which Claude Code Hook Do You Need? A Decision Guide. Layer 4 deep-dive: 4 handler types, 21 events, a decision tree, and which 3 hooks to implement first.
- Why CLAUDE.md Is the Most Important File in Your Project. Layer 1 deep-dive: how to write instructions Claude actually follows, with a 5-section template.