DEV Community

alifurkan gökçe
alifurkan gökçe

Posted on

Three ways your coding agent silently never reads your instructions

You write instructions for your coding agent. It ignores one of them. You rewrite it more forcefully, in bold, with "IMPORTANT" in front. It still ignores it.

Before blaming the model, check whether it ever saw the text. Each of the three cases below is documented behaviour of a tool you already use, each one drops part of your instructions on the floor, and none of them prints a warning.

1. Cursor ignores .md files in .cursor/rules

Project rules in Cursor must use the .mdc extension. Cursor's own docs put it plainly: a plain .md file there is ignored by the rules system, because it has nowhere to declare the description, globs and alwaysApply frontmatter that tells Cursor when to apply it.

So a file sitting in exactly the right directory, with exactly the right content, does nothing. No error at startup, no "rule skipped" line, nothing in the UI.

Ten-second check:

find .cursor/rules -name '*.md' 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

Any output is a rule that isn't loading. Rename to .mdc and add the frontmatter.

A detail that makes this worse: people who set up .md rules a while ago report that they used to work. If that's right, a working setup stopped working at some point during an update, and nothing announced it — so "I checked this once" is not protection.

2. Codex truncates your AGENTS.md files — as a set, not one by one

Codex reads the AGENTS.md files that apply to your working directory: a global one, the repo root, and the nested ones on the path. It concatenates them, and the 32 KB truncation applies to that combined payload.

This is the part that catches people, because every individual file looks fine:

AGENTS.md              12 KB   ✓ fine
packages/api/AGENTS.md 12 KB   ✓ fine
packages/web/AGENTS.md 12 KB   ✓ fine
                       -----
                       36 KB   ✗ 4 KB never reaches the model
Enter fullscreen mode Exit fullscreen mode

Nobody wrote a "too big" file. The rule you carefully put at the bottom of the last one simply isn't there when the model reads.

Check it:

find . -name AGENTS.md -not -path '*/node_modules/*' | xargs wc -c
Enter fullscreen mode Exit fullscreen mode

Add your global ~/.codex/AGENTS.md to the total, and remember only the files on the path to your working directory get concatenated — a file under packages/web doesn't count against you while you're working in packages/api.

I hit a real one while testing this: a checkout with four AGENTS.md files totalling 65.6 KB, 33.6 KB of it truncated away, no single file anywhere near the limit.

3. Claude Code truncates skill descriptions at 1,536 characters

Skills load their body on demand, which is the point — but the model only knows a skill exists from its listing, and the docs are specific: the combined description and when_to_use text is truncated at 1,536 characters in that listing.

Write a thorough description with five trigger examples and the last two are gone. The skill still exists, still works when invoked by name, and quietly stops being chosen on its own — which reads exactly like "the model is being lazy".

Put the key use case in the first sentence. Detail belongs in the body, which costs nothing until the skill runs.

The pattern

All three share a shape worth internalising: the failure is invisible from the inside. Your file is on disk. Your editor shows it. Code review shows it. The agent read a subset of it and had no way to tell you which part.

Regular documentation rots the same way, but a human reader notices when a doc is stale — the paths look wrong, the commands don't exist any more. An agent doesn't notice. It follows the text with complete confidence, including the part that stopped being true in March.

That second half is measurable. I scanned 118 popular open-source repositories with agent context files: 59% contained at least one hard dead reference — a file path or a script the instructions still name and the repo no longer has. Careful teams, well-maintained projects; the rot is just silent.

What to actually do

The manual checks above take a minute and catch a lot. Beyond that:

  • Keep one source of truth for CLAUDE.md and AGENTS.md. Claude Code reads the first, most other tools read the second, and asking for both is the most-upvoted request on the Claude Code tracker — 5,200+ reactions, marked not planned. An @AGENTS.md import inside CLAUDE.md works; a symlink works when the content is genuinely identical; two hand-maintained copies drift within a week.
  • Treat instruction files as code: they make claims about paths, scripts and links that CI can verify.
  • Re-check after tool updates, not just after your own edits. Case 1 is the reason.

For the automated version I wrote driftlint (disclosure: mine, MIT, zero runtime dependencies, no account, nothing leaves your machine):

npx @alifurkangokce/driftlint
Enter fullscreen mode Exit fullscreen mode

It checks all three limits above plus the drift half: dead file paths with did-you-mean fixes, removed npm scripts and make targets, markdown links whose target or heading moved, hooks and MCP servers pointing at scripts that don't exist, and CLAUDE.md ↔ AGENTS.md copies that have diverged.

But the tool is secondary. The idea worth keeping is the first one: when an agent ignores an instruction, check whether it was ever handed the instruction. Half the time, it wasn't.

Top comments (2)

Collapse
 
mateo_ruiz_6992b1fce47843 profile image
Mateo Ruiz

The “check whether it was ever handed the instruction” point is the real takeaway. We tend to debug agent behavior before verifying the agent’s actual input, which is backwards. I’d treat instruction files more like an API contract: validate what gets loaded, what gets truncated, and whether referenced paths/scripts still exist. Once instruction drift becomes something CI can detect, “the agent ignored my rule” becomes a concrete integration failure instead of a guessing game.

Collapse
 
alifurkangokce profile image
alifurkan gökçe

"API contract" is a better frame than the one I used, and it makes the missing piece
obvious: a real API contract has a failure channel. A malformed request gets a 400.
An agent that received half your instruction file gets nothing — no error, no log
line, and the model can't tell you what it didn't receive. That asymmetry is the
whole reason the check has to live outside the agent and run before the agent does.

The CI shape that's worked for me: exit non-zero on the mechanically verifiable
failures (a referenced path or script no longer exists, a file is past the load
limit), and diff against the merge base so a PR only fails on the drift it
introduced. That second part matters more than it sounds — adopt any checker on a
five-year-old repo and you get forty findings on day one and someone turns it off by
Friday. Same reason lint baselines exist.

Where I'd genuinely like your opinion is the contract's edge. Paths, scripts, links
and size limits are mechanical. "Auth goes through the BFF" isn't — it's true until a
refactor makes it false, and nothing about the text changes. Do you treat narrative
claims as part of the contract and accept they need a model in the loop to verify, or
keep the contract strictly mechanical and let the prose rot?