← All writing
Craft · · 9 min

Documentation for future-you

On picking a reader who is competent and remembers nothing, and why the discipline is mostly deleting instead of writing.

Documentation AI

A client came back onto the retainer in May, and the project that came back with them was one I’d built and hadn’t opened in over a year.

There’s a NOTES.md in the root. I wrote it. Three entries, all in the same confident voice, because they were all written by the same person having the same good week.

Two of them did exactly what they were there to do. One told me the deploy needs a flag I’d never have guessed at and would have had to reverse-engineer out of a CI config. The other told me that a piece of ordering in the checkout looks wrong and is deliberate, with one sentence about why, which is the only reason I didn’t quietly tidy it into a bug on my first afternoon back.

The third told me how the staging environment works. Four sentences, no date on it, very sure of itself. It had been true. Nobody had touched the file since, me very much included, and staging had moved twice in the meantime. I lost a couple hours to it, and most of those hours went on assuming I’d misread the sentence instead of assuming the sentence was wrong, because it was in my own voice and my own voice sounds trustworthy to me.

The file came out well ahead on the day. I’ve been chewing on the couple hours ever since.

There is no new hire

The move that made the most difference was getting specific about who the file is for.

Future-you, at a distance, is not a beginner and is not a stranger. They have every bit of general skill you have right now plus whatever you pick up in the meantime. They know the language, they know the framework, and they can read the code faster than they can read your prose about the code.

They’ve lost context. Not “how does dependency injection work in this framework,” which is a search and a few minutes away, but why it’s done this way in this repo, what got tried first and dropped, and which part looks like a mistake and isn’t.

Once that’s the reader, a lot of what goes into a wiki turns out to be addressed to somebody who doesn’t exist. It’s written for a new hire. There is no new hire, and on the rare occasion there is one they get onboarded by a person on a call and not by your file. I made a version of this argument about READMEs back in 2017 and I still stand by the whole thing. But I was writing that one as though the audience were plural, and it never was.

What’s recoverable and what isn’t

Three kinds of thing end up in these files and only one of them earns the space.

First, anything recoverable from the code, like what the function does, which components exist, where the routes live. Don’t write any of it down. It’s the cheapest information in the building, and the moment you copy it somewhere else you’ve made a second copy that goes stale invisibly. That’s the argument I made about commit messages coming at you from the other direction, that a commit message is bound to one diff and can’t lie about it, where a paragraph in a wiki has nothing holding it to anything at all.

Then the stuff that’s recoverable but expensive. The deploy sequence, the flag, the one-off command with seven arguments, which of the env vars actually has to be set. That’s worth writing down and it’s what most people mean when they say documentation. The return is real and it’s bounded, since what you’re buying is an afternoon of archaeology for a few minutes of reading.

And then the stuff that isn’t recoverable at all, like why the ordering matters, what we tried that didn’t work, what the client insisted on over our objection, which feature looks broken on purpose, and why the obviously better approach isn’t actually better here.

That third kind is the whole game. It’s the one that doesn’t get written, because at the moment you have the information it feels too obvious to be worth a sentence. It never survives. A few months is enough to lose most of it, and after a couple of years it isn’t anywhere in the world except in one person’s head, and eventually not there either.

Two things I actually keep

Nothing elaborate, and I’ve tried elaborate.

The first is a comment next to the strange line saying that the line is strange on purpose. That’s the highest return per second of anything I write. It sits in the one place guaranteed to be read by whoever’s about to break it, which is more than a wiki can claim. It moves with the code when the code moves.

checkout.js
// Clear the cart before the redirect, not after. The payment provider
// sends the customer back through this same handler, and if the cart is
// still populated at that point the confirmation email goes out twice.
clearCart(session);
redirect(returnUrl);
JavaScript

The second is a decision log, which is a dated list that gets appended to and never reorganized. Three lines an entry, what we decided, what we turned down, why. It takes about a minute at the moment of deciding, which is the only moment anybody has the information.

