Technical resources
TC

The Claude Code setup we run

active

Our actual configuration: the three rule files, the hooks that block, the 5 agents, the skills, session continuity and memory. Not a tutorial, the config we run.

guide · updated September 8, 2026

claude-codeagentshooksskillsconventionssetupmemory

Most write-ups about Claude Code explain the flags. None of them show you a configuration that has been run against real client work for months, and none of them tell you which parts earn their keep.

This is ours. Five agents, twenty skills, eight hooks, eight templates, two path-scoped rule files, a memory store and two continuity files. It is not a starter tutorial, and it is not a list of tips. It is the set of files we actually load, with the reasoning for each, including the parts we deliberately left out.

One caveat before anything else. A configuration is not a personality. Everything below exists to prevent a specific defect we watched happen, more than once. If you have not watched the defect, you probably do not need the rule yet.

The failure a setup is answering

Left to itself, a coding model drifts in three directions, reliably.

It writes long. Functions grow past the point where you can hold them in your head, and files grow past the point where you can find anything. It builds ahead. Asked for one thing, it delivers that thing plus an abstraction for the two cases you have not asked about, plus a configuration option nobody set. And it hoards. Replaced code stays behind with an _old suffix, dead branches stay commented out, and // TODO markers accumulate in committed code where nobody will ever read them.

None of that is fixed by asking nicely in a prompt. It is fixed by rules that live in files the model reads every time, and by hooks that refuse the action when a rule is not enough.

The three files, and what belongs in each

Three layers, each answering a different question. Putting a rule in the wrong layer is the most common mistake, and it fails in one of two ways: the rule is repeated in ten projects, or it is silently ignored because the project layer overrode it.

~/.claude/CLAUDE.md holds what is true on every project you will ever touch. Hard limits on function and file length. The toolchain, if it is genuinely yours everywhere. Security rules. Git policy. Copy and wording rules, if you have a house voice. Nothing here may mention a specific project, ever. The moment it does, it belongs one layer down.

The project's CLAUDE.md holds the stack, and only the rules that override or extend the global layer. Ours is short: the framework version and its breaking changes, how credentials are reached, the branch policy specific to a two-person team, and the agent roster for that repo. If a project's file repeats the global file, delete the repetition. A duplicated rule is a rule that will diverge.

CONTEXT.md is a different animal, and it is the one most people never write. It is a domain glossary: the vocabulary shared between you, the model and the code. Not instructions, definitions. What an "intervention" is in this business. What a "deal" means in this schema. One sentence each, describing what the thing is.

Create it lazily. Not at project setup, when you would be inventing terms, but the first time a term stabilises in a real conversation and you notice you have explained it twice. Written early it is fiction. Written at the right moment it removes an entire class of question, which is the point: every term defined once is a term the model never asks you to clarify again.

Hard limits

These are the rules that stop drift, expressed as numbers so they are not negotiable.

  • Functions: 40 lines maximum. Extract past that.
  • Files: 300 lines maximum. Split past that.
  • No speculative features. Implement what was asked, nothing adjacent.
  • Three similar cases before extracting a function.
  • Replace, do not deprecate. No _old suffixes, no commented-out blocks. Delete it.
  • No // TODO in committed code. Finish it or open an issue.

The third one deserves a note, because it is the one people push back on and the one that pays the most. A model's strongest architectural bias is to abstract at case two. Two things look similar, so it invents the shared helper, and the helper is wrong because two points do not determine the shape. Waiting for the third case costs you one duplicated block and buys you an abstraction that fits.

The related heuristic, for when you are looking at a module and cannot tell whether it deserves to exist: imagine it is gone. If the complexity disappears with it, it was a pass-through and you should inline it. If the complexity reappears in every caller, the module earns its place. Do not confuse a deep interface with a large implementation. A deep module is a small interface with a lot of behaviour behind it, not a big file.

Hooks, the part that actually blocks

Rules in a markdown file are advisory. The model reads them, and mostly follows them. Hooks are different: they intercept the tool call and refuse it. This is the part of a Claude Code setup that most people skip, and it is the only part that turns a preference into a guarantee.

We run eight. Four of them exist purely to make irreversible mistakes impossible:

  • block-push-main.js refuses a push to main or master. Branch protection on the host covers this too, but the hook fails earlier and locally, which means you find out before the round trip.
  • block-rm-rf.js refuses recursive force deletion outright and tells you what to use instead.
  • block-env-read.js refuses reads of credential files.
  • block-secret-leak.js refuses command shapes known to print secrets.

Two of the eight have test files sitting next to them. That is the part worth copying. A hook you have not tested is a hook you do not have: it will either fail open, in which case you believed you were protected and were not, or fail closed on innocent commands, in which case you will disable it within a week. Both outcomes are worse than no hook, because both come with a false belief attached.

There is also a structural limit worth understanding, because it changes what you must write as a rule rather than automate. A PreToolUse hook sees the text of a command, never its future output. It can refuse printenv. It cannot know that the object you are about to print carries an API key in a field, or that a cloud configuration endpoint is about to return a container's whole environment. Those cases cannot be hooked, at all, and they are exactly where real leaks happen. So they have to be covered by written rules that hold whether or not a hook fires: never print a secret even partially, never print a whole SDK client or config object for debugging, extract the one field you need.

One hook sits on the other side of that line, and it is the one whose limits are worth stating plainly. It runs after the tool, scans the output for credential-shaped strings, and when it finds one it cannot redact anything: the output is already in context. What it can do is force a loud reminder on the next turn and write an audit line, so a leak never depends on someone happening to notice. It is the second of the two hooks that ship with a test.

