# Thin Skills, Thick Context: How I Engineered My Claude Code Harness

At some point I did something embarrassing: I counted. My Claude Code setup had dozens of skills and plugins installed, and I had never read the description of most of them. I installed them the way most people do: they were well known, often recommended, and they sounded useful.

Two quick definitions, so the rest is clear. A *skill* is an instruction file that teaches Claude Code one specific job. A *plugin* is a package that bundles such files. Both live in `~/.claude`, the folder that holds the whole setup.

Several of my skills did the same job. Two gave opposite orders: one said "explore the whole codebase first", the other said "start from a knowledge graph". Claude had to pick a side in every session. And every conversation spent tokens on features I was not sure I used.

Then one thought changed how I work. `~/.claude` is not a settings folder. It is a **system** — agents, rules, skills, commands, hooks, MCP servers — many parts sharing one resource: the **context window**, everything the model can see in one turn. Every installed part competes for that space.

I would never run any other system this way. So why did I run the system that writes my code like this? I stopped tweaking and started engineering the *harness* — the whole setup, treated as one system. The result is [ClaudeHarness](https://github.com/StefanoZaghi1987/ClaudeHarness): my configuration, plus the method that produced it.

The audit is the story of how I got there. But the audit is not the answer, and this is the part I got wrong for a long time. What the audit actually gave me was a **shape** — a workflow of phases and approval gates — and only then a list of tools to fill it with. This post explains the method, then the shape, then every piece of the configuration, so you know exactly what you would install.

## The five-step audit

The method is [a prompt in the repo](https://github.com/StefanoZaghi1987/ClaudeHarness/blob/master/prompts/5_AnalyzeSkills.md). It runs in five steps, and it stops at two checkpoints to wait for my approval. One strict rule applies everywhere: **every claim comes from reading the file on disk, with the file path written next to it.** Never from memory — the file on your disk may differ from the original plugin version. And "not determinable" is a valid answer. It is better than a guess.

1.  **Inventory.** List everything installed: skills, plugins, subagents, commands, hooks, settings, MCP servers. Read-only, one table row per item.
    
2.  **A short report for each skill.** Read the whole file and record what it *actually* does, when it fires, what it reads and produces, and its rough token cost.
    
3.  **Weighted comparison.** For each phase of the workflow, score every candidate against a rubric and pick a winner.
    
4.  **Conflict map.** For each pair that overlaps: what overlaps, which one wins, and how to fix it — disable one, restrict when it fires, or add a precedence rule in `CLAUDE.md`, the instruction file Claude reads at every session start.
    
5.  **Target harness and migration plan.** The new setup, each document linked to the next (spec → plan → tasks → review), plus a migration in small steps that can each be undone.
    

The rubric in step 3 is where the honesty lives:

| Criterion | Weight |
| --- | --- |
| Effect on my workflow | 20 |
| Output quality | 20 |
| Coverage | 15 |
| Criticality & objectivity | 15 — **doubled to 30 for the review phases** |
| Token efficiency | 15 |
| Plays well with others | 10 |
| Fires reliably | 5 |

Why is the review weight doubled? Because review is where a "no" matters most. A reviewer that cannot challenge my assumptions is not a reviewer — it is a rubber stamp.

The audit is cheap on tokens by design: metadata in bulk first, full files only for the shortlist, and a stop to ask before more than about 30 full reads. A method that fights context waste should not waste context itself.

## Thin skills, thick context

If the audit taught me one thing, it is this: **skills should be thin, and the context should be thick.**

The thin half is about how many skills you install and how big they are. Every installed skill adds its description to the context window — in *every* turn, not just once at the start. And when a skill starts a **subagent** (a helper agent with its own context window, its own model, and its own tools), that subagent inherits the same base context. The weight multiplies.

Many similar skills create a second problem: the model must choose between them. It may choose badly, or two skills may give conflicting instructions — exactly what happened with my two exploration skills. The rule that came out of it: **install few skills, keep each one small, and know what each one does.** A good skill has a short body; extra depth belongs in reference files that load only when needed.

The thick half is about where the real knowledge lives. The most valuable thing in a session is not any single skill. It is the chain of documents the workflow produces — spec, plan, task list, review reports. Each phase reads the previous documents and writes the next one. Knowledge grows step by step, inside a structure, instead of being loaded up front by a big skill that charges you in every conversation.

The audit even forces an uncomfortable conclusion: **for some phases, the winning choice is zero skills and one line of instruction in** `CLAUDE.md`**.** The method explicitly tells the auditor to argue that case, instead of approving my choices out of politeness.

## Five phases, three gates

The audit kept saying "for each phase of the workflow". That assumes I could name the phases. When I finally wrote them down, the workflow turned out to be the most durable thing I own — and the one I had documented worst.

Here is the shape, for new features and for bug fixing alike:

1.  **Brainstorm** — turn a vague request into a stated intent, with agreed scope.
    
2.  **Specify** — write down what will be true when the work is done.
    
3.  **Plan** — turn the approved spec into ordered steps that name real files.
    
4.  **Implement** — land the change in small, verifiable pieces.
    
5.  **Review** — make sure nothing merges unreviewed.
    

Between them sit three **gates**, after Specify, after Plan, and after Review. And here is the part I want to insist on, because it is where most AI workflows quietly cheat:

**A gate is two reviews, not one.** First a reviewer subagent with a *fresh* context window reads the artifact and reports blocking findings, each with a concrete fix. Fresh context is the whole point: a long session quietly turns its own assumptions into facts, and the agent that wrote the spec is the worst possible agent to check it. Then — separately — a human approves. An agent can tell me that a spec contradicts itself. It cannot tell me that the feature is not worth building.

A blocking finding sends the work back one phase. Never forward into the code.

### Phases are durable, tools are not

Now the distinction that makes all of this usable, and the one that took me longest to get right.

A **phase** is a durable step: it has a goal, it produces an artifact, and it ends at a stated exit criterion. A **tool** — a skill, a subagent, a rule — is one *way* to reach that exit criterion.

> Swapping a tool does not change the workflow. Skipping a phase does.

It is tempting to draw the pipeline with tool names inside the boxes. That looks precise, and it is a mistake: it describes one implementation and calls it the workflow. A reader cannot tell which boxes are durable and which are replaceable — and the human approvals, the part I care about most, disappear entirely, because no tool represents them.

The brainstorm phase makes the point best, because I have implemented it several different ways and the phase never moved:

| Tool | When I reach for it |
| --- | --- |
| `interview-me` | My default. It asks one question at a time until it understands the intent *behind* the request. |
| `idea-refine` | When the idea is still shapeless and I want options before committing to one. |
| `grilling` | When the interview is over but something still feels unresolved. It is deliberately uncomfortable. |
| `brainstorming` | The all-in-one path I used for a long time. It still works. |
| `architect` (a subagent) | When the open question is structural rather than about intent. |

Not one of those is a subagent, except the last. That is exactly why a workflow described through subagents alone is incomplete — and misleading.

The same is true further down the pipeline: Specify runs on `spec-driven-development`, Plan on `writing-plans` or `planning-and-task-breakdown`, Implement on `incremental-implementation` or `executing-plans`. Bug fixing enters through `diagnosing-bugs` or `systematic-debugging`, which produce a root-cause statement that then plays the role of the spec — and the gates still apply, because a symptom fix is a failure.

The full version, with every phase's goal, exit criterion, tool options and a cheatsheet, is [WORKFLOW.md](https://github.com/StefanoZaghi1987/ClaudeHarness/blob/master/WORKFLOW.md) in the repo.

### Scale down, never skip

One last rule, and it is the one that keeps this from becoming bureaucracy. A one-line change does not need a five-page spec. It still needs a stated intent, a named exit criterion, and a review. The phase survives; only its size changes. The smallest legal Brainstorm phase is one sentence written by me: *"I want X, because Y."*

The failure this prevents is not "too much process". It is discovering, halfway through a small task that turned out to be large, that I skipped the process for good reasons.

## What is in the repo — every piece, explained

The audit's rule applies to you too: do not install files you have not read. So here is the full inventory. It is deliberately small: four agents, one rule, two skills, five prompts — plus the workflow document that explains how they fit together.

### The four agents

A *subagent* is a helper agent with its own context window, its own model, and its own tools. You start it by name, it does one job, and it reports back.

Three of these four run the **automated half** of the three gates. They are not the gates — the human approval is the other half, and it does not ship in a repository. The fourth, `architect`, is the odd one out: it is the only one that produces something rather than reviewing it.

1.  `architect` — designs the solution *before* any plan exists. It reads the real code first, then proposes the structure: component boundaries, data flow, where new code should land. It must name one or two alternatives and explain why it rejects them. It checks security risks and failure modes, and it ends with a build order. It runs on the strongest tier (`fable`) and can only read, never write.
    
2.  `spec-reviewer` — checks the written design: contradictions, hidden assumptions, security gaps, simpler alternatives nobody considered. Blocking issues come first, each with a concrete fix.
    
3.  `implementation-plan-reviewer` — checks the plan against the real codebase. Do the files and functions in each step actually exist? Is the order safe? What is missing — tests, config, a rollback step?
    
4.  `code-reviewer` — checks the final diff (it can run `git diff` itself): bugs, security problems, needless complexity. Issues come most severe first, each with a `file:line` reference and a fix.
    

The three reviewers run on `opus`; `architect` runs on the top tier because a weak architectural choice is not caught by tests and is expensive to reverse. A blocking finding sends the work back one phase — never forward into the code. And these four *won* their places in the rubric comparison; they were not an assumption.

One detail worth naming: `code-reviewer` is the only one that can run shell commands, and it has that permission for exactly one reason — so it can run `git diff` and source its own diff. A reviewer that could also write would stop being a reviewer.

All four files refer to models by alias (`fable`, `opus`, `sonnet`, `haiku`), never by version number. In my `settings.json` (not part of the repo) a fallback chain walks down one tier at a time, so a model release cannot break anything.

### The one rule

`effort-escalation.md` is 11 lines. It keeps reasoning *effort* — how hard the model thinks about a task — at the default level. Claude may only *suggest* raising it, for deep multi-file debugging, an architecture decision, a security review, or a final check before delivery. Then it waits for my yes. Bulk search and lookup work goes to the cheap `haiku` tier. A tiny file, but it stops the most expensive thinking from being spent casually.

### The two maintenance skills

Both skills are manual: they never start on their own, because their frontmatter says `disable-model-invocation: true`. You call them by name when you want them.

`model-config-sync` re-checks the model routing against the *current* official docs. It fetches the docs, reads my settings and agent files, and reports a table: item, current value, what the docs say now, action needed. Then it shows the exact edits it proposes — and applies nothing until I confirm. I run it monthly and after every Claude Code update.

`skills-resync` solves a problem the audit created on purpose. I *vendor* skills: I copied 28 skills out of six plugins into my own `~/.claude/skills` folder, so no plugin update can remove or change them. The price is that they receive no updates either. This skill makes updating safe again. Its engine is a bash script of about 800 lines with a simple command set: refresh the original plugin copies, check what changed for each skill, then update — replaying my eight local edits as patches — and roll everything back if a patch fails. A companion file records which plugin every skill came from. I run it monthly.

To be clear: those 28 vendored skills live on my machine, not in the repo. The repo ships the engine — so you can run your own selection through the same checks.

Those 28 are also the answer to an obvious question about the workflow above: if `interview-me` and `spec-driven-development` and `writing-plans` are what actually implement my phases, and none of them are in the repo, how is anyone supposed to reproduce this? The companion file records where every one of them came from — plugin, marketplace, path — so the list is reproducible even though the files are not mine to redistribute. `skills-resync` is what keeps that list from rotting.

### The five prompts

The `prompts/` folder is the design history of everything above: my original request for better model routing, the requirements document it produced, my request for a full harness audit, the audit prompt, and the five-phase method this post describes. Read them in order and you can reconstruct every decision.

They are also the most reusable part. Run them against your own `~/.claude` and you get a setup that fits *your* workflow, with evidence for every choice. That, more than my four agents, is what I would like people to take from this.

## What this is not

*   **A configuration, not a product**: no installer, no benchmarks, no measured savings — the rubric scores judgement.
    
*   **A personal setup**, built for Windows with Git Bash (works on Unix/macOS Git Bash too; you need `git`, `patch`, `diff`, `awk`, `python3`).
    
*   **Deliberately small**: four agents, one rule, two skills, five prompts. The value is in how they were chosen, not in how many they are.
    
*   **A personal workflow, not a standard**: the five phases are what works for me. If you take one thing from this post, take the separation between phases and tools — not my particular tools.
    

## Getting started

No build step. Two ways to install:

```bash
# from a clone — copy the pieces you want
find agents -name '*.md' ! -name README.md -exec cp {} ~/.claude/agents/ \;
cp -r skills/model-config-sync skills/skills-resync ~/.claude/skills/
cp rules/effort-escalation.md ~/.claude/rules/
```

Or download the release zip from the [releases page](https://github.com/StefanoZaghi1987/ClaudeHarness/releases) — it contains `agents/`, `skills/`, and `rules/` at the top level, so it expands straight into `~/.claude/`.

Then reference the rule from your `~/.claude/CLAUDE.md`, restart Claude Code, and the agents are available by name.

The repo is [Apache 2.0](https://github.com/StefanoZaghi1987/ClaudeHarness/blob/master/LICENSE). Audit what is installed, prefer thin skills, put the thickness in the shared documents — and write down your phases before you write down your tools. If you run the prompts on your own harness, I would genuinely like to read what you find.
