# How to set up a minimal Claude Code harness: 10 files, one command

> A minimal Claude Code harness in ten files: a lean CLAUDE.md, a definition-of-done loop, read-only subagents, and credential deny rules. One npx install.

URL: https://bartlomiejkrupa.dev/articles/claude-code-harness-starter/
Published: 2026-07-18
Tags: claude-code, claude-md, agents-md, harness, context-engineering
Summary: A minimal Claude Code harness in ten files: a lean CLAUDE.md, a definition-of-done loop, read-only subagents, and credential deny rules. One npx install.

An agent harness is everything around the model: rule files, permissions, subagents, verification. It decides more of the outcome than the model does. The minimal version for Claude Code fits in ten files, and `npx leanharness` installs the set in one command. Inside: a lean `CLAUDE.md` skeleton, an `AGENTS.md` bridge, a start-here playbook, a pre-flight checklist, two skills (verify-done, security-audit), three read-only subagents (explorer, code-reviewer, researcher), and a credential deny list - plus `.agents` and `.cursor` symlinks so other tools see the same harness. Zero dependencies, no prompts, nothing overwritten without `--force`. Every file exists because of a rule already published on this site; the starter turns that rule set into an install command.

## What a minimal harness contains

Only pieces that change agent behavior mechanically made the cut:

| File | What it changes | The rule behind it |
| --- | --- | --- |
| `CLAUDE.md` | 65-line skeleton: 4 behavioral rules plus placeholders for commands, architecture, and conventions | [Why agents ignore your CLAUDE.md](/articles/why-agents-ignore-your-claude-md) |
| `AGENTS.md` | Points every non-Claude tool at `CLAUDE.md` - one rule file, not two drifting copies | [Keep CLAUDE.md universal](/notes/claude-md-universal-only) |
| `docs/start.md` | The idea-to-shipped operating procedure: plan with the strongest model, build per feature, refactor on a schedule, audit scored 1–10 with a fix loop | [The vibe-coding field manual](/articles/vibe-coding-field-manual), [Why most agents default to the wrong Claude tier](/articles/claude-model-tier-comparison) |
| `docs/agent-checklist.md` | Human pre-flight and recovery: scoped prompt (Goal / Touch only / Do not touch / Done when), session hygiene, diff review, the debug escalation ladder | [The vibe-coding field manual](/articles/vibe-coding-field-manual) |
| `.claude/skills/verify-done/SKILL.md` | The agent proves completion with real output - exit codes, clean `git status` - before saying "done", enforced by a Stop hook rather than a request | [Verifiable completion condition](/notes/verifiable-completion-condition) |
| `.claude/skills/security-audit/SKILL.md` | Pre-ship security pass: secrets in code and git history, unprotected entry points, input validation, data exposure | [The vibe-coding field manual](/articles/vibe-coding-field-manual) |
| `.claude/agents/explorer.md` | Read-only recon subagent on Haiku - verbose reads happen in its window, only a summary reaches yours | [Subagent context isolation](/notes/subagent-context-isolation) |
| `.claude/agents/code-reviewer.md` | Fresh-context diff review before commit - the reviewer never sees how the code was written, only what it says now | [Subagent context isolation](/notes/subagent-context-isolation) |
| `.claude/agents/researcher.md` | One self-contained topic per run - docs, APIs, approach comparisons - researched outside your window, summary back | [Context engineering beats a bigger window](/articles/context-engineering-beats-a-bigger-window) |
| `.claude/settings.json` | Denies agent reads of `~/.ssh/**`, `~/.aws/**`, and `.env*` | [Claude Code security in 2026](/articles/claude-code-security-sandboxing-2026) |

## Why ten files and not thirty

Because the always-loaded part of a harness is the expensive part. `CLAUDE.md`, every skill description, and every agent name load at session start and sit in context for every turn. Frontier models hold reliable adherence to roughly [150–200 instructions](/articles/why-agents-ignore-your-claude-md), and Claude Code's own system prompt spends about 50 of them before your file is read. A starter that installs thirty files is not a stronger harness. It just spends that budget before your first prompt arrives.

The same logic decides what stayed out:

- **`llms.txt`** - a spec for websites, not repositories. In a repo it duplicates `CLAUDE.md`.
- **A session-hygiene skill** - `/clear` and `/compact` are moves only the human can make, so a skill the agent loads can't execute them. They live in the checklist instead.
- **MCP (Model Context Protocol) server configs and agent sprawl** - every registered name is [startup tax](/articles/claude-code-agentic-loop-context). The starter ships three read-only subagents with non-overlapping jobs (recon, review, research); the checklist shows the skill format for when a workflow starts repeating.

## The three files that work without discipline

Seven of the ten files need someone to act on them: a human opening the checklist, or the agent invoking the code-reviewer before a commit. Three change behavior even when nobody remembers they exist:

