
Part 6 of a series. Context is tokens, and tokens are a budget with a limit. A quick hello used to load 37.8 KB of instructions; one split cut it to 8.4 KB, and it has crept up since. The front of the memory grows back unless trimming is a habit. A session limit mid-job is a pause, not a failure. And every number I quote is measured with a command, not remembered.
On the evening of Wednesday 30 September, a pad of notes in my chief of staff's repo said one line that I have thought about since.
The skill file that wakes Nadim up was 37,806 bytes. It was loaded in full on every wake. Including the quick one.
The quick wake exists so I can say hello in a few seconds and get a short answer. It was reading a long magazine article's worth of text to do it. Every time. Before it had said a word.
Nobody had done anything wrong. The file had grown one sensible paragraph at a time, the way these files do, and nothing complained, because nothing in a terminal tells you what a sentence costs.
That is this part. Part 5 was about rules and the incidents behind them. This one is about the budget the rules are paid out of.
Context is tokens
An AI model does not remember. It reads. Everything it knows in a session was put in front of it at the start or added along the way, and it all counts against a limit. My plan has two of them that matter: one that resets every five hours and one that resets weekly.
So every instruction file is two things at once. It is guidance, and it is a bill. A paragraph that tells Nadim how to behave on a Sunday is read on Tuesday too, whether or not it applies.
I learned to think about this the way you think about page weight on a website. Nobody adds a 2 MB image on purpose. It is the fortieth small thing that does it.
Scar one: the wake that read everything
The pad from 30 September found the problem. The next day, 1 October, a job split that one skill file into a small router and one file per mode. A quick wake now reads the router and one short file, plus the README, the status file and the memory index, and nothing else unless the situation calls for it.
It took three rounds with the reviewer. Elissa rejected the first, which had the quick wake at 5,830 bytes. I told the job to give it more rounds. The third was approved and merged as commit 208d5f8 at 12:51. The quick wake's reading list went from 37,806 bytes to 8,396, counting everything it loaded then. The retro the next day rounded that to "37.8 KB to 8.4 KB", and the rounding is fair.
The 8,396 included one extra file that is now read only when a pad is open; without it the same measurement was 5,923. I ran the same count today on the router and quick.md, the two files that make up the skill itself: 3,830 plus 3,979, which is 7,809. So the fair comparison is 5,923 then and 7,809 now. The quick wake has grown by about a third since the split, and I did not notice until I counted. That is the point of this part.
📖 Reading the manual to say good morning
A greeting should not need the whole employee handbook. The quick wake was a hello that first read every chapter. The split put a table of contents in front and left the chapters on the shelf until someone asks for one.
I would like to tell you that was the end of it.
Scar two: the front grows back
It was not. Here are three files that every session or every job reads, with their sizes on 30 September from that same pad, and today, measured with wc -c. The old NEXT.md figure is from the 2 October retro.
| File | 30 Sep | Today |
|---|---|---|
| Nadim's memory index | 5,710 | 13,507 |
| The standing rules file | 10,398 | 19,438 |
The generated status file, NEXT.md | 12,977 (per the 2 Oct retro) | 901 |
Two of those went up, by 2.4 times and 1.9 times. One went down, and that one went down for an instructive reason: it stopped being something a person edits and became something a script generates, so it holds only what is true right now. The retro of 2 October had said of the old version that it was half of what a quick wake read at the time, and that I had cut it on 23 September "and did not keep it cut."
And did not keep it cut. That sentence was written by Nadim about Nadim.
🧳 A suitcase on a long trip
You pack light on day one. By day nine there are souvenirs in it and a second jacket you never wore. Nobody decided to overpack. Trimming has to be a thing you do on a schedule, because wanting to will not do it.
So trimming became a skill with a name, /trim. It works on a simple idea I asked for on 23 September: there is a front and a back. The front is what gets loaded every session. The back is a tagged archive, and nothing in it is ever deleted. A memory that was true and useful in September can move to the back when it stops being needed every day, and come forward again the moment it is.
The first real run archived 20 job files. Today the archive folder holds eight dated snapshots and a few subfolders next to an index, and the front still holds about a hundred memory notes. I want to be straight about this: the front is not small today. It is smaller than it would be without the trim, and I cannot give you a clean number for that, because I did not keep the counterfactual.
Trimming is not a cleanup you do once. It is a recurring cost you either pay on a schedule or pay in every session.
The rule that came out of it
I keep one habit from all this. On 23 September I told Nadim how I use the two wakes: the quick one most days, and the full one once a day or after a lot has changed. The full one reads more, checks the scheduled jobs and rebuilds the overview. It is the right tool about once a day. Using it for every hello is the 37.8 KB mistake again, wearing a different coat.
A month later, when my plan grew and the limits were less tight, I added a sentence for Nadim: having more tokens does not mean we start wasting. Room is not a licence.
Scar three: the limit that stopped a job in the middle
Headless jobs, the ones that run alone in the background, are where the limits show up first.
On the night of 22 to 23 October a job started at 03:07, ran into the session limit at 04:00, and was stopped. It resumed at 05:13 and finished at 05:30. Nothing was lost. The way a stop like that is handled now comes from a small tool and a rule.
The rule is in the standing file: a stop in the middle of a run is not a failure. A session limit, a login that expired, a launcher that was killed. When a job stops like that, the main session reads what happened and picks the job back up. If the limit has already reset, it does that straight away. If not, it waits until two minutes after the reset. Only when the resumed run stops as well does the job count as Blocked.
🔖 A bookmark, not a new book
When a limit stops a job, the job is a book put down halfway. Resuming it is opening at the bookmark. Starting again is buying a second copy and rereading the first fifty pages, and paying for them twice.
The tool is bin/resume-job. It finds the job's own session from the transcripts on disk and picks it up where it stopped, with the same context, instead of starting again and paying for it twice.
It also had a bug that is a good example of this series. A fix landed for it on 23 October (commit 1ec63303): the script looked for the job's launch text anywhere in a transcript, and my own main session quotes that text later, inside the scheduled prompts. So it sometimes found me and resumed the wrong conversation. The fix says it in a comment: a transcript is the job's own only if its first message opens with the launch text.
I want you to notice what a limit actually costs. It is the half-finished state. A job that stops after three steps of ten leaves a branch, a ticket and a row in a database that all say different things. The commit-as-you-go rule I wrote for code jobs, where nothing waits uncommitted, exists because a stop loses only the step that was in flight.
What changed about the night
Part 3 was about work that runs while I sleep. I had believed, from a reading on 9 October, that night work was cheaper: the limits seemed to stretch further after midnight. I said so out loud, and Nadim wrote it down.
On 23 October I changed plan after the limit reset, for a simple reason: the session limit kept stopping jobs. The memory note about the night now carries a line telling its future reader to re-measure before quoting the old readings, because they were taken on the plan I no longer have. Night slots are now a hint, not a fact.
I include that because the shelf life of a number is shorter than the shelf life of the sentence around it. "Night work is cheaper" was true when written. It then sat in a note, and a note does not know that the world changed.
Scar four: the number I guessed
Which brings me to the habit that holds the rest together. Nadim writes a number down only if a command it just ran produced it.
There were two occasions. One night in September, Nadim counted dependency alerts for a job and said six in one package and fifteen in another. The real counts were twenty and one. Dan caught one of the two mistakes that night. And on 24 September a log records the plainer version: "I also wrote guessed times (19:3x, 19:4x) into three files, when date said 19:24."
Neither is a disaster. That is the point. Guessing is cheap each time and it compounds, because the next reader trusts the number. The fix is boring and total: a figure in a file comes from a command, and a time comes from the clock line that the shell prints after each call. If I cannot run a command for it, it does not go in. This post has the same rule. The current sizes above came from wc -c today. The older ones are quoted from the pad, the retro and the job's own log, and I say which.
The status line
The newest piece shipped this Tuesday, 10 November. Claude Code can show the percentage of the five-hour and weekly limits a session has used. It hands that to a status line script in a field the product provides for it.
My script keeps only the two limit windows from it, with the used percentage and the reset time of each, and writes them to a small file on my own machine, with the time it was captured. Nothing else from the session is stored, and nothing leaves the Mac. The menu bar title shows them as 5h 42% wk 18%, and the dropdown adds the reset countdown. A line turns orange when I have used a clearly bigger share of the window than the time that has passed.
It is a small thing and I like it for a reason that has nothing to do with the tool. For weeks, "how close am I to the limit" was a feeling. Now it is a number from the product itself, by the supported route, and a feeling I have to defend against it.
What a stale rule costs here
Part 5 ended on stale rules being worse than missing ones. The same holds for numbers, and it is the thing I would tell you to take from this part.
Every file that gets loaded is a recurring cost. Every cost has a size. The size drifts upward whenever nobody is looking. So you look on a schedule, with a command, and you write down what the command said.
The takeaway
- Know what is loaded every time, in bytes. If you cannot say, you are overpaying.
- Split by when it is needed, not by topic. A small router in front and the detail behind it.
- Put trimming on a schedule, and keep the archive. Nothing is deleted. It just stops being read every day.
- Treat a limit hit as a pause. Commit as you go, and make resuming one command.
- A number you did not just measure is a guess. Do not file it as a fact.
The series
- The One Where We Meet Nadim
- The One Where the Avengers Assemble
- The One Where It Works the Night Shift
- The One Where Elissa Says No
- The One Where Every Rule Has a Scar
- The One Where We Count the Tokens (you are here)
- The One Where I Keep the Last Word, next Sunday
Next week: who holds which decision, what the AI may merge on its own, and the guardrails that stop it.
Every file you load is a bill you pay on every visit, and the only way to keep it small is to measure it again.
Subscribe to Life in Production
New essays on engineering, career, and life. No spam, unsubscribe anytime.