Two instructions, maximum
The .md I hand to my coding agent is two or three lines long. Useful rules only appear after I see the agent fail at something specific.
The file starts empty
The `.md` file I hand to my coding agent is, almost always, two instructions long. Sometimes three. I want to talk about why, because people keep assuming I'm under-investing.
I'm not.
Here's how I actually start a session. I open the file empty. There's no preamble. There's no "you are a senior engineer who values clean code." There's no list of conventions, no description of what the project is, no pre-baked examples. The agent gets a blank page and the codebase.
Then I work.
The file grows during the work, not before
This is the part that surprises people. The `.md` doesn't grow before the work - it grows during it. Because the rules that matter only show up when you see the agent miss something specific.
The canonical example is the logger. The codebase already has one. It's built around the same shape as SFCC's `dw.system.Logger.getLogger(fileNamePrefix, category)` - two args, where `fileNamePrefix` is the actual log filename and `category` is the logical bucket. One category per concern: payment is one bucket, order creation is one bucket, analytics is one bucket. Every module in a category reaches for the same handle and writes through it. One stream per category. Vendors and integrations are not their own categories - GTM doesn't get its own logger, Apple Pay doesn't get its own logger, credit-card processing doesn't get its own logger. They all log through the bucket they belong to.
On a clean prompt, the agent does not reach for the existing logger. It makes new ones. For analytics, instead of using the analytics bucket, it created a GTM-specific logger, a PDO-specific logger, and a couple of others - one logger per vendor, one logger per integration. For payment, instead of using the payment bucket, it created a credit-card logger, an Apple Pay logger, and whatever the next provider was. Each one a small logger in its own right. Each one writing into its own stream.
The codebase now has six loggers where it used to have one. Every search across logs is a join across six files. Every "show me all payment events" query is a grep across half the codebase. The fix isn't a fancy rewire - it's a one-line instruction, modelled on how SFCC's two-arg `getLogger('int_analytics', 'gtm')` still routes through the analytics category instead of spawning a GTM-only stream: log through the category bucket. One category, one stream. No per-vendor loggers. That's instruction number three. It only exists because I watched the agent scatter payment logs across vendor-specific files on a project that already had a single payment-category logger running.
The second scar: function duplication
Another one: function duplication. The agent will, fairly often, write a new function when an existing one does the job. Sometimes because the existing function is named weirdly. Sometimes because the agent didn't grep before it started writing. The fix isn't a giant preamble - it's a line, after the third time it happens, that says: before you write a new function, search the codebase first. That's instruction number four.
A journal of scars, not a plan
That's the pattern. The `.md` is a journal. Every line in it has a timestamp and a scar. "We added this because the agent did X, and we don't want it to do X again."
The thing I want to push back on is the framing that the .md is a plan.
You don't know what the agent needs to know. The agent will tell you, badly, by doing the wrong thing. Your job is to take notes.
It's the same reason I don't write ten examples of the same thing. One example, the real one that actually happened, is worth more than ten I imagined in advance. The imagined ones are usually wrong in subtle ways - they encode my assumptions about what the agent will do, which are not what the agent actually does. The real example is the one that fixes the real failure.
Why the file stays small
So when people ask how my agent "knows" the project conventions, the honest answer is: the `.md` is small because the codebase is big. The agent reads the codebase. The `.md` only has the things the codebase doesn't make obvious. And those things only become obvious after the agent has already missed them once.
The file is short on purpose. It'll be longer next month.