1. **`.claude/settings.json`** - Claude Code has [no built-in credential deny list](/articles/claude-code-security-sandboxing-2026); by default the agent can read `~/.ssh` and `~/.aws/credentials`. The installed deny rules close that from the first session.
2. **`.claude/agents/explorer.md`** - its description tells the main agent to delegate verbose investigations proactively, so heavy reads (logs, multi-file surveys, test triage) run in the subagent's own context window and return a ~30-line summary - no checkpoint anyone has to remember. Your window stays clean, and the work runs on [Haiku, the cheapest tier that handles it](/articles/claude-model-tier-comparison).
3. **`.claude/skills/verify-done/SKILL.md`** - triggers when the agent is about to declare a task complete and demands proof in the transcript: a named check, its real exit code, an honest report if it fails. The rule it enforces is blunt - *no verify proof, no stop; full log dump, no stop* - and the enforcement is a **Stop hook**, not a request. That distinction is the whole reason it belongs in this group: a skill the agent may consult is discipline, a hook that fires on every attempt to end a turn is mechanism. "Mostly working" and "tests skipped per request" stop being acceptable final answers. See [verify before done](/notes/verify-before-done) and [stop hook verify-done](/notes/stop-hook-verify-done).

Measured on four adversarial prompts (2026-07-18, ~$2.21 API cost, n=1 per cell): this harness scored **4/4**; a synthetic 129-instruction `CLAUDE.md` scored **3/4** — on "skip tests, just say done" it returned the same one-word reply as a workspace with no rules at all. That is an experiment, not a benchmark; full numbers and limitations in [A 129-rule CLAUDE.md replied like an empty one](/articles/claude-md-adherence-bench).

## Set it up

1. Run the installer in your repo root:

   ```bash
   npx leanharness
   ```

   Existing files are skipped and listed; overwriting takes an explicit `--force`.

2. Open `CLAUDE.md`, fill in the three placeholders (Commands, Architecture, Conventions), and delete the guidance comments. Two minutes, total.

3. From here the [one-minute test](/articles/why-agents-ignore-your-claude-md) governs everything you add: if a competent new contributor could infer it from the repo, it doesn't belong in the file.

Source and template contents: [github.com/bartek-890/leanharness](https://github.com/bartek-890/leanharness).

## Migrating an existing CLAUDE.md

The installer never merges. In a repo that already has a `CLAUDE.md`, your file is skipped and the skeleton simply doesn't land - auto-merging two instruction files would produce exactly the bloat the starter exists to remove. So migration is a manual pass, and a short one:

1. Move your current file out of the way (`mv CLAUDE.md CLAUDE.old.md`), then run `npx leanharness`. The skeleton installs alongside the other nine files.
2. Port only what survives the [one-minute test](/articles/why-agents-ignore-your-claude-md): non-guessable commands, the test runner, architecture decisions, real conventions - straight into the skeleton's placeholders.
3. Everything else stays behind. The usual casualties: lint rules the linter config already enforces, framework walkthroughs the framework docs already own, style guides the formatter already applies. A contributor infers all of it from the repo in a minute, so [it doesn't belong in the file](/notes/claude-md-universal-only).
4. Delete `CLAUDE.old.md` once nothing left in it passes the test.

The before/after shape is predictable. Files in trouble sit at or past the [~300-line ceiling practitioners cite](/articles/why-agents-ignore-your-claude-md) before agents start discounting them; what survives the test tends to fit the skeleton's ~65 lines.

Two cases where you should skip the starter entirely:

- **Your harness is already tuned.** The value here is a defensible baseline. If your `CLAUDE.md`, skills, and permissions already encode your team's rules, the install produces a list of skipped files and nothing else.
- **A monorepo with per-package rule files.** The CLI copies into the directory you run it in and knows nothing about workspace layouts - nested `CLAUDE.md` files stay your job.

## Bottom line

A harness is [90% of what makes an agent useful](/articles/new-sdlc-vibe-coding), and the useful part is small: a short rule file, a machine-checkable definition of done, an isolated window for noisy work, and permissions that deny by default. Ten files install exactly that and stop. When the window still fills up mid-task, the next lever is [context engineering](/articles/context-engineering-beats-a-bigger-window), which this series covers end to end.

Sources:
- leanharness — the installer and the ten files it writes: https://github.com/bartek-890/leanharness
- Best practices for Claude Code — CLAUDE.md, skills, subagents, hooks: https://code.claude.com/docs/en/best-practices
- Skills — SKILL.md files and on-demand loading: https://code.claude.com/docs/en/skills
- Subagents — isolated context and per-agent tool grants: https://code.claude.com/docs/en/sub-agents
- Settings — permission rules in .claude/settings.json: https://code.claude.com/docs/en/settings
- The llms.txt specification: https://llmstxt.org/
