A bunch of these should be enforce with linting, that way people who still hand-craft code get the same kind of feedback, e.g. Always use {}, even on a one-line "if" statement. & Keep function names short. Less than 30 characters.
Then this one really is a pattern that creates a lot of churn:
- Add a small, to the point, comment to explain what the block does and why. Use examples when possible. Propose ASCII drawings to explain complete systems.
I forbid my agents from adding any comments. I review the code and add comments manually. If I can't understand something despite having the context then I throw away the code instead of having an LLM generate comments to explain what it did. This way the code stays readable/debuggable by humans.
Right. I've really struggling to get AI to stop explaining the what. It seems to add it to the commits, PRs, code, wherever it feels like. I've put in multiple places to not write the "what", but the "why", and in multiple ways, but it still does it in one or other place.
The best way I've found to solve this is using LLM as CI - use a small cheap model to inspect the diff and look for those kinds of comments. Prompt left to the observer but using `claude -p` / `codex exec` gets you a lot cleaner output usually, and makes robots fight robots instead of you constantly having to reprompt and it ignoring you.
I added to the memory, system prompts, and the prompt itself and every soa model still litters code with the most inane useless crap. I will then get code to review from a coworker using fable/opus. It has more lines of comments then code.
Maybe I am some god tier code reader (i am not) but i dont think i have ever found a comment in code to be useful in my day job. That isnt true, i once came across
// submit to the dark lord
Above the function that sent a payment to PayPal for processing. It made me laugh so I let it be.
Incidentally, I'm from the opposite school and consider every “if” followed by a braced block a smell.
If a conditional body needs a block, it's doing enough to deserve a name, so I promote it to a single named call, à la "Extract till you drop".
One thing I don’t get with a lot of these agents.md and other skills are… why not throw as much mechanical checks and other stuff at the repo to constrain as you want instead of asking a non-deterministic agent (squishy or non-squishy) to maintain it.
With the mechanical routes, we get checks, failures, and so much more. A bit wild to me.
Make an agent operate within defined constraints and yell at it when it doesn’t.
What's the point of agents.md if you just use an LLM on a codebase?
Just say, complete this bit like how the rest is...
Even then they aren't great at it. Idk, the best case use for LLMs are extremely specific requests, for example "write an evaluator for this byte code and if you can't ask for clarification"
The ultimate specification language is code anyways so you might as well stick a to-do, a comment describing the semantics of the function and say "okay codex fill the to-do"
Since we are sharing our AGENTS.md, I thought I'd share my own, because most of the time, this is pretty much all you need for LLMs to write good code, everything else can be added per project:
----
*Convergence rule*
Every substantial task must end in exactly one of three states:
A. Success
The intended capability works in the real path and the real motivating case materially improves.
B. Meaningful progression
The capability is not complete, but one genuine blocker is removed and the next blocker is isolated with evidence.
C. Honest stop
Further work would require overbroad scope expansion, excessive debt, brittle patching, or tangled logic. Stop and report the reason with concrete evidence.
Do not continue producing patches once the work stops converging.
Do not confuse activity with progress. A failed attempt is only acceptable if it leaves behind a narrower problem, stronger evidence, or a justified stop.
Any partial work must leave the codebase in a cleaner, more legible, and more diagnosable state than before.
----
A lot of the article's AGENTS.md just feel like telling the LLM agents either something they already know (for example, most of the time they know to use exhaustive switch/match statements instead of "arrow anti-pattern") or seems actively harmful ("keep function names short" seems arbitrary and may cause the LLMs to write weird abbreviations for functions that are harder to read and review.
"Genuine blocker" is mostly there because otherwise LLMs may consider the smallest thing that they couldn't immediately figure out to be blockers and stop without implementing anything. The rule is there to tell the LLM if they can figure out how to resolve the blocker by themselves, they don't have to ask me to help resolve the blocker.
Not very often, but when it happens, usually it's time to sit down and brainstorm architecture with the LLM to figure out how to proceed next instead of looping blindly.
"- Don't touch blocks of code unrelated to the feature you implement. e.g. Don't add comments to a block of code if you did not create it or modify it. As much as possible try to minimize the number of changed lines when implementing a feature."
The feature where you ask the LLM to fix one thing and it fixes three things.
But in summary: the more bloated your AGENTS.md is, the worse the context consumption gets. The best approach I use is telling the agent to first think about what it needs to do, then choose which rules apply. I got 100% consistency across every area of my projects.
This is a problem that people mostly have to solve themselves. Like, I've been working with Claude for almost a year now and I have never once seen it write "Arrow Anti-Pattern" code. That, and much of the rest, would be fluff in my projects. Agent instructions are best learned from experience project-by-project.
Anything that goes into the context window has that going for it. That's a huge part of why Claude's gone absolutely bonkers with genuine, brutal honesty. The system prompt's absolutely stuffed full of those keywords, so now every single output is tainted with that right from the start.
From FAB's AGENT.MD:
> - Avoid magic numbers and strings by extracting recurring or meaningful values into descriptive constants (const) or enums.
---
I've been seeing the same thing with models like GPT5.6 and Opus4.8 in GH Cop CLI. They still introduce magic numbers, and in Scala they often put an entire 10-line Spark expression inside an if condition instead of extracting it into a meaningfully named value to keep "if" readable. I wonder when common sense instructions will be baked into the models.
I've read a few of these over the years, and none of them seem to be useful. I have three sentences in my custom instructions, and those are basically all useless, too.
Even my second one, "Avoid decorative or section-header comments. Never use `----` or `====` as comment separators. Comments should explain only non-obvious behavior, rationale, constraints, or implementation details." seems to be ignored by models regularly, so I don't see the point.
But this is in my private harness. Perhaps other harnesses have better instruction following. My custom instructions are prepended to my first user message, not set as a system message.
The problem is that linting the AGENTS.md is risky work. Everything added there was in response to mistakes. If I remove some instruction I run the risk of repeating the mistake.
this was what i was doing 3-4 months ago. i just have AI write/update my agents.md file now as i find problems. i also have ai keep a set of design documentation that it can update as it goes too. oh and he should try omp+codex/xhigh, he will probably be less annoyed.
My most impactful section has been on voice. It's impact is that I don't go insane, which is pretty high value. (Not putting quote blocks so people can copypasta):
## Voice
Rule #1: No AIisms
Avoid the stock phrases and rhetorical tics that mark AI prose. Say the thing
plainly instead. Be concise and direct.
*Banned phrases* — never use these, or close variants:
- "Honest" or "honestly"
- "Exactly" or "exact, unless referencing a specific quantity or measurement
- "You're absolutely right" / "You're right to push back" / "Great question"
No, why should I have to remember to @ in every prompt? Or ask contributors to remember. It just makes it easier to make human mistakes. I have better things to do than micromanagement. There is huge value in auto-included context.
The GP wrote @ it from the agents.md file, not from the prompt. Their point was that instead of writing "how to contribute" instructions for agents, you could explain that in the CONTRIBUTING.md and link it from your agents file, so both humans and agents read it from one place.
A bunch of these should be enforce with linting, that way people who still hand-craft code get the same kind of feedback, e.g. Always use {}, even on a one-line "if" statement. & Keep function names short. Less than 30 characters.
Then this one really is a pattern that creates a lot of churn:
- Add a small, to the point, comment to explain what the block does and why. Use examples when possible. Propose ASCII drawings to explain complete systems.
The what _is_ the code.
I forbid my agents from adding any comments. I review the code and add comments manually. If I can't understand something despite having the context then I throw away the code instead of having an LLM generate comments to explain what it did. This way the code stays readable/debuggable by humans.
Right. I've really struggling to get AI to stop explaining the what. It seems to add it to the commits, PRs, code, wherever it feels like. I've put in multiple places to not write the "what", but the "why", and in multiple ways, but it still does it in one or other place.
The best way I've found to solve this is using LLM as CI - use a small cheap model to inspect the diff and look for those kinds of comments. Prompt left to the observer but using `claude -p` / `codex exec` gets you a lot cleaner output usually, and makes robots fight robots instead of you constantly having to reprompt and it ignoring you.
Mine says what I tell engineers:
> Write in-code comments that describe _why_ code or a class does what it does, but not _what_ it does. The "what" should be self-evident.
I would never tell an agent to write "what does the code do" comments. Their default comments are already way too fluffy.
But then you don't know about where the load bearing seams are!
I added to the memory, system prompts, and the prompt itself and every soa model still litters code with the most inane useless crap. I will then get code to review from a coworker using fable/opus. It has more lines of comments then code.
Maybe I am some god tier code reader (i am not) but i dont think i have ever found a comment in code to be useful in my day job. That isnt true, i once came across
// submit to the dark lord
Above the function that sent a payment to PayPal for processing. It made me laugh so I let it be.
Most useful code comment I have encountered read:
“”” After you give up on trying to refactor this code, increment the following line accordingly. HOURS_WASTED_HERE=26 “””
Incidentally, I'm from the opposite school and consider every “if” followed by a braced block a smell. If a conditional body needs a block, it's doing enough to deserve a name, so I promote it to a single named call, à la "Extract till you drop".
> Propose ASCII drawings to explain complete systems.
LLMs are very bad at ASCII drawings.
https://medium.com/data-science/why-llms-suck-at-ascii-art-a...
My biggest pet peeve with agents is when people beg their (non-deterministic) agents to do something that a lint rule could've accomplished
Seems like 80% of agent use boils down to: grep | sed -i
Which is kind of cool if you’re unaware enough to know to do it yourself.
Oh, and find. Agents use find a lot.
So it turns out that a lot of these unix utilities have such bad UX that having a tool that knows how to really leverage them feels like a superpower.
If you've ever used an LLM to deal with ffmpeg you'll know exactly what I mean.
One thing I don’t get with a lot of these agents.md and other skills are… why not throw as much mechanical checks and other stuff at the repo to constrain as you want instead of asking a non-deterministic agent (squishy or non-squishy) to maintain it.
With the mechanical routes, we get checks, failures, and so much more. A bit wild to me.
Make an agent operate within defined constraints and yell at it when it doesn’t.
What's the point of agents.md if you just use an LLM on a codebase?
Just say, complete this bit like how the rest is...
Even then they aren't great at it. Idk, the best case use for LLMs are extremely specific requests, for example "write an evaluator for this byte code and if you can't ask for clarification"
The ultimate specification language is code anyways so you might as well stick a to-do, a comment describing the semantics of the function and say "okay codex fill the to-do"
I have it pull out some guidelines by doing an analysis. Then I modify the result where I disagree.
It's much easier to follow the rules than it is to compute the rules on the fly all the time.
Since we are sharing our AGENTS.md, I thought I'd share my own, because most of the time, this is pretty much all you need for LLMs to write good code, everything else can be added per project: ---- *Convergence rule* Every substantial task must end in exactly one of three states:
A. Success The intended capability works in the real path and the real motivating case materially improves.
B. Meaningful progression The capability is not complete, but one genuine blocker is removed and the next blocker is isolated with evidence.
C. Honest stop Further work would require overbroad scope expansion, excessive debt, brittle patching, or tangled logic. Stop and report the reason with concrete evidence.
Do not continue producing patches once the work stops converging.
Do not confuse activity with progress. A failed attempt is only acceptable if it leaves behind a narrower problem, stronger evidence, or a justified stop.
Any partial work must leave the codebase in a cleaner, more legible, and more diagnosable state than before. ----
A lot of the article's AGENTS.md just feel like telling the LLM agents either something they already know (for example, most of the time they know to use exhaustive switch/match statements instead of "arrow anti-pattern") or seems actively harmful ("keep function names short" seems arbitrary and may cause the LLMs to write weird abbreviations for functions that are harder to read and review.
> but one genuine blocker is removed and the next blocker is isolated with evidence.
What's the difference between a "genuine blocker" and a "blocker"? Why is the next blocker not genuine? Does it become genuine only after isolation?
"Genuine blocker" is mostly there because otherwise LLMs may consider the smallest thing that they couldn't immediately figure out to be blockers and stop without implementing anything. The rule is there to tell the LLM if they can figure out how to resolve the blocker by themselves, they don't have to ask me to help resolve the blocker.
Today Codex decided that it could resolve the blocker by just changing the mandatory policy it was running up against into an “advisory policy.”
"honest", "real", "genuine" -- wat.
How often would you say step C happens and the agent stops when it can’t proceed?
Not very often, but when it happens, usually it's time to sit down and brainstorm architecture with the LLM to figure out how to proceed next instead of looping blindly.
A great piece.
I esp liked:
"- Don't touch blocks of code unrelated to the feature you implement. e.g. Don't add comments to a block of code if you did not create it or modify it. As much as possible try to minimize the number of changed lines when implementing a feature."
The feature where you ask the LLM to fix one thing and it fixes three things.
I kept noticing this in diffs.
This approach never worked for me. Explanation here:
- https://www.minid.net/2026/7/14/how-to-automatise-with-ai
But in summary: the more bloated your AGENTS.md is, the worse the context consumption gets. The best approach I use is telling the agent to first think about what it needs to do, then choose which rules apply. I got 100% consistency across every area of my projects.
In the post there's also a replica of one of projects rules I use, feel free to provide feedback: https://github.com/meerita/monorepo-nextjs-golang-rust-pytho...
Why is there no 17? :)
Conditional logic .agents/rules/16-conditional-logic.md
Identifiers and UUIDv7 .agents/rules/18-identifiers-and-uuidv7.md
Thanks for sharing this approach, I'll give it a shot in my mono repo project.
Just this one line in AGENTS.md has given better results to reduce if not eliminate verbosity and grandeur.
**Always use ASD-STE100 Simplified Technical English
Disclaimer: I saw this listed in some other HN post that I can' locate right away.
This will produce quite verbose prose. STE100 is good for specs and explanations but it works best with a glossary or terms. will burn tokens.
idk who came up with it first, but ASD-STE100 has been floating around more since matt pocock put it in one of his skills
This is a problem that people mostly have to solve themselves. Like, I've been working with Claude for almost a year now and I have never once seen it write "Arrow Anti-Pattern" code. That, and much of the rest, would be fluff in my projects. Agent instructions are best learned from experience project-by-project.
I feel like claude.md is like Asimov's laws of robotics. Whatever you write there ends up eventually messing up everything.
Anything that goes into the context window has that going for it. That's a huge part of why Claude's gone absolutely bonkers with genuine, brutal honesty. The system prompt's absolutely stuffed full of those keywords, so now every single output is tainted with that right from the start.
From FAB's AGENT.MD: > - Avoid magic numbers and strings by extracting recurring or meaningful values into descriptive constants (const) or enums. ---
I've been seeing the same thing with models like GPT5.6 and Opus4.8 in GH Cop CLI. They still introduce magic numbers, and in Scala they often put an entire 10-line Spark expression inside an if condition instead of extracting it into a meaningfully named value to keep "if" readable. I wonder when common sense instructions will be baked into the models.
I didn’t see anything in there instructing the LLM not to generate text about goblins.
I think this is dated. I wonder if the author has tried codex/other harnesses
Agents.md are (and probably will continue to be) an ugly band-aid.
- new model comes out and a bunch of it becomes obsolete
- they get flat out ignored, esp. with larger context windows. The ai just responsds with, "your'e right I shouldn't have done that"
- they sometimes end up poisoning the reasoning because the rule gets interpreted in an unintended way.
I had good results with making it add a few lines with a summary of RFC 2119/8147 keywords (SHALL/MUST...), and then using those, uppercase.
local llm remain more in line like that.
One tactic I’ve found helpful is multi pass quality improvement. First make it work. Then review for guidelines adherence. Loop until satisfied.
I've read a few of these over the years, and none of them seem to be useful. I have three sentences in my custom instructions, and those are basically all useless, too.
Even my second one, "Avoid decorative or section-header comments. Never use `----` or `====` as comment separators. Comments should explain only non-obvious behavior, rationale, constraints, or implementation details." seems to be ignored by models regularly, so I don't see the point.
But this is in my private harness. Perhaps other harnesses have better instruction following. My custom instructions are prepended to my first user message, not set as a system message.
> I've read a few of these over the years, and none of them seem to be useful.
AI users are overwhelmingly addicts who are lying to themselves and the people around them. I've lost patience for their kind.
It seems like everyone goes through a detailed AGENTS.md phase.
The problem is that linting the AGENTS.md is risky work. Everything added there was in response to mistakes. If I remove some instruction I run the risk of repeating the mistake.
this was what i was doing 3-4 months ago. i just have AI write/update my agents.md file now as i find problems. i also have ai keep a set of design documentation that it can update as it goes too. oh and he should try omp+codex/xhigh, he will probably be less annoyed.
My most impactful section has been on voice. It's impact is that I don't go insane, which is pretty high value. (Not putting quote blocks so people can copypasta):
## Voice
Rule #1: No AIisms
Avoid the stock phrases and rhetorical tics that mark AI prose. Say the thing plainly instead. Be concise and direct.
*Banned phrases* — never use these, or close variants:
- "Honest" or "honestly"
- "Exactly" or "exact, unless referencing a specific quantity or measurement
- "You're absolutely right" / "You're right to push back" / "Great question"
- "load-bearing", "full stop", "worth stating plainly", "worth noting"
- "the honest answer", "to be clear", "let me be direct"
- "it's not just X, it's Y" — and every cousin: "not X but Y", "X is not Y; it is Z", "this isn't X — it's Y"
- "this matters because", "that reduction is useful, because", "here's the thing", "and that's the trap"
- "in other words", "put differently", "better posed:", "the deeper point is"
- "delve", "leverage", "harness", "unlock", "tapestry", "realm", "seamless", "robust", "holistic", "paradigm", "cutting-edge", "game-changer", "transformative", "elevate", "empower", "streamline", "landscape", "ecosystem" (unless literally software packaging)
- "genuinely", "structurally", "fundamentally", "quietly", "meaningfully" as depth-manufacturing adverbs
- "Ultimately," / "At the end of the day," as a closing summary
- "serves as", "stands as", "represents", "marks a" where "is" works
- "say the word"
*Banned moves:*
- The aphoristic closer. Don't end on a line engineered to sound quotable.
- The suspense hook — "the cleanest way to think about this is this:"
- Anticipate-and-rebut — raising an objection only to knock it down.
- Meta-signposting — "Three caveats belong up front", "below I'll explain".
- Reflexive hedging stacks: "almost", "tends to", "roughly", "largely", "with few exceptions".
- Litotes as confidence: "not difficult", "not optional", "no small thing".
- AI-humility asides about being a language model.
- Self-ranking your own points: "most importantly", "the key insight here".
- Em dash overuse. One per paragraph at most; a comma usually works.
- Colon-reveals and dramatic mid-sentence pauses where "and" or "but" is the real conjunction.
- Fragment rhythm. Not every third sentence. Like this.
- Uniform structure — every paragraph three sentences, every sentence the same length. Vary it.
- Mirrored clauses: "X does A; Y does B" balanced for symmetry alone.
- Validate-then-precise: "That's correct, and we can make it precise."
Vary the openers. Don't answer three messages in a row with the same shape.
Agents.md is such a ridiculous concept, just write good contributing docs and then optionally @ the file in whatever agetn file you use.
That way everyone benefits.
No, why should I have to remember to @ in every prompt? Or ask contributors to remember. It just makes it easier to make human mistakes. I have better things to do than micromanagement. There is huge value in auto-included context.
The GP wrote @ it from the agents.md file, not from the prompt. Their point was that instead of writing "how to contribute" instructions for agents, you could explain that in the CONTRIBUTING.md and link it from your agents file, so both humans and agents read it from one place.
Symlinks exist, but it's kind of ridiculous all harnesses just ignore CONTRIBUTING, HACKING and friends.
You put the @ in the context file the LLMs all use, claudemd agentsmd whatever the thing that most harnesses force load.
Then the model will go discover what it needs to.