charles forson

Set up your Claude Code harness for success: where each instruction belongs

5 min read

This is specific to Claude Code. The five layers below, CLAUDE.md, rules, skills, hooks and subagents, are its building blocks. If you use a different agent the principle carries over, but the names won't.

Most people fix "the agent keeps doing the wrong thing" by adding more instructions to one file. I did too, for a while. My CLAUDE.md grew past three hundred lines before I saw the real problem. The agent had plenty of instructions. The trouble was that every instruction lived in the same place, no matter how often it actually needed to apply.

The fix is routing, not a bigger file. Claude Code gives you five places to put an instruction, each answering a different question about it. Picking the wrong one is what makes a harness slow and unreliable, far more than the wording of any single instruction.

CLAUDE.md is the always-on core, and every line in it is paid for on every single turn. That's not a figure of speech. It's read into the agent's context before you type anything, relevant to the task or not. So it earns only what genuinely has to be true for every task: what the project is, where to find things, the handful of rules that always apply. Mine stays under two hundred lines. If I catch myself writing a paragraph about one specific workflow in there, that paragraph belongs somewhere else. The size limit is a cost control, not a style preference.

Rules are for things that are always true but not always relevant. A rule about how to scope a pull request doesn't need to load while I'm reading research. A rule about commit-message format doesn't need to load while I'm capturing feedback. Rules are modular and path-scoped, so they appear only when the task touches the thing they govern. This is the layer most people skip. They either stuff everything into the top-level file, which is expensive and drowns out the few instructions that really are universal, or they write nothing down and hope the agent infers the convention from the code. That works until it quietly doesn't.

Skills are for ability you need sometimes, on demand. A skill is a procedure the agent runs when the task calls for it, not a fact it should always hold: a research-routing decision, a review checklist, a pass over a long-running goal. Skills are invoked, not loaded in the background, so they cost nothing on the turns where they don't apply. This is also where genuinely reusable know-how lives, instead of being re-explained in every prompt.

Hooks are for anything that must be true, not just usually true. This is the layer that turns "the agent should remember to do X" into "the agent cannot proceed without X." A written rule gets followed maybe 70% of the time. That's not a failure of the model, it's just what conventions do, and the misses add up if nothing catches them. A hook is deterministic. It either blocks the action or it doesn't. I moved draft-PR enforcement, worktree checks and secret-scanning into hooks precisely because "usually" isn't good enough there. If a pull request opens in the wrong state, a downstream gate can hang forever, and no amount of politely worded convention fixes that as reliably as a script that just says no.

Subagents are for isolated, specialised work. A subagent inherits none of the above. It starts from its own instructions with no memory of your conversation, your CLAUDE.md or your rules. That isolation is the whole point when you want an independent pass, a researcher that can't write to the repo, a reviewer that doesn't share the implementer's blind spots. It's also a liability when you forget to hand it the context it needs, which you then have to pass in explicitly every time. (When a task is worth giving its own agent is its own decision, and usually the answer is no.)

The pattern across all five is one question asked five ways: how often does this need to be true, and what happens if it's ignored? Always, and you can't enforce it, goes in CLAUDE.md. Often, and you can't enforce it, goes in a rule. Sometimes goes in a skill. Must-never-fail goes in a hook. Isolated and specialised goes in a subagent.

The part nobody tells you: the harness gets messy

Set this up and work at any real pace, and a second problem shows up. The harness bloats. You keep adding rules, skills and hooks, and most of them are useful the week you write them, but some go stale, some overlap, and some never get used. Left alone, the thing you built to go faster starts slowing you down.

The fix is more agents, pointed at the harness itself. I run a routine that sweeps the setup on a schedule, weekly and monthly: what's actually being used, what's gone stale, what's duplicated. It flags the dead weight so I can prune it, and the harness stays lean enough to keep moving at speed. The agents end up following me around, tidying the mess I make while I work fast. That's the difference between a setup that helps for a month and one that keeps helping.

What actually surprised me

Building this out, what actually struck me was how much of my early frustration with the agent had nothing to do with the model, and everything to do with where I'd put the instruction. There was one rule I'd written three times, in three slightly different phrasings, because I kept finding it wasn't being followed and my fix was always "say it more clearly." The real fix was recognising it needed to be a hook, not better prose. Once I moved it, the problem stopped, not because the agent got better at reading, but because I'd stopped asking a probabilistic system to guarantee a deterministic outcome.

Writing a good instruction is the easy part. Deciding where it lives is the actual work, and it's easy to skip because a bigger CLAUDE.md always feels like progress. It isn't. It's just a more expensive way of getting the same 70%.

Building the same things I write about — see what I'm working on in Projects, or get in touch.