I ship a data product on my own, and AI sessions do most of the typing. In Context, harness, the loop — a map of the architecture I run my project on with AI
I split the setup into three parts: the context (what the model always sees), the harness
(what it can reach and what stops it), and the loop the work runs in.
This is the context. Three things.
1. Two piles, and the small one is small on purpose
Every session I open reads three files before I type a word:
-
claude.md— the rules -
ActualStatus.md— where the project stands today -
Sprint.md— what's in flight
About 24 KB together. Plus one thing that isn't a file at all: a small script re-injects 2.4 KB
into every single message — a handful of reflexes I want in front of the model at all times.
Everything else lives in library/: 29 files, about 470 KB, and none of it is loaded. One
book per subject, fetched only when a task needs it — lib-git-discipline.md before touching
branches, lib-verifica-avversariale.md before finalising a design that's expensive to undo,
lib-quando-fermarsi.md when I'm on the fourth review round of something I should have shipped. One
index lists them all, a line each; that index is the only part of the library always in the room.
So: twenty times more written knowledge outside the room than inside it, deliberately.
A file earns permanent residency by what it costs when the model doesn't know it — not by how good it is. A short rule that gets silently broken when absent belongs in the pile. An excellent long document a session will correctly go and fetch when it matters does not.
2. The ceiling, and which way it moves
Of those three files, the one holding the rules is claude.md. Not documentation — only the
things that are expensive to get wrong, a line or two each:
- never commit a secrets file;
- only the directing session writes to the main branch — everyone else works in their own copy;
- before anything irreversible or expensive, go and read the relevant book;
- when a sub-task ends, stop and hand back. Don't start the next one.
Plus the one-line index of the library. It's about half the always-loaded weight, and it's the file
nobody edits during normal work — which is exactly why it drifts.
Left alone it grows forever: every lesson feels important the day you learn it, and nobody ever wants to delete a rule that once saved them.
So it has a ceiling. It falls on its own. It rises only if I write down why.
The enemy was never growth. It was growth nobody noticed. A rise that has to be dated, written down and justified is not that thing. It's a decision, and decisions are allowed.
Mine has roughly halved, and it has risen exactly once, by 2,404 bytes. I had been weighing the
three files and not the script that injects into every message. Next to 24 KB that channel looks
like a rounding error — but one is paid per session and the other per message, so over a long
session the small one costs several times more.
3. What the ceiling cannot see
It counts bytes. It has no opinion about what they say — and the two worst things I found were living inside a file it was successfully keeping small: pointers to registers nobody had written to in a month, and two sections that repeated what was already elsewhere. Both are cheap in bytes and expensive in attention, so a weight check will never report them. Dead pointers have their own check, running before every commit and asking a different question: this name is declared live — has anyone written to it in the last thirty days?
Three lines, if you take nothing else:
- Residency is decided by the cost of not knowing it, not by size or quality.
- Put a ceiling on whatever is always loaded. Let it fall by itself and rise only in writing — the thing you're fighting is drift, not growth.
- A ceiling weighs, it doesn't read.


Top comments (0)