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.
How do you stop LLMs from making comments? In my experience, LLMs treat requirements for code output as suggestions
Ask the agent to write a script to run after each changes, against the newly added code.
Use that script as a super linter.
Thatās the only way I found to strictly enforce some rules, like the no comments rule, without enforcing them against my own changes or old code.
If you donāt trust the code to write a decent comment, why trust it write good code?
Of course, ensuring compilation or other checks can verify some code, which it canāt do for comments. But comments still serve the same purpose as human comments.
That seems like a really smart workflow
I wish my coworkers would adopt this.
Iām sick of reading a fucking Charles dickens novel for every fucking tiny function
[flagged]
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.
[dead]
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!
Honestly? Thatās the kicker.
Hmm, I guess everyone here is using Claude? I find that Sol is much more restrained, to the point where I have a prompt to tell it to add short comments for things that are not obvious. Really, I find the verbosity problem to be worse in tests. I regularly prompt my review agent to remove tests used only for scaffolding to write the code in the first place. The agent is in a way following strict TDD, which reminds me why I donāt like TDD, even though some of the generated tests can be useful.
I tell the agent to NEVER write comments in the system prompt and it ignore it like 90% of the time. RLHF is a helluva drug.
We trained agents on millions of pages of documentation telling them to write good comments and good code and then we tell them never to write any comments.
Itās almost the āwe built a robot who loves to play Sonatas and gave it no handsā type of thing.
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 āāā
> A bunch of these should be enforce with linting
Agreed. One of the first rules I toss into Biome is `noNestedTernary` - LLMs seem to adore completely unreadable nested expressions.
> - Keep function names short. Less than 30 characters.
Recently I asked GPT to port a browser game to Rust. It voluntered this gem:
draw_image_with_html_image_element_and_sw_and_sh_and_dx_and_dy_and_dw_and_dh(...)
I thought it was smoking some good stuff, but it turned out, that is actually the name of the function!
https://docs.rs/web-sys/latest/web_sys/struct.CanvasRenderin...
They laughed at objective-c back then, now the shoe's on the other foot
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.
It's interesting to read these things.
I would describe this as 13 code writing rules (interpreted to be at least 16 - Starting with reduce code indentation) plus a commit message instruction set which I chose to ignore - because it's style-specific and not interesting to me.
8 or 9 of these rules are not necessary. Basic CS is not something I have needed to ask agents, I use, to follow. eg Explaining that you need explicit interfaces is not a necessary instruction, nor is leveraging early return.
Unclear instructions are of limited utility. What "Let the reader of the code breathe" or "reduce code indentation" means is subjective and will rarely be effective. Maybe the training for the language being used has gaps, which others do not. If you want to measure, ask it to output a string when it applies a rule. You'll figure out what works, what doesn't and how often, quickly.
There's 3 or 4 style choices included.
The rest are not something I would use, but we all get burned by different things so I get it.
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.
Yes, the interesting part about seeing other people's agent.md files, is getting to see what issues they have with working with agents. Seems different people run into very different issues, which probably is caused by how differently we work. So a the file probably should be personalised.
Might also be per model. Different models might have different issues and require different instructions
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.
> As much as possible try to minimize the number of changed lines when implementing a feature
Great way to get LLMs to start making an endless profusion of methods instead of adding parameters to or switching to a richer return type from an existing method, in my experience.
Iām tired of seeing āget_total_rounded_upā + āget_total_floatā bloat when a few changes to unrelated code to round floats to ints would keep the method API surface small.
An earlier version of Gemini used to do this a lot to me back when I used it for some light tinkering around on my projects. "Oh by the way, I fixed a misspelling in a comment file completely unrelated to the feature you asked for, so I fixed that as well, shall I commit everything now?" GAHHH. NO.
These days I have an instruction in my default AGENTS.md to bring issues unrelated to the prompt to my attention when found, but never to just automatically fix them.
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.
Do you give the model access to the ASD-STE100 spec for reference/review or are you just assuming that enough of it is baked into the model for it to mostly adhere to it?
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
Agreed. ASD-STE100 makes automated code reviews tolerable.
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.
Get a daily email with the the top stories from Hacker News. No spam, unsubscribe at any time.