NOTES.md
## 2025-03-18

Kept the order confirmation email on the old template instead of moving
it onto the new layout. Tried the new one first. The client's email
platform strips anything inside a <style> block, so every rule has to
stay inline, and the new layout has no inline path.
Markdown

The half I’d have called optional is the rejected half. Knowing that somebody already tried the obvious thing and watched it fall over has saved me from re-running the same failed experiment more times than I’d like to put in writing, and on one of those I’d have lost the better part of a week to it.

There’s a formal version of all this called an architecture decision record, which is a good idea and which I’ve bounced off twice. A dated list in a Markdown file is the one I’ll actually keep. So that’s the one I’ve got.

A wrong file is worse than no file

Back to the couple hours.

A document that’s wrong is worse than no document at all, because it’s confidently wrong and it comes with your own name on it, so the reader trusts it and starts debugging themselves instead of debugging it. No document sends them off to go and look, which is slower and correct. Wrong isn’t a weaker version of missing, it’s a different thing pointed the other way.

Which means the discipline isn’t writing more. It’s writing less and deleting without ceremony.

I know, I know, just keep the file updated. Sure. Nobody has ever kept a file updated in the abstract, so the version I’ve landed on is attached to something I’m already doing. Whenever I come back to a project after a gap, I do one small task first and pay attention to what I have to work out. Anything I spend more than a minute rediscovering goes in the file. Anything already in the file that isn’t true anymore comes out right then, while I’ve got the evidence in front of me.

That’s maybe 15 minutes. It happens at the one moment I can see the gaps at all, because two weeks later I’ll have absorbed every one of them and the file will look fine to me.

The reader who never skims

These files have a second reader now, which I didn’t see coming.

Whatever your agent reads at the start of a session is documentation, written by you, for a reader with perfect attendance and no memory whatsoever, which is a fairly precise description of the future-you I’ve been talking about the whole way through. In April I wrote about the lines in an instruction file that tell you to stop, and every word of that post quietly assumed the file was current.

A stale line now fails more loudly. A wrong sentence in a README can sit there for two years without anyone finding out, which is precisely how mine got to be two years old. Hand the same sentence to a model and it acts on it before you’ve finished reading the reply, in the working tree, while you’re watching. We got the loud version of that at work back in March, when a template repo turned out to be carrying a CLAUDE.md that described, in confident detail, a repo that wasn’t the one you were standing in. Nobody had to find that one the slow way.

I can’t help but think it’s the best feedback loop I’ve ever gotten on my own writing. It’s a slightly grim way to have gotten it. A coworker reading a vague line will do the sensible thing and never mention it to you. A model does the wrong thing immediately and visibly, and then you go and fix the line, and the line is better for people afterward too. So I started writing these files for the machine and my documentation for humans improved as a side effect, which is not the direction I’d have guessed. I’m not going to pretend I’d have gotten there on my own.

The staging entry, fixed

The staging entry is fixed. It’s 4 lines now instead of 11, it has a date on it, and 2 of the 11 were describing something that stopped existing in 2025 and are simply gone.

The date is the part I’d argue for. It’s the only thing in the file that tells the next person how much to trust the rest of it without opening anything else, and the next person is the whole point of the exercise. Anyway, there’ll be another gap, because that’s how retainers work, and I’ll be a stranger to that repo again by the time the next ticket lands. Four lines looks thin written out like that. It’s four lines I’ll believe, though, which is more than the 11 bought me in May.

Read similar posts
10 min

It's never the prompt

The prompting turns out to be the least interesting part of my Claude Code setup, and most of what's actually doing the work is a handful of files I wrote once and then stopped thinking about.

14 min

It will finish the list

Two Claude skills at work cover the two ways a Shopify client repo starts life, and having written both I'm fairly sure the numbered steps are the part nobody needed written down. The four or five places where the instruction is to stop are what earn the disk space.