The Navigator · 18 min mission
Claude Code Harness Engineering and Configuration
Build a repo-specific Claude Code harness with instructions, permissions, hooks, skills, subagents, MCP, and verification.
On this page
This guide shows you how to turn Claude Code from a capable coding assistant into a repo-specific engineering harness with instructions, permissions, hooks, skills, subagents, MCP, and verification.
Who this is for
Use this if you already run Claude Code and want repeatable results across a real repository. The goal is not more prompting. The goal is a small operating layer around Claude Code that gives it the right context, blocks the wrong actions, routes repeated work into reusable tools, and proves the result before you trust it.
You need:
- Claude Code installed and authenticated.
- Permission to add or edit
CLAUDE.md,.claude/settings.json,.claude/skills/, and.claude/agents/. - At least one validation command, such as lint, tests, typecheck, build, or a browser smoke test.
- A git branch or worktree for changes.
Expected result: a starter Claude Code harness that a teammate can clone, inspect, and improve without relying on a transcript from your machine.
Define harness engineering in Claude Code
Harness engineering is the work of designing the environment around the agent loop. Claude Code already knows how to read files, edit code, run tools, ask for permission, and continue after tool results. Your harness decides what the agent sees first, what it can do without asking, which workflows load on demand, which external systems are available, and which checks must pass before a task is called done.
A useful Claude Code harness has six layers:
- Stable repo context in
CLAUDE.md. - Permission and sandbox policy in settings.
- Deterministic hooks for checks and blocks.
- Skills or custom commands for repeated procedures.
- Subagents for fresh-context work.
- MCP or plugins for shared external capabilities.
Do not start at layer six. A repo with no test command in CLAUDE.md usually does not need three MCP servers yet.
| Mechanism | Use it for | Avoid it when |
|---|---|---|
| Prompt | One current task, scope, and acceptance criteria | The instruction should persist across sessions |
CLAUDE.md | Stable repo facts, commands, constraints, and pointers | The content is a long workflow or reference manual |
| Skill | A repeated procedure, checklist, or reference set loaded on demand | The rule must block unsafe behavior |
| Subagent | Noisy research, fresh review, specialist checks, parallel work | The work needs the main thread to keep every detail |
| Hook | A deterministic action or gate at a lifecycle event | The decision needs judgment |
| MCP | Live external tools or data used repeatedly | A CLI export or pasted context is enough |
| Plugin | A shared bundle of skills, agents, hooks, settings, or MCP | The workflow is still changing every day |
| Permission rule | Allow, ask, or deny exact tool use | The issue is only missing context |
Audit and generate a harness starter
Harness workbench
Check the setup before the agent runs
Use this locally before you widen permissions, add MCP, or start a long run.
Start with a minimal setup
The minimal setup is small enough to review in one sitting. It gives Claude Code the repo map, exact checks, safe default permissions, and one place to put repeated workflows.
.
|-- CLAUDE.md
|-- .claude/
| |-- settings.json
| |-- hooks/
| | `-- validate-edits.sh
| |-- skills/
| | `-- release-check/
| | `-- SKILL.md
| `-- agents/
| `-- code-reviewer.md
|-- docs/
| `-- agent-runs/
`-- package.json# CLAUDE.md
## Project map
- Next.js app router site.
- Routes live in app/.
- Shared logic lives in lib/.
- Reusable UI lives in components/.
- Generated output lives in out/ and must not be edited.
## Setup
- Install: npm install
- Dev server: npm run dev
## Checks
- Lint: npm run lint
- Test: npm test
- Build: npm run build
## Working rules
- Read the nearest domain docs before editing that area.
- Keep edits scoped to the requested outcome.
- Do not change auth, payments, secrets, migrations, deploy scripts, or generated files without explicit approval.
- Before completion, report changed files, checks run, and remaining risk.
## Routing
- Use .claude/skills/release-check/SKILL.md for release readiness work.
- Use .claude/agents/code-reviewer.md for fresh review of non-trivial diffs.{
"permissions": {
"allow": [
"Bash(npm run lint *)",
"Bash(npm test *)",
"Bash(npm run build *)",
"Bash(git status *)",
"Bash(git diff *)"
],
"ask": [
"Bash(git commit *)",
"Bash(git push *)",
"Bash(npm install *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(rm -rf *)",
"Bash(curl *)",
"Bash(wget *)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/validate-edits.sh"
}
]
}
]
}
}#!/usr/bin/env bash
set -euo pipefail
payload="$(cat)"
file_path="$(printf '%s' "$payload" | jq -r '.tool_input.file_path // empty')"
case "$file_path" in
*.ts|*.tsx|*.js|*.jsx)
npx prettier --write "$file_path"
npm run lint -- --file "$file_path" >/tmp/claude-lint.log 2>&1 || {
tail -n 40 /tmp/claude-lint.log >&2
exit 2
}
;;
esacMove repeated work into a skill
A skill is better than a long CLAUDE.md section when the instruction is procedural. The description is the trigger surface. Keep it specific so Claude loads the skill only when it fits the task.
---
name: release-check
description: Use before merging or publishing a web app change that needs lint, tests, build, preview review, and a short risk note.
allowed-tools: Bash(npm run lint *) Bash(npm test *) Bash(npm run build *) Bash(git diff *) Bash(git status *)
---
# Release check
Run this procedure before saying a change is ready.
1. Inspect the current diff.
2. Run lint, tests, and build.
3. If the app has a UI change, start the preview and inspect the route.
4. Summarize changed files, validation commands, failed checks, and remaining risk.
5. Do not commit unless the user asks.Add subagents with narrow roles
Use a subagent when the side task would flood the main context or when the implementation needs a fresh reviewer. Avoid vague roles such as "senior engineer" because they do not tell Claude when to delegate or what evidence to return.
Subagent role quality
Too vague
name: expert-reviewer\n\ndescription: Reviews code and finds problems.\n\nThis role has no scope, severity model, tool limit, or return format.
Usable
name: regression-reviewer\n\ndescription: Use after implementation to review the diff for behavior regressions, missing tests, unsafe auth/payment changes, and P0/P1 blockers. Return only findings with file paths, severity, evidence, and suggested fix.
---
name: code-reviewer
description: Use after a non-trivial implementation to review the current diff for correctness, regressions, missing tests, and unsafe changes.
tools: Read, Grep, Glob, Bash
---
Review only the current diff and directly related files.
Report findings as:
- severity: P0, P1, P2, or P3
- file and line when available
- evidence from the code
- suggested fix
Do not rewrite the code. Do not comment on style unless it hides a bug.| Need | Use MCP? | Better simpler option |
|---|---|---|
| Read a single ticket once | No | Paste the ticket or export it with a CLI |
| Repeatedly query Jira, Linear, Sentry, or docs | Yes | None, if the workflow repeats across tasks |
| Run a local script already in the repo | No | Allow the exact Bash command |
| Share a tool with a team | Maybe | A plugin if it bundles skills, MCP, and settings |
| Access production data | Only with review | Read-only export, audit log, and explicit owner approval |
Expand to a production setup
The production setup is not bigger for its own sake. It adds ownership and proof:
CLAUDE.mdstays short and imports deeper docs only when useful..claude/settings.jsondenies secrets, destructive commands, and production paths by default.- Hooks enforce deterministic checks and never hide their failures.
- Skills hold release, incident, migration, and review procedures.
- Subagents separate research, implementation review, test repair, and security checks.
- MCP servers are pinned, documented, and limited to workflows with repeated external state.
- Worktrees isolate long-running or parallel work.
- Verification evidence is written to
docs/agent-runs/<task>.mdfor long tasks.
| Weak rule | Corrected rule |
|---|---|
Always write clean code. | Run npm run lint and npm test before completion. Flag any remaining failure with command output. |
Claude can run any command it needs. | Allow Bash(npm test *), Bash(npm run lint *), Bash(git diff *); ask for git commit; deny rm -rf, curl, wget, and .env reads. |
Use MCP for docs. | Use MCP only when the task needs current external docs repeatedly. For one-off docs, paste the relevant source link or export. |
Review your own work carefully. | After implementation, invoke code-reviewer on the diff and require no P0/P1 findings before completion. |
| Failure mode | What it looks like | Fix |
|---|---|---|
| Context bloat | CLAUDE.md contains tutorials, API docs, and old run logs | Move procedures to skills and references; keep CLAUDE.md as a router |
| Conflicting instructions | Root file says run all tests; package file says never run all tests | Make default and exception explicit, with package owner |
| Unsafe permissions | Broad Bash(*) or network commands allowed by default | Allow exact commands; ask or deny everything else |
| Stale docs | Commands in CLAUDE.md no longer exist | Run the setup from a clean checkout and update the file |
| Overused MCP | Every external system is connected before a workflow needs it | Start with one high-frequency tool and audit usage |
| Vague subagents | Subagent names are roles, not jobs | Define trigger, scope, tools, evidence, and output format |
| Blocking hooks | Hooks run slow global checks after every edit | Scope hooks to file type, event, and fast checks |
Verification workflow before trusting output
Check the diff
Run
git diff --statand inspect changed files. Confirm the diff matches the requested scope.Run deterministic checks
Run lint, typecheck, tests, and build. Use scoped checks while iterating and the full gate before completion.
Review the runtime behavior
Start the app or preview route. Inspect the affected path on desktop and mobile when UI changed.
Ask for fresh review
Use a reviewer subagent or
/code-reviewstyle workflow. The implementing context should not be the only grader.Record evidence
List commands, screenshots or preview notes, changed files, and remaining risks in the final response or a state file.
Adopt the harness incrementally
Write the minimal CLAUDE.md
Add setup, checks, protected paths, and completion evidence. Keep it under reviewable length.
Add permission policy
Allow the exact safe commands. Ask for package installs and git operations. Deny secrets and destructive commands.
Add one hook
Start with a fast edit validation or Stop gate. Remove it if it blocks normal work without producing useful evidence.
Extract one skill
Pick the workflow you paste most often and turn it into a skill with a narrow description.
Add one reviewer subagent
Use it after implementation. Tune its output until it finds concrete issues without dumping broad commentary.
Connect one MCP server
Add MCP only when a repeated workflow needs live external state. Document the risk and owner.
Reach the end and this star joins your charted sky.