<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: John Young</title>
    <description>The latest articles on DEV Community by John Young (@johnayoung).</description>
    <link>https://dev.to/johnayoung</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F982173%2Fbae3202f-5bd5-4bb9-a29f-dce02da5c2f0.png</url>
      <title>DEV Community: John Young</title>
      <link>https://dev.to/johnayoung</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/johnayoung"/>
    <language>en</language>
    <item>
      <title>How to Structure CLAUDE.md: It's a Loading Policy, Not a Document</title>
      <dc:creator>John Young</dc:creator>
      <pubDate>Mon, 27 Jul 2026 14:14:24 +0000</pubDate>
      <link>https://dev.to/johnayoung/how-to-structure-claudemd-its-a-loading-policy-not-a-document-41op</link>
      <guid>https://dev.to/johnayoung/how-to-structure-claudemd-its-a-loading-policy-not-a-document-41op</guid>
      <description>&lt;p&gt;When a developer filed a bug titled &lt;code&gt;[BUG] Claude Code continually ignores CLAUDE.MD file&lt;/code&gt;, Anthropic closed it not-planned and labeled it &lt;code&gt;area:model&lt;/code&gt; — bug-tracker shorthand for &lt;em&gt;this is not a defect we can patch&lt;/em&gt; (&lt;a href="https://github.com/anthropics/claude-code/issues/34197" rel="noopener noreferrer"&gt;anthropics/claude-code#34197&lt;/a&gt;). The report carried its own confession, pasted straight from the session that triggered it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The rules are clear in the CLAUDE.md and memory files — read them, I know them, and I still violated them.&lt;br&gt;
— &lt;a href="https://github.com/anthropics/claude-code/issues/34197" rel="noopener noreferrer"&gt;GitHub: anthropics/claude-code#34197&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the model knows the rules and breaks them anyway, a longer, sterner CLAUDE.md is not the fix. The fix is structural: CLAUDE.md is not a document you fill, it is a loading policy you configure. Most of what goes wrong is content sitting in the wrong tier — billed to every session whether that session needs it or not.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Loading Tiers Claude Code Already Runs
&lt;/h2&gt;

&lt;p&gt;Before you decide what belongs in a CLAUDE.md, look at where it loads — because Claude Code already sorts your instructions into three tiers, and the tier decides the bill.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CLAUDE.md and CLAUDE.local.md files in the directory hierarchy above the working directory are loaded in full at launch. Files in subdirectories load on demand when Claude reads files in those directories.&lt;br&gt;
— &lt;a href="https://code.claude.com/docs/en/memory" rel="noopener noreferrer"&gt;Claude Code Docs: How Claude remembers your project&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That splits your configuration into three tiers with three different costs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;What lives here&lt;/th&gt;
&lt;th&gt;When it loads&lt;/th&gt;
&lt;th&gt;Who pays&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Always-loaded&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Root and ancestor &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;@&lt;/code&gt;-imports, unscoped &lt;code&gt;.claude/rules/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;In full, at launch&lt;/td&gt;
&lt;td&gt;Every session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pay-per-read&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Subdirectory &lt;code&gt;CLAUDE.md&lt;/code&gt;, path-scoped rules&lt;/td&gt;
&lt;td&gt;When Claude reads a matching file&lt;/td&gt;
&lt;td&gt;Only sessions that touch that code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pay-per-trigger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;~100-token blurb always; body on trigger&lt;/td&gt;
&lt;td&gt;Only sessions that invoke it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pay-per-read tier is lazy and file-access-triggered, not a startup scan — Claude Code's creator confirmed as much when he closed a request to make subdirectory loading eager: Claude automatically reads a subdirectory's &lt;code&gt;CLAUDE.md&lt;/code&gt; as it works on files in that directory (&lt;a href="https://github.com/anthropics/claude-code/issues/4275" rel="noopener noreferrer"&gt;anthropics/claude-code#4275&lt;/a&gt;). The vendor's large-codebases guidance describes the same additive behavior — "root file for the big picture, subdirectory files for local conventions" (&lt;a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start" rel="noopener noreferrer"&gt;Claude by Anthropic: Large codebases&lt;/a&gt;). The pay-per-trigger tier is quantified: a skill costs roughly 100 tokens of always-loaded metadata, and its body — under 5k tokens — enters the context window only when the skill fires (&lt;a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview" rel="noopener noreferrer"&gt;Anthropic: Agent Skills overview&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This is &lt;a href="https://jyoung.dev/blog/anatomy-of-a-perfect-ai-agent-task/" rel="noopener noreferrer"&gt;context engineering&lt;/a&gt;, and Anthropic frames it that way: "Context, therefore, must be treated as a finite resource with diminishing marginal returns," with CLAUDE.md as the part "naively dropped into context up front" while glob and grep retrieve the rest just-in-time (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic: Effective context engineering&lt;/a&gt;). The always-loaded tier is exactly that — in context at the start of every session, before you type a word (&lt;a href="https://claude.com/blog/using-claude-md-files" rel="noopener noreferrer"&gt;Claude by Anthropic: Using CLAUDE.md files&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Now take a real file. A developer split a 2,100-line CLAUDE.md into a 150-line core plus five &lt;code&gt;@&lt;/code&gt;-imported docs — &lt;code&gt;testing.md&lt;/code&gt; (270 lines), &lt;code&gt;typescript.md&lt;/code&gt; (305), &lt;code&gt;code-style.md&lt;/code&gt; (370), &lt;code&gt;workflow.md&lt;/code&gt; (671), and &lt;code&gt;examples.md&lt;/code&gt; (278) — the tidy, modular layout every "keep it lean" guide recommends (&lt;a href="https://github.com/anthropics/claude-code/issues/11759" rel="noopener noreferrer"&gt;anthropics/claude-code#11759&lt;/a&gt;). Map it onto the table and the tidiness evaporates. &lt;code&gt;@&lt;/code&gt;-imports load at launch, so all six files ride the always-loaded tier. The split changed the file browser, not the bill. This corpus recurs in every section below — it already made the naive fix and measured the result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the Pay-Per-Read Tier on Your Own Surface
&lt;/h3&gt;

&lt;p&gt;The pay-per-read tier is documented design, but it has a reliability caveat — confirm it before you bet directory conventions on it. It has unresolved reports of not firing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When subdirectory conventions get silently ignored, suspect the surface.&lt;/strong&gt; Nested loading has been reported broken on the VS Code extension while the CLI reportedly works (&lt;a href="https://github.com/anthropics/claude-code/issues/24987" rel="noopener noreferrer"&gt;anthropics/claude-code#24987&lt;/a&gt;). An earlier macOS report was closed not-planned without a fix (&lt;a href="https://github.com/anthropics/claude-code/issues/2571" rel="noopener noreferrer"&gt;anthropics/claude-code#2571&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Before you rely on a nested file, run &lt;code&gt;/memory&lt;/code&gt;.&lt;/strong&gt; It lists every CLAUDE.md, CLAUDE.local.md, and rules file loaded in the current session; if the file you expect isn't listed, Claude can't see it (&lt;a href="https://code.claude.com/docs/en/memory" rel="noopener noreferrer"&gt;Claude Code Docs: How Claude remembers your project&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat the lazy tiers as just-in-time retrieval, with JIT's failure modes.&lt;/strong&gt; They pull content in as Claude navigates — powerful, but with quiet ways to break down, which is the subject of a &lt;a href="https://jyoung.dev/blog/jit-context-retrieval-failure/" rel="noopener noreferrer"&gt;separate post on where lazy retrieval silently fails&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Over-Specified CLAUDE.md Is a Named Failure Mode
&lt;/h2&gt;

&lt;p&gt;Prune your CLAUDE.md on adherence grounds, not tidiness. Past the file's attention budget, every rule you add subtracts from the ones already there. The rules you actually need to &lt;a href="https://jyoung.dev/blog/how-to-size-tasks-for-ai-coding-agents/" rel="noopener noreferrer"&gt;land a change on the first try&lt;/a&gt; are the ones that get buried. Anthropic names the pattern directly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The over-specified CLAUDE.md. If your CLAUDE.md is too long, Claude ignores half of it because important rules get lost in the noise.&lt;br&gt;
— &lt;a href="https://code.claude.com/docs/en/best-practices" rel="noopener noreferrer"&gt;Claude Code Docs: Best practices&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is measured, not folklore. IFScale, a benchmark that scales a single prompt from 10 to 500 simultaneous instructions, found that even the best frontier models top out at 68% accuracy once you hit 500 — and their bias toward earlier instructions peaks around 150–200 (&lt;a href="https://arxiv.org/abs/2507.11538" rel="noopener noreferrer"&gt;arXiv: How Many Instructions Can LLMs Follow at Once?&lt;/a&gt;). The instruction ceiling is real and closer than it looks, which is the whole argument of the &lt;a href="https://jyoung.dev/blog/claude-md-instruction-ceiling/" rel="noopener noreferrer"&gt;companion post on the root file's budget&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The mechanism is well-documented and not specific to CLAUDE.md. Chroma's context-rot study across 18 models found performance grows unreliable as input length grows, and that distractors compound:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even a single distractor reduces performance relative to the baseline (needle only), and adding four distractors compounds this degradation further.&lt;br&gt;
— &lt;a href="https://www.trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It gets worse with position — models are worst at using information stranded in the middle of a long context (&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Liu et al.: Lost in the Middle&lt;/a&gt;) — and worse with sheer length: one study measured accuracy dropping 13.9–85% as input grew, even when the model could perfectly retrieve every relevant fact (&lt;a href="https://aclanthology.org/2025.findings-emnlp.1264/" rel="noopener noreferrer"&gt;Du et al.: Context Length Alone Hurts LLM Performance&lt;/a&gt;). A single irrelevant sentence is enough to derail a problem the model solves cleanly without it (&lt;a href="https://arxiv.org/abs/2302.00093" rel="noopener noreferrer"&gt;Shi et al.: Distracted by Irrelevant Context&lt;/a&gt;); on a controlled reasoning benchmark, step accuracy fell from 26% to 2% as distractors climbed from one to fifteen (&lt;a href="https://arxiv.org/abs/2505.18761" rel="noopener noreferrer"&gt;arXiv: GSM-DC&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;One honest caveat keeps this from overreaching. Truly unrelated filler — text with no plausible bearing on the task — mostly costs latency, not accuracy: one study saturated a 70B model with 15,000 words of generic noise and watched accuracy fall only from 98.5% to 98%, while latency rose 719.64% (&lt;a href="https://arxiv.org/abs/2601.11564" rel="noopener noreferrer"&gt;Ponnusamy et al.: Context Discipline and Performance&lt;/a&gt;). The accuracy damage comes from the plausible-but-inapplicable line — the TypeScript convention that looks relevant during a bash task. So the rule is not "delete everything." It is: treat each non-universal line as a suspect, because the ones that read like they might apply are the ones that do the damage.&lt;/p&gt;

&lt;p&gt;That is what makes the corpus above worse than a monolith. Its author measured that 85–90% of the loaded content is irrelevant to most conversations (&lt;a href="https://github.com/anthropics/claude-code/issues/11759" rel="noopener noreferrer"&gt;anthropics/claude-code#11759&lt;/a&gt;). Most of its per-session tax buys distraction, not guidance — 2,100 lines competing for an attention budget that starts thinning well before 500 instructions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why @imports Won't Save You
&lt;/h2&gt;

&lt;p&gt;When a CLAUDE.md gets too long, the reflex is to break it apart with &lt;code&gt;@path&lt;/code&gt; imports and call it lean. That reflex is wrong, and it is wrong in a specific, measurable way: splitting the file is organization, not load reduction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt; the 2,100-line file split into a 150-line core with five &lt;code&gt;@docs/*.md&lt;/code&gt; imports. Reads modular. Loads identically — all ~2,100 lines enter context at launch, every session. The author who built exactly this split measured the outcome: "the same tokens as a monolithic file, providing organizational benefits only" (&lt;a href="https://github.com/anthropics/claude-code/issues/11759" rel="noopener noreferrer"&gt;anthropics/claude-code#11759&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt; the same content moved to tiers that actually gate loading. &lt;code&gt;typescript.md&lt;/code&gt; becomes a path-scoped rule that loads only when Claude touches &lt;code&gt;.ts&lt;/code&gt; files; &lt;code&gt;workflow.md&lt;/code&gt; becomes a skill that loads only when invoked. Now a bash-only session pays for none of it.&lt;/p&gt;

&lt;p&gt;The documentation states the mechanic plainly, and states it more than once:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Splitting into &lt;a class="mentioned-user" href="https://dev.to/path"&gt;@path&lt;/a&gt; imports helps organization but does not reduce context, since imported files load at launch.&lt;br&gt;
— &lt;a href="https://code.claude.com/docs/en/memory" rel="noopener noreferrer"&gt;Claude Code Docs: How Claude remembers your project&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This matters because the wrong model is actively taught. One popular guide frames &lt;code&gt;@&lt;/code&gt;-imports as pure leanness — "Put detailed instructions in separate markdown files, then reference them. Claude pulls in the content when relevant" (&lt;a href="https://www.builder.io/blog/claude-md-guide" rel="noopener noreferrer"&gt;Builder.io: How to Write a Good CLAUDE.md&lt;/a&gt;). "When relevant" is exactly what imports do not do; they load at launch, relevant or not. Even the guides that state the mechanic correctly — imports "do not reduce context usage" because the "content is expanded inline and still counts against the active window" (&lt;a href="https://medium.com/@bijit211987/the-complete-guide-to-claude-md-memory-rules-loading-and-cross-tool-compression-97cc12ed037b" rel="noopener noreferrer"&gt;Bijit Ghosh: The Complete Guide to CLAUDE.md&lt;/a&gt;) — stop at the mechanic and never turn it into a placement rule. That rule is the next section.&lt;/p&gt;




&lt;h2&gt;
  
  
  Route Every Line by the Sessions That Need It
&lt;/h2&gt;

&lt;p&gt;Here is the fix that actually holds. For every line in your CLAUDE.md, ask one question — &lt;em&gt;which sessions need this?&lt;/em&gt; — and let the answer pick the tier. That is Anthropic's own instruction: "If an entry is a multi-step procedure or only matters for one part of the codebase, move it to a skill or a path-scoped rule instead" (&lt;a href="https://code.claude.com/docs/en/memory" rel="noopener noreferrer"&gt;Claude Code Docs: How Claude remembers your project&lt;/a&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Content class&lt;/th&gt;
&lt;th&gt;Route to&lt;/th&gt;
&lt;th&gt;Loads when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Facts every session needs&lt;/strong&gt; — build commands, "always do X", critical gotchas&lt;/td&gt;
&lt;td&gt;Root &lt;code&gt;CLAUDE.md&lt;/code&gt;, kept short&lt;/td&gt;
&lt;td&gt;In full, at launch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Conventions for one file type or directory&lt;/strong&gt; — a &lt;code&gt;.ts&lt;/code&gt; style rule, a package's local rules&lt;/td&gt;
&lt;td&gt;Path-scoped rule or nested &lt;code&gt;CLAUDE.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Claude reads a matching file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;A procedure or occasional reference&lt;/strong&gt; — a multi-step workflow, a bank of examples&lt;/td&gt;
&lt;td&gt;A skill&lt;/td&gt;
&lt;td&gt;Metadata always; body on trigger&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The skills row is where the docs are most direct: "CLAUDE.md is loaded every session, so only include things that apply broadly. For domain knowledge or workflows that are only relevant sometimes, use skills instead" (&lt;a href="https://code.claude.com/docs/en/best-practices" rel="noopener noreferrer"&gt;Claude Code Docs: Best practices&lt;/a&gt;). Named practitioners land in the same place — a skill "only takes up a few dozen extra tokens, with the full details only loaded in should the user request a task that the skill can help solve" (&lt;a href="https://simonwillison.net/2025/Oct/16/claude-skills/" rel="noopener noreferrer"&gt;Simon Willison: Claude Skills&lt;/a&gt;). The discipline for the root file is to keep it "concise and universally applicable" (&lt;a href="https://www.humanlayer.dev/blog/skill-issue-harness-engineering-for-coding-agents" rel="noopener noreferrer"&gt;HumanLayer: Skill Issue&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The routing question is therefore not "is this rule good?" but "which sessions should pay for it?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the corpus through it. &lt;code&gt;typescript.md&lt;/code&gt; and &lt;code&gt;code-style.md&lt;/code&gt; govern specific file types — path-scoped rules matching &lt;code&gt;**/*.ts&lt;/code&gt; and your source globs, loaded only when Claude edits those files. &lt;code&gt;testing.md&lt;/code&gt; rides along with the test files it describes. &lt;code&gt;workflow.md&lt;/code&gt; (671 lines of TDD procedure) and &lt;code&gt;examples.md&lt;/code&gt; (278 lines of patterns) are a procedure and a reference bank — skills, bodies loaded only on trigger. Layer boundaries are the natural seams here: what governs one layer routes to that layer's files. What is left of the 150-line core shrinks toward what the root is actually for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The root file should be pointers and critical gotchas only; everything else drifts into noise.&lt;br&gt;
— &lt;a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start" rel="noopener noreferrer"&gt;Claude by Anthropic: Large codebases&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is not an aspiration. HumanLayer's production root CLAUDE.md runs "less than sixty lines," on the rule to "Prefer pointers to copies" (&lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer: Writing a good CLAUDE.md&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  On-Demand Is Not Free Once It Fires
&lt;/h3&gt;

&lt;p&gt;Routing to a skill is not a free lunch, and pretending otherwise sets a footgun. A skill's body stays out of context until something triggers it — but once it fires, it stays:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you or Claude invoke a skill, the rendered SKILL.md content enters the conversation as a single message and stays there for the rest of the session.&lt;br&gt;
— &lt;a href="https://code.claude.com/docs/en/skills" rel="noopener noreferrer"&gt;Claude Code Docs: Extend Claude with skills&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So a triggered skill is a recurring cost from that point on, not a one-time read. The routing win is real — a bash-only session never pays for your TDD skill — but budget the skill body as if it will load, because in the sessions that need it, it does, and it lingers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Measured Cost of a Wrongly Routed Line
&lt;/h2&gt;

&lt;p&gt;Here is the failure mode people underweight. A rule in the wrong tier is not quietly ignored — it is dutifully obeyed, at &lt;a href="https://jyoung.dev/blog/per-task-cost-attribution/" rel="noopener noreferrer"&gt;a price you can measure&lt;/a&gt;. A benchmark of repository context files across multiple coding agents found the compliance itself is the cost: the files "tend to reduce task success rates compared to providing no repository context, while also increasing inference cost by over 20%" (&lt;a href="https://arxiv.org/html/2602.11988v1" rel="noopener noreferrer"&gt;Gloaguen et al.: Evaluating AGENTS.md&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The measured penalty, across SWE-bench Lite and a benchmark of developer-written files (&lt;a href="https://arxiv.org/html/2602.11988v1" rel="noopener noreferrer"&gt;Gloaguen et al.: Evaluating AGENTS.md&lt;/a&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the study measured&lt;/th&gt;
&lt;th&gt;Result with a repository context file&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Task success / resolution rate&lt;/td&gt;
&lt;td&gt;Lower than the no-context baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inference cost&lt;/td&gt;
&lt;td&gt;+20–23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra steps per task&lt;/td&gt;
&lt;td&gt;+2.45 and +3.92 across the two benchmarks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The mechanism is obedience — "agents generally follow instructions present in the context files" — so a misplaced line is therefore not inert weight; it is an instruction the agent will burn steps satisfying. And the thing most root files try hardest to do — narrate the codebase — is the thing the same study found they fail at. Context files "are not effective at providing a repository overview."&lt;/p&gt;

&lt;p&gt;Put the two failure modes together and the corpus's real cost comes into focus. The rules you need get lost in the noise (the over-specified failure), and the rules you don't need get executed anyway (the compliance cost). The 2,100-line always-loaded corpus pays both, every session — including the ones that only touch a bash script — to carry content its own author measured as 85–90% irrelevant. That is pure context burn.&lt;/p&gt;

&lt;p&gt;And because it is a per-session cost, it compounds. In an iterative loop that restarts context repeatedly, the misrouted tax is paid on every pass — the &lt;a href="https://jyoung.dev/blog/loop-engineering-breaks-your-playbook/" rel="noopener noreferrer"&gt;recurring-cost problem that breaks playbooks built for one-shot sessions&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Routing Flowchart for Every Line You Keep
&lt;/h2&gt;

&lt;p&gt;You do not need a quarterly re-prune ritual. You need to run each line you keep through one decision path — and then most of the pruning takes care of itself. Ask these in order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it needed in every session?&lt;/strong&gt;&lt;br&gt;
→ Root file — but it now competes for &lt;a href="https://jyoung.dev/blog/claude-md-instruction-ceiling/" rel="noopener noreferrer"&gt;the adherence budget that caps out well before 500 instructions&lt;/a&gt;. Keep it to pointers and critical gotchas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it needed in one directory or file type?&lt;/strong&gt;&lt;br&gt;
→ Nested &lt;code&gt;CLAUDE.md&lt;/code&gt; or path-scoped rule — the pay-per-read tier. Verify it loads on your surface with &lt;code&gt;/memory&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a procedure or an occasional reference?&lt;/strong&gt;&lt;br&gt;
→ Skill — pay-per-trigger. Budget the body anyway; once it fires it sticks for the session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you just want the file shorter?&lt;/strong&gt;&lt;br&gt;
→ That is organization, not savings. &lt;code&gt;@&lt;/code&gt;-imports change nothing — they load at launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can't say which sessions need it?&lt;/strong&gt;&lt;br&gt;
→ Delete it. Every surviving line binds and bills.&lt;/p&gt;

&lt;p&gt;Run the corpus through the gates and it lands where it should have started: a ~150-line root of pointers and gotchas, three path-scoped files next to the code they govern, and two skills that load only when invoked. Same content, a fraction of the per-session tax, and no standing re-prune ritual — Anthropic's own cadence is a configuration review every three to six months, not a weekly file diet (&lt;a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start" rel="noopener noreferrer"&gt;Claude by Anthropic: Large codebases&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You do not have to run this flowchart by hand. I packaged it as a Claude Code skill — &lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;agent-engineering-toolkit&lt;/a&gt; — that inventories your repo's three tiers, expands every &lt;code&gt;@&lt;/code&gt;-import, totals the real always-loaded token cost, and emits the routing report above. It is the audit I ran on my own repos while writing this.&lt;/p&gt;

&lt;p&gt;And the skill transfers. The same nearest-file hierarchy is now the cross-tool &lt;code&gt;AGENTS.md&lt;/code&gt; convention — "Agents automatically read the nearest file in the directory tree, so the closest one takes precedence and every subproject can ship tailored instructions" (&lt;a href="https://agents.md/" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt;) — with the same discipline attached: keep the root short and push specifics down the tree (&lt;a href="https://addyosmani.com/agents/15-agents-md/" rel="noopener noreferrer"&gt;Addy Osmani: AGENTS.md&lt;/a&gt;). Route by tier once and the discipline is portable.&lt;/p&gt;

&lt;p&gt;The pay-per-read and pay-per-trigger tiers you just routed into are just-in-time retrieval by another name — and just-in-time retrieval has failure modes of its own. That is the next thing worth understanding before you push your whole config into the lazy tiers: &lt;a href="https://jyoung.dev/blog/jit-context-retrieval-failure/" rel="noopener noreferrer"&gt;where lazy retrieval silently breaks&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Research and Data
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot — Hong, Troynikov, Huber&lt;/a&gt; — Across 18 LLMs, model performance grows unreliable as input length grows, and even one topically-plausible distractor measurably degrades it. Backs the degradation-by-analogy argument.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2507.11538" rel="noopener noreferrer"&gt;arXiv: How Many Instructions Can LLMs Follow at Once?&lt;/a&gt; — The best frontier models reach only 68% accuracy at 500 simultaneous instructions, with the early-instruction bias peaking around 150–200. Backs the instruction-ceiling claim.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Liu et al.: Lost in the Middle&lt;/a&gt; — Models are worst at using information stranded in the middle of a long context. Backs the position-dependence point.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aclanthology.org/2025.findings-emnlp.1264/" rel="noopener noreferrer"&gt;Du et al.: Context Length Alone Hurts LLM Performance&lt;/a&gt; — Accuracy drops 13.9–85% as input grows even under perfect retrieval, well within claimed context windows. Backs the length-alone degradation point.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2302.00093" rel="noopener noreferrer"&gt;Shi et al.: Distracted by Irrelevant Context&lt;/a&gt; — A single irrelevant sentence degrades accuracy on problems the model otherwise solves cleanly. Backs the distraction mechanism.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2505.18761" rel="noopener noreferrer"&gt;arXiv: GSM-DC — Reasoning Distracted by Irrelevant Context&lt;/a&gt; — GPT-4.1 step accuracy falls from 26% to 2% as distractors climb from one to fifteen. Backs distractor compounding.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2601.11564" rel="noopener noreferrer"&gt;Ponnusamy et al.: Context Discipline and Performance&lt;/a&gt; — A 70B model held 98% accuracy under 15,000 words of generic filler while latency rose 719.64%. Backs the honest caveat that unrelated filler costs latency, not accuracy.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/html/2602.11988v1" rel="noopener noreferrer"&gt;Gloaguen et al.: Evaluating AGENTS.md&lt;/a&gt; — Repository context files reduced task success while raising inference cost over 20%, because agents comply with everything the file says, and are not effective at providing a repository overview. Backs the measured-cost section.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Practitioner Guidance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://code.claude.com/docs/en/memory" rel="noopener noreferrer"&gt;Claude Code Docs: How Claude remembers your project&lt;/a&gt; — Ancestor CLAUDE.md files load in full at launch, subdirectory files load on demand when Claude reads files there, and @imports load at launch without reducing context. The loading-policy spec the whole post routes against.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.claude.com/docs/en/best-practices" rel="noopener noreferrer"&gt;Claude Code Docs: Best practices for Claude Code&lt;/a&gt; — "The over-specified CLAUDE.md" is a named failure: too long and Claude ignores half of it, so route sometimes-relevant content to skills. Backs the prune-on-adherence and routing sections.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start" rel="noopener noreferrer"&gt;Claude by Anthropic: How Claude Code works in large codebases&lt;/a&gt; — Root file should be pointers and critical gotchas only, Claude loads files additively as it moves through the codebase, and teams should review configuration every three to six months. Backs the root-scope rule and the cadence.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic: Effective context engineering for AI agents&lt;/a&gt; — Context is a finite resource with diminishing marginal returns; CLAUDE.md is dropped in up front while glob and grep retrieve just-in-time. Backs the finite-budget and hybrid-tier framing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview" rel="noopener noreferrer"&gt;Anthropic: Agent Skills overview&lt;/a&gt; — Progressive disclosure: ~100 tokens of metadata always loaded, the under-5k body only when triggered, resources effectively unlimited. Backs the pay-per-trigger cost model.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.claude.com/docs/en/skills" rel="noopener noreferrer"&gt;Claude Code Docs: Extend Claude with skills&lt;/a&gt; — A skill's body loads only when used, but once invoked it stays in context for the rest of the session. Backs the routing rule and the on-demand-is-not-free caveat.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://claude.com/blog/using-claude-md-files" rel="noopener noreferrer"&gt;Claude by Anthropic: Using CLAUDE.md files&lt;/a&gt; — Every conversation starts with the always-loaded context already in place. Backs the every-session recurring-cost framing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.builder.io/blog/claude-md-guide" rel="noopener noreferrer"&gt;Builder.io: How to Write a Good CLAUDE.md File — Gopinath&lt;/a&gt; — Frames @imports as "Claude pulls in the content when relevant," the naive model the loading docs refute. The SERP foil in the @imports section.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/@bijit211987/the-complete-guide-to-claude-md-memory-rules-loading-and-cross-tool-compression-97cc12ed037b" rel="noopener noreferrer"&gt;Bijit Ghosh: The Complete Guide to CLAUDE.md&lt;/a&gt; — States correctly that imports don't reduce context usage, but never turns the mechanic into a placement rule. The gap the post fills.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/2025/Oct/16/claude-skills/" rel="noopener noreferrer"&gt;Simon Willison: Claude Skills are awesome&lt;/a&gt; — Each skill costs a few dozen extra tokens until invoked. Named-author validation of metadata-first loading.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer: Writing a good CLAUDE.md — Kyle&lt;/a&gt; — HumanLayer's root CLAUDE.md runs under sixty lines on the rule to prefer pointers to copies. Backs the trimmed-root target.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.humanlayer.dev/blog/skill-issue-harness-engineering-for-coding-agents" rel="noopener noreferrer"&gt;HumanLayer: Skill Issue — Harness Engineering for Coding Agents&lt;/a&gt; — Keep CLAUDE.md concise and universally applicable. Backs the route-by-scope rule.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://agents.md/" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt; — Agents read the nearest file in the directory tree, so the closest one takes precedence. Backs the cross-tool generalization.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://addyosmani.com/agents/15-agents-md/" rel="noopener noreferrer"&gt;Addy Osmani: Lesson 16 — AGENTS.md&lt;/a&gt; — Agents read the nearest file in the current directory or its parents; aim for 150 lines or fewer. Backs the cross-tool close.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/34197" rel="noopener noreferrer"&gt;anthropics/claude-code#34197&lt;/a&gt; — "Claude ignores my CLAUDE.md" closed not-planned and labeled area:model, locating the failure in model behavior rather than fixable tooling. The hook.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/4275" rel="noopener noreferrer"&gt;anthropics/claude-code#4275&lt;/a&gt; — Boris Cherny confirms subdirectory CLAUDE.md files load lazily as Claude works on files there. Backs the pay-per-read tier.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/11759" rel="noopener noreferrer"&gt;anthropics/claude-code#11759&lt;/a&gt; — A 2,100-line CLAUDE.md split across six @-imported files consumed the same tokens as a monolith, ~85–90% irrelevant to most conversations. The running-thread artifact.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/24987" rel="noopener noreferrer"&gt;anthropics/claude-code#24987&lt;/a&gt; — Subdirectory CLAUDE.md files reported not loading on the VS Code extension while the CLI works. Backs the verify-your-surface caveat.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/2571" rel="noopener noreferrer"&gt;anthropics/claude-code#2571&lt;/a&gt; — Subdirectory CLAUDE.md files reported not auto-loading on macOS, closed not-planned. Backs the reliability caveat.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;agent-engineering-toolkit: audit-claude-md&lt;/a&gt; — This post's routing flowchart as a runnable Claude Code skill: tier inventory, &lt;a class="mentioned-user" href="https://dev.to/import"&gt;@import&lt;/a&gt; expansion, token estimates, and a per-section routing report. MIT-licensed, runs standalone.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Author's Judgment (not directly sourced)
&lt;/h3&gt;

&lt;p&gt;The following framings are my own synthesis. They follow logically from the sourced material above, but no source states them directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"CLAUDE.md is a loading policy, not a document"&lt;/strong&gt; — my lens on the mechanics; follows from Anthropic's documented tiers (memory docs), which describe the loading behavior but never frame the file this way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying the context-rot and instruction-density literature to CLAUDE.md&lt;/strong&gt; — Chroma, IFScale, Liu, Du, Shi, GSM-DC, and Ponnusamy never test CLAUDE.md itself; the transfer is my analogy, disclosed in-prose as "not specific to CLAUDE.md."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "quarterly re-prune ritual" the flowchart retires&lt;/strong&gt; — my characterization of the periodic-review habit; Anthropic recommends a three-to-six-month configuration review but does not frame it as a symptom of wrong routing.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Loop Engineering Breaks Your Single-Shot Context Playbook</title>
      <dc:creator>John Young</dc:creator>
      <pubDate>Mon, 27 Jul 2026 14:14:08 +0000</pubDate>
      <link>https://dev.to/johnayoung/loop-engineering-breaks-your-single-shot-context-playbook-d4b</link>
      <guid>https://dev.to/johnayoung/loop-engineering-breaks-your-single-shot-context-playbook-d4b</guid>
      <description>&lt;p&gt;An agent was "just an LLM using tools based on environmental feedback in a loop" a year and a half before anyone sold you "loop engineering" (&lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Anthropic: Building Effective AI Agents&lt;/a&gt;). The term is new; the primitive isn't — and neither is the trap. The CLAUDE.md budget and just-in-time retrieval you spent last quarter tuning for a single invocation don't fail louder when the unit of work becomes many. They fail quieter, and pointing more autonomy at the same bloated context makes it worse, not better.&lt;/p&gt;




&lt;h2&gt;
  
  
  Loop Engineering Is the Primitive You Already Had
&lt;/h2&gt;

&lt;p&gt;Before you buy loop engineering as a greenfield discipline, look at what the loop actually is: the thing an agent already was. Anthropic's definition has not moved since December 2024 — agents "are typically just LLMs using tools based on environmental feedback in a loop" (&lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Anthropic: Building Effective AI Agents&lt;/a&gt;). Simon Willison was calling the design of that loop "a critical new skill to develop" nine months before the label caught on. His working definition is the same one: an LLM agent is "something that runs tools in a loop to achieve a goal" (&lt;a href="https://simonwillison.net/2025/Sep/30/designing-agentic-loops/" rel="noopener noreferrer"&gt;Simon Willison: Designing agentic loops&lt;/a&gt;). The Claude Agent SDK draws the identical cycle as four steps — "gather context -&amp;gt; take action -&amp;gt; verify work -&amp;gt; repeat" (&lt;a href="https://www.anthropic.com/engineering/building-agents-with-the-claude-agent-sdk" rel="noopener noreferrer"&gt;Anthropic: Building agents with the Claude Agent SDK&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So when Addy Osmani defines the new term — "Loop engineering is replacing yourself as the person who prompts the agent. You design the system that does it instead" (&lt;a href="https://addyosmani.com/blog/loop-engineering/" rel="noopener noreferrer"&gt;Addy Osmani: Loop Engineering&lt;/a&gt;) — read it as a shift in &lt;em&gt;who runs the loop&lt;/em&gt;, not the arrival of a new mechanism. The primitive is the same gather/act/verify cycle you have been driving by hand; loop engineering is the decision to stop pressing enter between turns.&lt;/p&gt;

&lt;p&gt;The concrete version of "stop pressing enter" is the artifact this whole post keeps returning to: the unattended overnight loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The Ralph loop — a fresh context every iteration, state on disk.&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; :&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;PROMPT.md | agent&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You point it at a &lt;code&gt;PROMPT.md&lt;/code&gt;, walk away in the evening, and read what it built in the morning — the technique Geoffrey Huntley popularized as "Ralph" (&lt;a href="https://ghuntley.com/ralph/" rel="noopener noreferrer"&gt;Geoffrey Huntley: Ralph Wiggum as a "software engineer"&lt;/a&gt;). Nothing in that line is new. It is your single-invocation agent, wrapped in &lt;code&gt;while :; do ... done&lt;/code&gt; and handed the keys.&lt;/p&gt;

&lt;p&gt;The frame is therefore a migration, not a blank slate: &lt;strong&gt;treat loop engineering as your single-invocation habits run many times, not a discipline you learn from zero.&lt;/strong&gt; That reframe tells you where the breakage lives. It is not in the loop syntax — that is one line. It is in every assumption you baked into the playbook when the unit of work was one invocation and the context window reset the moment the task finished. A loop keeps the seat warm.&lt;/p&gt;

&lt;p&gt;This axis is worth naming precisely, because it is easy to confuse with the other one. A loop is one agent iterating sequentially — the same context lineage, turn after turn. Running many agents in parallel is a different problem with different failure modes, the isolation and hand-off concerns I covered in &lt;a href="https://jyoung.dev/blog/multi-agent-context-isolation/" rel="noopener noreferrer"&gt;multi-agent context isolation&lt;/a&gt;. Loop engineering lives on the sequential axis: not more agents, more iterations of one. Why it matters now is measurable — the length of tasks agents can complete autonomously "with 50% reliability has been doubling approximately every 7 months for the last 6 years" (&lt;a href="https://metr.org/blog/2025-03-19-measuring-ai-ability-to-complete-long-tasks/" rel="noopener noreferrer"&gt;METR: Measuring AI Ability to Complete Long Tasks&lt;/a&gt;). The loops are getting longer, so an assumption that was merely wrong on turn one gets expensive by turn fifty.&lt;/p&gt;




&lt;h2&gt;
  
  
  Audit Your CLAUDE.md as a Per-Iteration Tax
&lt;/h2&gt;

&lt;p&gt;Re-read every "just in case" line in your CLAUDE.md as a charge you re-pay on every iteration, not a fee you settle once. In a single invocation, a bloated instruction file is a fixed cost. The agent loads it, and either the rule near the bottom gets followed or it falls past the &lt;a href="https://jyoung.dev/blog/claude-md-instruction-ceiling/" rel="noopener noreferrer"&gt;instruction ceiling&lt;/a&gt; and gets dropped — silently, once. In a loop, that same file reloads every turn, and each turn stacks its own output on top of it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An agent running in a loop generates more and more data that could be relevant for the next turn of inference, and this information must be cyclically refined.&lt;br&gt;
— &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic: Effective context engineering for AI agents&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Refined&lt;/em&gt; is the operative word — the context does not refine itself. Left alone it grows by default, because "each invocation requires a full inference pass, and intermediate results pile up in context whether they're useful or not" (&lt;a href="https://www.anthropic.com/engineering/advanced-tool-use" rel="noopener noreferrer"&gt;Anthropic: Introducing advanced tool use on the Claude Developer Platform&lt;/a&gt;). The scale that always-on context can reach is easy to underestimate: Anthropic reports having "seen tool definitions consume 134K tokens before optimization" (&lt;a href="https://www.anthropic.com/engineering/advanced-tool-use" rel="noopener noreferrer"&gt;Anthropic: Advanced tool use&lt;/a&gt;). That figure is tool definitions, not your CLAUDE.md — but it is the same shape of problem, an always-on block riding every inference pass whether or not this turn needs it.&lt;/p&gt;

&lt;p&gt;Here is the audit, applied line by line to the file your overnight loop is pointed at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When a line is architecture the agent can read from the repo&lt;/strong&gt; → cut it. It is context burn re-paid every iteration for something a &lt;code&gt;grep&lt;/code&gt; would surface on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a line is a "just in case" preference no real failure ever earned&lt;/strong&gt; → cut it. In one invocation it was one distractor; across fifty iterations it is fifty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a line is a genuine constraint that must hold&lt;/strong&gt; → keep it, phrase it as a runnable check, and move it as high in the file as it will go, because position decays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a line is a hard safety boundary&lt;/strong&gt; → it does not belong in an advisory file at all; a loop with no human at the keyboard is exactly the run where "the agent usually respects this" is not good enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reliability cost of skipping that audit is measured, not asserted. Chroma's study across 18 models and 194,480 calls found that "models do not use their context uniformly; instead, their performance grows increasingly unreliable as input length grows" (&lt;a href="https://www.trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot&lt;/a&gt;). This is not a lone vendor's marketing line — Chroma coined &lt;em&gt;context rot&lt;/em&gt;, and Anthropic documents the same finding on its own product surface: "As token count grows, accuracy and recall degrade, a phenomenon known as context rot" (&lt;a href="https://docs.anthropic.com/en/docs/build-with-claude/context-windows" rel="noopener noreferrer"&gt;Anthropic: Context windows&lt;/a&gt;). &lt;strong&gt;A single invocation pays context rot once; a loop pays it on every turn, and the bill compounds with the output the loop keeps adding.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Presentation Over Presence: Cut for Turn 50
&lt;/h3&gt;

&lt;p&gt;The instinct when a loop misbehaves is to add a line — spell out the rule the agent missed. That optimizes for presence: the rule is now technically in the file. But presence is the wrong target. Chroma's sharper finding is that "whether relevant information is present in a model's context is not all that matters; what matters more is how that information is presented" (&lt;a href="https://www.trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot&lt;/a&gt;). On turn one, a 300-line CLAUDE.md and a 60-line one both technically contain your rule. By turn fifty, with the loop's own output layered on top, the 60-line file is the one where the rule is still legible. Cut and order for how the file reads deep into the run, not for whether the rule is present at the start.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Clean One-Shot Demo Is the Weakest Evidence You Have
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Author's judgment.&lt;/strong&gt; That a loop fails &lt;em&gt;quieter&lt;/em&gt; than the demo — not just more often — is my inference, not a measured result. It follows from two sourced premises: models self-condition on their own prior errors (Sinha et al.), and autonomous runs carry "the potential for compounding errors" (Anthropic). The clean first turn is the least informative data point you have about the fiftieth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A flawless single run is the worst evidence you can bring to a decision about autonomy, because per-step reliability is a different quantity from single-turn reliability, and the gap is measured.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the per-step accuracy of models degrades as the number of steps increases. This is not just due to long-context limitations — curiously, we observe a self-conditioning effect — models become more likely to make mistakes when the context contains their errors from prior turns.&lt;br&gt;
— &lt;a href="https://arxiv.org/abs/2509.09677" rel="noopener noreferrer"&gt;Sinha et al.: The Illusion of Diminishing Returns&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Their sharpest data point cuts directly against extrapolating from a clean demo: "larger models can correctly execute significantly more turns even when small models have near-perfect single-turn accuracy." Single-turn accuracy does not predict how many turns a model survives.&lt;/p&gt;

&lt;p&gt;Carry that result with its caveats, because the honest version is more useful than the scary one. It was measured on a synthetic running-sum task, not a literal tool loop; the same authors find "thinking mitigates self-conditioning"; and, counterintuitively, larger models are &lt;em&gt;more&lt;/em&gt; prone to self-conditioning, not less. &lt;strong&gt;So the claim is not "big models get dumb in loops." It is narrower and harder to dodge: single-shot accuracy doesn't predict loop reliability, and the mechanism that breaks the extrapolation is the model reading its own earlier mistakes as ground truth.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is that mechanism on the running artifact. The overnight loop makes a bad call at iteration 12 — say it edits &lt;code&gt;auth.go&lt;/code&gt; against a misread of the token-refresh flow and commits it. Every iteration after 12 opens a fresh context, reads the repo as it now stands, and finds that wrong &lt;code&gt;auth.go&lt;/code&gt; sitting there as established fact. The loop is no longer debugging its mistake; it is building on it. By 3 a.m. it has spent thirty iterations making the codebase consistent with a decision it never should have made — and the terminal shows steady, confident progress the whole time. That is the compounding-errors path Anthropic warns about (&lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Anthropic: Building Effective AI Agents&lt;/a&gt;), running unattended. The blast radius of one bad call is no longer a single turn you can catch; it is every turn that reads the commit.&lt;/p&gt;

&lt;p&gt;This is why the demo lies by omission. Geoffrey Huntley, who popularized the overnight loop, is blunt about its nondeterminism: Ralph goes off track, and you can wake up to a broken codebase that doesn't compile unless you build in &lt;a href="https://jyoung.dev/blog/evaluating-ai-coding-agent-output/" rel="noopener noreferrer"&gt;programmatic verification&lt;/a&gt; rather than letting the model grade its own work (&lt;a href="https://ghuntley.com/ralph/" rel="noopener noreferrer"&gt;Geoffrey Huntley: Ralph Wiggum as a "software engineer"&lt;/a&gt;). The demo you were shown is the run that shipped clean on the first try and got kept. The runs that went off track do not get recorded — which is precisely why a clean one-shot demo is the weakest evidence in the room.&lt;/p&gt;




&lt;h2&gt;
  
  
  Budget the Two Fields a Single Prompt Never Had
&lt;/h2&gt;

&lt;p&gt;A single prompt has two things a loop does not: a natural end, and a memory that lasts exactly as long as the task. The task finished, the window cleared, and "done" handled both. A loop inherits neither for free — so before you walk away, write a stop spec and a state file.&lt;/p&gt;

&lt;p&gt;Start with the stop. Anthropic's baseline is that "the task often terminates upon completion, but it's also common to include stopping conditions (such as a maximum number of iterations) to maintain control" (&lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Anthropic: Building Effective AI Agents&lt;/a&gt;). The field guide that covers this most concretely names three, and an unattended loop needs all of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Max iteration count&lt;/strong&gt; — a hard ceiling on turns, full stop. Your &lt;code&gt;while :; do ... done&lt;/code&gt; has no upper bound; give it one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No-progress detection&lt;/strong&gt; — if a pass produces no measurable change against the check, halt instead of grinding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A token or dollar budget&lt;/strong&gt; — a hard spend ceiling that ends the run (&lt;a href="https://dev.to/truongpx396/the-agentic-loop-a-practical-field-guide-mnc"&gt;Truong Phung: The Agentic Loop / Loop Engineering: A Practical Field Guide&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hardened version of the running artifact is only a few lines longer, and every added line is a brake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The overnight loop, with the two fields a single prompt never needed.&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MAX_ITERS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;          &lt;span class="c"&gt;# (1) max-iteration ceiling&lt;/span&gt;
  &lt;span class="nb"&gt;cat &lt;/span&gt;PROMPT.md progress.txt | agent        &lt;span class="c"&gt;# externalized state, reloaded each turn&lt;/span&gt;
  ./run_checks.sh &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;                   &lt;span class="c"&gt;# the verification the model doesn't self-grade&lt;/span&gt;
  git add &lt;span class="nt"&gt;-A&lt;/span&gt;
  git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"iter &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;break&lt;/span&gt;          &lt;span class="c"&gt;# (2) nothing to commit -&amp;gt; no progress -&amp;gt; stop&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="c"&gt;# (3) the spend ceiling lives on the wrapper: a wall-clock or token budget that kills the run.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cap makes the run bounded; the failed commit makes each pass verifiable — nothing changed against the check, so the loop stops instead of grinding on. That is what turns an open-ended loop into bounded, verifiable work.&lt;/p&gt;

&lt;p&gt;Then the state. Anthropic's harness work names it exactly: "the core challenge of long-running agents is that they must work in discrete sessions, and each new session begins with no memory of what came before" (&lt;a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents" rel="noopener noreferrer"&gt;Anthropic: Effective harnesses for long-running agents&lt;/a&gt;). Their conclusion is the one that breaks the single-prompt playbook: "even a frontier coding model like Opus 4.5... will fall short of building a production-quality web app if it's only given a high-level prompt." The fix is not a better prompt; it is state on disk — Anthropic reconstructs it "with the claude-progress.txt file alongside the git history," and the field guide reduces it to a line worth taping to your monitor: "the agent forgets; the repo doesn't" (&lt;a href="https://dev.to/truongpx396/the-agentic-loop-a-practical-field-guide-mnc"&gt;Truong Phung&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Carry one version caveat so you don't over-learn the memoryless framing. On newer models the strict "no memory of what came before" is softer than it sounds. Server-side compaction and the Agent SDK's "compact feature automatically summarizes previous messages when the context limit approaches" (&lt;a href="https://www.anthropic.com/engineering/building-agents-with-the-claude-agent-sdk" rel="noopener noreferrer"&gt;Anthropic: Building agents with the Claude Agent SDK&lt;/a&gt;) both blunt the hard session boundary. The mechanism is version-dependent; the discipline is not. Externalized state is what survives a window reset regardless of how gracefully your model compacts, so write the &lt;code&gt;progress.txt&lt;/code&gt; either way.&lt;/p&gt;

&lt;p&gt;State also changes what retrieval means, and this is where the loop reopens a problem you thought you had scoped. Just-in-time retrieval, in a single invocation, is one agent resolving pointers at runtime — and it has its own quiet failure modes (&lt;a href="https://jyoung.dev/blog/jit-context-retrieval-failure/" rel="noopener noreferrer"&gt;where JIT retrieval silently breaks&lt;/a&gt;). A loop adds a second retrieval axis with no single-shot analog: pulling the right slice of &lt;em&gt;its own past sessions&lt;/em&gt; back into a fresh window. Anthropic's managed-agent architecture makes that axis explicit: the session is "a context object that lives outside Claude's context window." A &lt;code&gt;getEvents()&lt;/code&gt; interface "allows the brain to interrogate context by selecting positional slices of the event stream" to pick up where it last stopped (&lt;a href="https://www.anthropic.com/engineering/managed-agents" rel="noopener noreferrer"&gt;Anthropic: Scaling Managed Agents&lt;/a&gt;). That is cross-iteration retrieval, and it is its own discipline. Keep the run's progress log separate from your durable skills and rules, because they answer different questions: what did &lt;em&gt;this run&lt;/em&gt; do, versus what should &lt;em&gt;every run&lt;/em&gt; know.&lt;/p&gt;




&lt;h2&gt;
  
  
  Re-Check Every Assumption Before You Press Go
&lt;/h2&gt;

&lt;p&gt;Do not scale autonomy on a playbook you have not re-derived for many invocations. Every assumption in the table below was safe when the unit of work was one invocation; each one changes when the unit becomes many. Before the overnight loop runs unattended, walk each row and confirm you have an answer — this is the migration made into a checklist.&lt;/p&gt;

&lt;p&gt;That checklist is runnable: &lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;loop-preflight&lt;/a&gt; greps your wrapper for the three brakes, the state file, and the check you don't let the model self-grade, then prices the always-on context your loop re-pays every iteration.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Single-shot assumption&lt;/th&gt;
&lt;th&gt;What changes across many invocations&lt;/th&gt;
&lt;th&gt;Check before you walk away&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Loop engineering is a new skill to learn&lt;/td&gt;
&lt;td&gt;It is the gather/act/verify primitive you already ran, now unattended&lt;/td&gt;
&lt;td&gt;Are you migrating your single-invocation habits, or starting from a blank slate you don't need?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLAUDE.md is a one-time cost paid at load&lt;/td&gt;
&lt;td&gt;It reloads every turn and stacks the loop's own output on top, so context rot compounds&lt;/td&gt;
&lt;td&gt;Did you cut the file for how it reads on turn 50, and move every real constraint above the fold?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A clean demo predicts reliability&lt;/td&gt;
&lt;td&gt;Per-step accuracy decays and the model conditions on its own earlier mistakes, quietly&lt;/td&gt;
&lt;td&gt;Have you budgeted for the run that builds on a 2 a.m. error in &lt;code&gt;auth.go&lt;/code&gt;, not the one you were shown?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Done" ends the task and the window clears it&lt;/td&gt;
&lt;td&gt;Nothing terminates the loop and nothing survives the reset&lt;/td&gt;
&lt;td&gt;Is there a max-iteration cap, no-progress detection, a spend ceiling, and a &lt;code&gt;progress.txt&lt;/code&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The through-line is one sentence. &lt;strong&gt;A loop is many invocations, not one — so the question before you press go is not "is my prompt good?" but "does every assumption I tuned for a single invocation still hold on turn fifty?"&lt;/strong&gt; The single-invocation playbook was not wrong; it was scoped. Loop engineering is what you get when you re-derive it for the unit of work you actually shipped — and the reader who runs that migration keeps the overnight wins instead of the overnight surprises.&lt;/p&gt;

&lt;p&gt;I write one long-form piece at a time on context engineering and agent reliability. If re-deriving the playbook every time the unit of work changes isn't how you want to spend the quarter, &lt;a href="https://jyoung.dev/subscribe/" rel="noopener noreferrer"&gt;subscribe&lt;/a&gt; and the next one lands in your inbox.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Research and Data
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot — How Increasing Input Tokens Impacts LLM Performance (Hong, Troynikov, Huber)&lt;/a&gt; — Across 18 models and 194,480 calls, performance grows increasingly unreliable as input length grows, and presentation matters more than presence. Backs the per-iteration rot and "presentation over presence" sections.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2509.09677" rel="noopener noreferrer"&gt;Sinha, Arun, Goel, Staab, Geiping: The Illusion of Diminishing Returns — Measuring Long Horizon Execution in LLMs&lt;/a&gt; — Per-step accuracy decays and models self-condition on their own prior errors; larger models are more prone and thinking mitigates it. Measured on a synthetic running-sum task. Backs "a loop is a different reliability regime."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metr.org/blog/2025-03-19-measuring-ai-ability-to-complete-long-tasks/" rel="noopener noreferrer"&gt;METR: Measuring AI Ability to Complete Long Tasks&lt;/a&gt; — Task length agents complete autonomously with 50% reliability has been doubling roughly every 7 months. The "why now" for taking loops seriously.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Practitioner Guidance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Anthropic: Building Effective AI Agents&lt;/a&gt; — An agent is "just LLMs using tools ... in a loop"; the compounding-errors warning; stopping conditions such as a maximum number of iterations. Backs loop-as-primitive and the stop spec.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/2025/Sep/30/designing-agentic-loops/" rel="noopener noreferrer"&gt;Simon Willison: Designing agentic loops&lt;/a&gt; — Designing the loop is "a critical new skill," and an agent "runs tools in a loop to achieve a goal" — the term's lineage predating its coinage. Backs loop-as-primitive.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://addyosmani.com/blog/loop-engineering/" rel="noopener noreferrer"&gt;Addy Osmani: Loop Engineering&lt;/a&gt; — Defines loop engineering as replacing yourself as the person who prompts the agent. The term the post reframes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic: Effective context engineering for AI agents&lt;/a&gt; — A looping agent generates more and more data that must be cyclically refined; names context rot and attributes it to Chroma. Backs "the context accumulates every turn."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.anthropic.com/en/docs/build-with-claude/context-windows" rel="noopener noreferrer"&gt;Anthropic: Context windows&lt;/a&gt; — Accuracy and recall degrade as token count grows (context rot), so curation matters as much as capacity. Official-docs corroboration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/advanced-tool-use" rel="noopener noreferrer"&gt;Anthropic: Introducing advanced tool use on the Claude Developer Platform&lt;/a&gt; — Intermediate results pile up in context whether useful or not; tool definitions have consumed 134K tokens before optimization. The 134K figure is tool definitions, used only as an analog for always-on bloat.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents" rel="noopener noreferrer"&gt;Anthropic: Effective harnesses for long-running agents&lt;/a&gt; — Long-running agents work in discrete sessions with no memory of what came before; a high-level prompt alone fails; state reconstructed from a claude-progress.txt file alongside git history. Backs externalized state.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/managed-agents" rel="noopener noreferrer"&gt;Anthropic: Scaling Managed Agents&lt;/a&gt; — The session is a context object that lives outside the context window; getEvents() selects positional slices of the event stream. Backs cross-iteration retrieval as its own discipline.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/building-agents-with-the-claude-agent-sdk" rel="noopener noreferrer"&gt;Anthropic: Building agents with the Claude Agent SDK&lt;/a&gt; — The gather/act/verify/repeat cycle and the compact feature that summarizes previous messages as the window fills. Backs loop-as-primitive and the compaction caveat.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ghuntley.com/ralph/" rel="noopener noreferrer"&gt;Geoffrey Huntley: Ralph Wiggum as a "software engineer"&lt;/a&gt; — The unattended overnight loop with a fresh context each iteration and state in files; verify success programmatically rather than trusting the model to self-assess. The running artifact and the honest failure mode.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/truongpx396/the-agentic-loop-a-practical-field-guide-mnc"&gt;Truong Phung (DEV Community): The Agentic Loop / Loop Engineering: A Practical Field Guide&lt;/a&gt; — The three hard stops (max iterations, no-progress detection, spend budget) and disk-backed state: "the agent forgets; the repo doesn't." Backs the stop-and-state section.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;agent-engineering-toolkit: loop-preflight&lt;/a&gt; — A preflight script plus Claude Code skill that checks an unattended loop wrapper for the max-iteration, no-progress, and spend brakes, externalized state, and a non-self-graded check, and prices the always-on context re-paid every iteration. Every check is a pattern grep and says so — MISSING means no recognizable pattern was found, not proof the guard is absent.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Author's Judgment (not directly sourced)
&lt;/h3&gt;

&lt;p&gt;The following claim is my own synthesis. It follows logically from the sourced material above, but no source states it directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"A loop fails quieter than the demo, not just more often"&lt;/strong&gt; — Inferred from Sinha et al.'s self-conditioning result (the model reads its own earlier errors as ground truth) and Anthropic's compounding-errors warning. Neither source states the "less visibly" framing; that is my inference.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>productivity</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Anatomy of a Perfect AI Agent Task</title>
      <dc:creator>John Young</dc:creator>
      <pubDate>Mon, 27 Apr 2026 20:30:03 +0000</pubDate>
      <link>https://dev.to/johnayoung/the-anatomy-of-a-perfect-ai-agent-task-4a2m</link>
      <guid>https://dev.to/johnayoung/the-anatomy-of-a-perfect-ai-agent-task-4a2m</guid>
      <description>&lt;p&gt;A well-crafted task for an AI coding agent is essentially context engineering — you're deliberately curating the minimum set of information the agent needs to produce the right output on the first try. Rather than pre-loading everything up front, the best approach combines focused instructions with enough pointers that the agent can pull in additional context just-in-time as it works (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic — Effective Context Engineering&lt;/a&gt;). Below is a breakdown of every element that matters, why it matters, and a full example at the end that ties it all together.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use This
&lt;/h2&gt;

&lt;p&gt;The seven elements below describe the upper-bound shape of a non-trivial task spec, not a baseline checklist. For trivial work — fixing a typo, renaming a variable, anything where the agent has no real risk of getting it wrong — skip the elaborate spec. (The &lt;a href="https://jyoung.dev/blog/how-to-size-tasks-for-ai-coding-agents/#heuristic-2-the-one-sentence-diff-test" rel="noopener noreferrer"&gt;companion sizing post&lt;/a&gt; uses "describable in one sentence" as a &lt;em&gt;sizing&lt;/em&gt; test, not a triviality test — well-sized tasks often fit in one sentence yet still warrant a full spec when there are constraints, edge cases, or pitfalls to communicate. The worked example below is one such task.) Even for non-trivial tasks, treat these elements as a maximum rather than a minimum: frontier LLMs reliably follow only ~150–200 instructions before performance degrades, and every irrelevant detail dilutes the signal of the rest (&lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer: Writing a Good CLAUDE.md&lt;/a&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  1. State the Goal, Not the Steps
&lt;/h2&gt;

&lt;p&gt;Lead with the &lt;em&gt;outcome&lt;/em&gt; you want, not a micro-managed sequence of instructions. Agents perform better when they understand the "why" and can plan their own approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt; "Open &lt;code&gt;user.go&lt;/code&gt;, find the &lt;code&gt;CreateUser&lt;/code&gt; function, add a field called &lt;code&gt;PhoneNumber&lt;/code&gt;..."&lt;br&gt;
&lt;strong&gt;Good:&lt;/strong&gt; "Add phone number support to user registration, including validation, storage, and API response."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best task descriptions share three properties: they state the goal, provide constraints, and define done."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://www.claudedirectory.org/blog/context-engineering-claude-code" rel="noopener noreferrer"&gt;Claude Directory: Context Engineering for Claude Code&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  2. Provide Architectural Context the Agent Can't Infer
&lt;/h2&gt;

&lt;p&gt;The agent can read your code. What it &lt;em&gt;can't&lt;/em&gt; read is the reasoning behind your architectural decisions, team conventions, or the "why" behind structural choices. Include only what's not derivable from the codebase itself.&lt;/p&gt;

&lt;p&gt;Include things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt; the architecture is shaped a certain way (e.g., "We use the repository pattern to keep DB logic out of handlers")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relevant files and entry points&lt;/strong&gt; (saves the agent from searching blindly and burning context window)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology choices and versions&lt;/strong&gt; (e.g., "Go 1.22, sqlc for query generation, chi router")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-specific terminology&lt;/strong&gt; the agent might misinterpret&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Claude already knows what your project is after reading a few files. What it needs is information it can't derive from reading code."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://www.claudedirectory.org/blog/context-engineering-claude-code" rel="noopener noreferrer"&gt;Claude Directory: Context Engineering&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That said, there's a discipline to this — more context is not always better. Research suggests frontier LLMs can reliably follow roughly 150–200 instructions before performance degrades, and broader context-rot studies show models attend to context less reliably as input grows (&lt;a href="https://research.trychroma.com/context-rot" rel="noopener noreferrer"&gt;Chroma: Context Rot — Hong et al., 2025&lt;/a&gt;). Every irrelevant detail you add dilutes the signal of the details that actually matter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Your CLAUDE.md file should contain as few instructions as possible — ideally only ones which are universally applicable. An LLM will perform better when its context window is full of focused, relevant context compared to when it has a lot of irrelevant context."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer: Writing a Good CLAUDE.md&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  3. Define Explicit Constraints and Non-Goals
&lt;/h2&gt;

&lt;p&gt;This is where most tasks fall apart. Without boundaries, agents will happily refactor your auth layer while you asked them to add a field to a struct.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constraints:&lt;/strong&gt; What rules must be followed (e.g., "Do not change the public API contract," "Use the existing &lt;code&gt;validate&lt;/code&gt; package, do not introduce a new dependency")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-goals:&lt;/strong&gt; What is explicitly out of scope (e.g., "Do not modify the frontend," "Do not refactor existing tests")&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Without constraints, AI might miss pagination for list APIs, use field injection instead of constructor injection, or not adhere to your project's package structure."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://blog.jetbrains.com/idea/2025/05/coding-guidelines-for-your-ai-agents/" rel="noopener noreferrer"&gt;JetBrains: Coding Guidelines for AI Agents&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  4. Provide Concrete Examples and Reference Implementations
&lt;/h2&gt;

&lt;p&gt;One of the highest-leverage things you can do. Point the agent at an existing implementation in your codebase that follows the pattern you want replicated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Follow the same pattern as &lt;code&gt;internal/order/handler.go&lt;/code&gt; for the new endpoint."&lt;/li&gt;
&lt;li&gt;"See &lt;code&gt;migrations/003_add_email.sql&lt;/code&gt; for the migration format we use."&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Include helpful examples for reference. ❌ 'Implement tests for class ImageProcessor' → ✅ 'Implement tests for class ImageProcessor. Check text_processor.py for test organization examples.'"&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://www.augmentcode.com/blog/best-practices-for-using-ai-coding-agents" rel="noopener noreferrer"&gt;Augment Code: Best Practices for AI Coding Agents&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  5. Define "Done" with Acceptance Criteria
&lt;/h2&gt;

&lt;p&gt;If you don't define what "done" looks like, the agent will decide for you — and you probably won't agree.&lt;/p&gt;

&lt;p&gt;Acceptance criteria should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observable&lt;/strong&gt; (can be verified by running something)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specific&lt;/strong&gt; (not "should work correctly")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testable&lt;/strong&gt; (ideally map to test cases)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Create a set of tests that will determine if the generated code works based on your requirements."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/five-best-practices-for-using-ai-coding-assistants" rel="noopener noreferrer"&gt;Google Cloud: Five Best Practices for AI Coding Assistants&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  6. Include Verification Commands
&lt;/h2&gt;

&lt;p&gt;Tell the agent exactly how to confirm its own work. This is the difference between "I think it works" and "it passes the build."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;go test ./internal/user/...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go vet ./...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;golangci-lint run&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curl -X POST localhost:8080/api/v1/users -d '{"phone": "+1234567890"}' | jq .&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Claude Code's best practices emphasize including Bash commands for verification. This gives Claude persistent context it can't infer from code alone."&lt;/em&gt;&lt;br&gt;
— &lt;a href="https://code.claude.com/docs/en/best-practices" rel="noopener noreferrer"&gt;Claude Code Docs: Best Practices&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  7. Call Out Edge Cases and Known Pitfalls
&lt;/h2&gt;

&lt;p&gt;You know things about your system the agent doesn't. If there's a footgun, flag it. If there's a non-obvious coupling between modules, say so.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The &lt;code&gt;user_id&lt;/code&gt; column has a unique constraint — the migration must handle existing duplicates."&lt;/li&gt;
&lt;li&gt;"The &lt;code&gt;Validate()&lt;/code&gt; method is called both at the handler level and inside the repository. Don't double-validate."&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Full Example
&lt;/h2&gt;

&lt;p&gt;A non-trivial feature decomposes into a handful of well-sized tasks. Take adding an optional phone number to user registration — accepted on signup, persisted on the user record, and returned by the user API. That feature splits into four tasks, one per architectural layer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Migration&lt;/strong&gt; — Add a nullable &lt;code&gt;phone_number&lt;/code&gt; column with reversible up/down SQL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model + sqlc&lt;/strong&gt; — Update the &lt;code&gt;User&lt;/code&gt; struct and regenerate sqlc queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service + validation&lt;/strong&gt; — Add &lt;code&gt;ValidatePhone&lt;/code&gt; to &lt;code&gt;UserService&lt;/code&gt; using &lt;code&gt;validate.PhoneE164&lt;/code&gt;, with unit tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handler + integration&lt;/strong&gt; — Wire the field through &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;GET /api/v1/users&lt;/code&gt; and add integration tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third is spec'd out in full below as the worked example. It's the strongest illustration of the seven elements at the right scope: the diff fits in one sentence, it stays inside a single layer, the agent reads ~5 files, the change lands well under the 200 LOC ceiling, and it can be verified independently — passing every gate of the &lt;a href="https://jyoung.dev/blog/how-to-size-tasks-for-ai-coding-agents/#sizing-decision-flowchart" rel="noopener noreferrer"&gt;companion sizing post's decision flowchart&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Task Spec: Add E.164 phone validation to UserService&lt;/span&gt;

&lt;span class="gu"&gt;### Goal&lt;/span&gt;
Phone numbers submitted to user registration must be rejected at the service layer when they aren't valid E.164. This task delivers that check; handler wiring and DB persistence are separate tasks.

&lt;span class="gu"&gt;### Architectural Context&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Semantic validation belongs in the service, not the handler. Handler does null/shape; service owns format and bounds.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`UserService.ValidateEmail`&lt;/span&gt; is the canonical example of this split — match its shape.

&lt;span class="gu"&gt;### Relevant Files&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`internal/user/service.go`&lt;/span&gt; — add &lt;span class="sb"&gt;`ValidatePhone`&lt;/span&gt; here.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`internal/user/service_test.go`&lt;/span&gt; — add tests here.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`internal/pkg/validate/phone.go`&lt;/span&gt; — read-only reference for &lt;span class="sb"&gt;`PhoneE164`&lt;/span&gt; and &lt;span class="sb"&gt;`validate.Error`&lt;/span&gt;.

&lt;span class="gu"&gt;### Reference Implementation&lt;/span&gt;
Mirror &lt;span class="sb"&gt;`UserService.ValidateEmail`&lt;/span&gt; in &lt;span class="sb"&gt;`service.go`&lt;/span&gt;:
&lt;span class="p"&gt;-&lt;/span&gt; Signature: &lt;span class="sb"&gt;`func (s *UserService) ValidatePhone(phone *string) error`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Nil pointer → return nil. Empty string → return error.
&lt;span class="p"&gt;-&lt;/span&gt; Return the &lt;span class="sb"&gt;`*validate.Error`&lt;/span&gt; from &lt;span class="sb"&gt;`PhoneE164`&lt;/span&gt; unwrapped — no &lt;span class="sb"&gt;`fmt.Errorf`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Copy the table-driven layout from &lt;span class="sb"&gt;`TestUserService_ValidateEmail`&lt;/span&gt;.

&lt;span class="gu"&gt;### Constraints&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`validate.PhoneE164`&lt;/span&gt;. No regex, no new dependencies.
&lt;span class="p"&gt;-&lt;/span&gt; Don't touch &lt;span class="sb"&gt;`UserRepository`&lt;/span&gt; or its mock — validation is pure.
&lt;span class="p"&gt;-&lt;/span&gt; Don't wrap the error; the handler relies on &lt;span class="sb"&gt;`errors.As(&amp;amp;validate.Error{})`&lt;/span&gt; to map it to HTTP 422.

&lt;span class="gu"&gt;### Non-Goals&lt;/span&gt;
No handler, migration, sqlc, or integration-test changes. No edits to &lt;span class="sb"&gt;`ValidateEmail`&lt;/span&gt; or other unrelated methods.

&lt;span class="gu"&gt;### Edge Cases&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`phone == nil`&lt;/span&gt; → return nil (field not provided).
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`*phone == ""`&lt;/span&gt; → return &lt;span class="sb"&gt;`validate.Error`&lt;/span&gt; (malformed input).
&lt;span class="p"&gt;-&lt;/span&gt; Strict E.164: &lt;span class="sb"&gt;`1234567890`&lt;/span&gt; (no leading &lt;span class="sb"&gt;`+`&lt;/span&gt;) must fail.
&lt;span class="p"&gt;-&lt;/span&gt; The handler already checks the JSON field is present and is a string — don't re-check those concerns here.

&lt;span class="gu"&gt;### Acceptance Criteria&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; &lt;span class="sb"&gt;`ValidatePhone(phone *string) error`&lt;/span&gt; on &lt;span class="sb"&gt;`UserService`&lt;/span&gt;.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="sb"&gt;`nil`&lt;/span&gt; phone → returns nil.
&lt;span class="p"&gt;3.&lt;/span&gt; Empty or non-E.164 → returns &lt;span class="sb"&gt;`*validate.Error`&lt;/span&gt; (verifiable via &lt;span class="sb"&gt;`errors.As`&lt;/span&gt;).
&lt;span class="p"&gt;4.&lt;/span&gt; Valid E.164 (e.g., &lt;span class="sb"&gt;`+14155552671`&lt;/span&gt;) → returns nil.
&lt;span class="p"&gt;5.&lt;/span&gt; At least four test cases: valid, invalid, nil, empty.
&lt;span class="p"&gt;6.&lt;/span&gt; Only &lt;span class="sb"&gt;`service.go`&lt;/span&gt; and &lt;span class="sb"&gt;`service_test.go`&lt;/span&gt; change.

&lt;span class="gu"&gt;### Verification&lt;/span&gt;
    go test ./internal/user/... -v -run TestValidatePhone
    go vet ./...
    golangci-lint run ./internal/user/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The spec above is available as a copy-paste template with a lint script that fails on missing sections in the &lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;agent-engineering-toolkit&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Goal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Anchors the agent on &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt;, not &lt;em&gt;how&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Architectural context&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides knowledge the agent can't infer from code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relevant files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Eliminates unnecessary exploration and context burn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reference implementation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;"Do it like this" is worth 1,000 words of description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Constraints + non-goals&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prevents scope creep and unsolicited refactors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edge cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Surfaces domain knowledge only you have&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Acceptance criteria&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines "done" in observable, testable terms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Verification commands&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lets the agent self-check before declaring victory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic — Effective Context Engineering for AI Agents&lt;/a&gt; — Why just-in-time context retrieval and focused instructions outperform pre-loading everything into the prompt.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.claude.com/docs/en/best-practices" rel="noopener noreferrer"&gt;Claude Code Docs — Best Practices&lt;/a&gt; — Including verification commands and CLAUDE.md conventions so the agent can self-check its work.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.claudedirectory.org/blog/context-engineering-claude-code" rel="noopener noreferrer"&gt;Claude Directory — Context Engineering for Claude Code&lt;/a&gt; — The task trifecta: state the goal, provide constraints, define done.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.augmentcode.com/blog/best-practices-for-using-ai-coding-agents" rel="noopener noreferrer"&gt;Augment Code — Best Practices for Using AI Coding Agents&lt;/a&gt; — Pointing agents at reference implementations and reviewing changes after each sub-task.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.jetbrains.com/idea/2025/05/coding-guidelines-for-your-ai-agents/" rel="noopener noreferrer"&gt;JetBrains — Coding Guidelines for Your AI Agents&lt;/a&gt; — How missing constraints lead agents to skip pagination, misuse injection patterns, and ignore project conventions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/five-best-practices-for-using-ai-coding-assistants" rel="noopener noreferrer"&gt;Google Cloud — Five Best Practices for AI Coding Assistants&lt;/a&gt; — Planning-first workflow and using tests as acceptance criteria for generated code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md" rel="noopener noreferrer"&gt;HumanLayer — Writing a Good CLAUDE.md&lt;/a&gt; — Why fewer, focused instructions outperform instruction overload, and the ~150–200 instruction ceiling for frontier models.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://research.trychroma.com/context-rot" rel="noopener noreferrer"&gt;Chroma — Context Rot (Hong et al., 2025)&lt;/a&gt; — Empirical study across 18 LLMs showing that attention to context degrades non-uniformly as input length grows.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/johnayoung/agent-engineering-toolkit" rel="noopener noreferrer"&gt;agent-engineering-toolkit: task-spec&lt;/a&gt; — Copy-paste task-spec skeleton matching this post's worked example, plus a lint script that fails on missing sections and flags vague acceptance criteria.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