The last three are not guards. One loads the previous session's notes at start, one logs agent invocations for metrics, one audits bash calls. Cheap, and each removes a thing you would otherwise do by hand every session.

Agents, and when routing beats working directly

Five specialised agents, discovered automatically from ~/.claude/agents/, which is scanned recursively. Each is a markdown file with frontmatter: name, description, tools, model. We file them in subfolders by territory, which is documentation only: the identity comes from the name field alone, never from the path. The description is what does the routing, so it carries the trigger vocabulary rather than a job title.

  • ui for components and pages
  • auth-billing for authentication and payments
  • backend-api for routes, schemas, validation, transactional email
  • devops for containers, pipelines, DNS, deploys
  • marketing for SEO, metadata, structured data, analytics
  • security-observability for audits, rate limiting, incidents

Four run on a mid-tier model. One, the security agent, runs on the strongest available, because vulnerability reasoning is where model capability actually changes the answer, and because an audit that misses something is worse than no audit.

The discipline that makes this work is not the roster, it is the forced evaluation: before any coding task, decide explicitly whether a dedicated agent fits better than working directly, and say so. Left implicit, agent routing never happens, and you have five files doing nothing.

Where it pays most is parallel work on disjoint scopes. One agent per scope, all invoked in the same turn. Where it costs you is a task that crosses scopes, in which case say so and ask rather than letting two agents edit the same file.

Skills as procedures, not shortcuts

A skill is a packaged procedure the model follows instead of improvising. Ours split into two families.

The engineering ones are the load-bearing three:

  • grill-me runs before any non-trivial implementation. It interrogates the plan, walks every branch, and surfaces contradictions with the existing code, until you and the model actually agree on what is being built. Almost every design defect we have caught cheaply was caught here, before any code existed.
  • diagnose for a complex bug or a performance regression: reproduce, minimise, hypothesise, instrument, fix, add the regression test. In that order, which is the whole value, since the tempting order is to guess and patch.
  • cloture at session end: rewrite the continuity files, update memory, commit deliberately.

The rest are domain procedures: audits, PRD writing, SEO reviews, framework-specific guidance. Those are worth having only if you do that kind of work repeatedly. Written for a one-off, a skill is more expensive than just doing the task.

The same forced-evaluation rule applies: list the relevant skills, decide yes or no with a reason, and if yes invoke it before anything else. A skill that is not evaluated is never used.

Continuity: two files with different jobs

Every project carries two files at its root, versioned with the code. Splitting them matters, because they answer opposite questions.

lastdiscussion.md looks backwards. Fixed sections, no invention: current state, decisions taken this session with a short reason, what was actually done, technical notes covering traps and non-obvious dependencies, and an immediate next step in three lines maximum. It is read automatically at session start. It is rewritten whole, never appended, and only when you ask for it. Appending produces a log nobody reads within two weeks.

todo.md looks forwards. In progress, capped at one item so multitasking cannot hide. A backlog ordered top to bottom. Done recently, capped at ten dated items, past which they simply disappear, since the detail already lives in the git log.

The one habit that makes them worth the trouble: treat the narrative as a claim, not as truth. A previous session's notes routinely over or under-state where things stand, so the first action of a new session is git status, even when the notes say nothing is in flight. We have started sessions on a stale branch by trusting the file.

Memory: one fact per file

A single growing memory file collapses. It becomes a log, it is loaded whole whether relevant or not, and nothing in it is ever deleted because deleting a line from a wall of text feels arbitrary.

One fact per file fixes all three. Each file carries frontmatter with a name, a one-line description used to judge relevance, and a type: who the user is, feedback on how to work, project state that is not derivable from the code, or a pointer to an external resource. The body holds the fact, and for feedback and project notes, why it matters and how to apply it. Files cross-link each other, and linking to a memory that does not exist yet is fine, since it marks something worth writing later.

A one-line index is loaded each session, so relevance is judged from descriptions rather than by loading everything.

Two rules keep it honest. Do not save what the repository already records: code structure, past fixes, git history, the conventions already written in CLAUDE.md. And treat a recalled memory as background, reflecting what was true when it was written, not as a current instruction. If one names a file, a function or a flag, verify it still exists before acting on it. Ours has been wrong about a rate that changed and a file that moved.

What we deliberately do not do

  • No settings.json edited by an agent. Hooks and permissions are changed by a human, on purpose.
  • No .gitignore edited by an agent, for the same reason.
  • No credential files created or modified by an agent, ever.
  • No generic "be helpful" instructions. Every line in a rule file either constrains a decision or it is noise diluting the lines that do.
  • No metrics we do not read. We log agent invocations because we look at them. We do not log anything else.

Where to start, if you are starting

Not with the agents, and not with the skills. In this order:

  1. The global CLAUDE.md, with the six hard limits and your security rules. Half a page. This alone changes the output.
  2. The four blocking hooks, with a test for each. This is where the guarantee comes from.
  3. The two continuity files, and the habit of running git status before believing them.
  4. CONTEXT.md, the first time a domain term stabilises. Not before.
  5. Agents, once you notice you are repeating the same kind of task in the same area.
  6. Skills, once a procedure has been improvised three times.

Steps one and two are most of the value, and they take an afternoon. Everything after that is a refinement of a system that is already working.

The kit

Get the files

The configuration described above, as files you can run. Paths rewritten, our own tooling names removed, nothing else touched up.

Contents

  • 4 blocking hooks, 1 output leak detector, 3 utility
  • 2 of the 8 hooks ship with their tests
  • 6 agent definitions
  • 4 engineering skills
  • CLAUDE.md, settings.template.json, design.md
  • Templates for the glossary and both continuity files

Your email, and the download opens.

No mailing-list signup: just the kit.