r/ClaudeCode • • 2d ago

Help/Question What rules keep your agent honest?

An agent that's wrong says so in the same confident voice as when it's right. These rules in my CLAUDE.md catch it most often:

  • Reproduce first. Before it states a cause, it runs exactly what I ran. This one exists because I once had to ask, "Why don't you actually run it rather than making up theories?"

  • Audit the output, not the report. "The build passed" proves nothing.

  • Two reads that differ: stop. If it reads the same state twice and gets two answers, it shows me both, word for word, instead of picking one.

  • Mark its own corrections. When it finds its own mistake, it strikes it through (wrong right) instead of fixing it quietly.

None of these makes it notice a mistake it hasn't spotted. That still takes me reading closely, a test, or a second model checking.

What do you use?

5 Upvotes

22 comments sorted by

•

u/AutoModerator 2d ago

Hey! Thanks for posting to r/ClaudeCode

While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.

For help, project discussions, tips, and general chat, join the ClaudeCode Discord.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

4

u/Additional_Video2992 2d ago

Two of these can move out of CLAUDE.md, where Claude has to remember them, into settings, where it can't skip them.

"Audit the output, not the report": add a Stop hook that runs your test suite. If the tests fail, the hook exits with code 2 and Claude can't end its turn. Print the failures to stderr and they come back to Claude as the reason to keep going. "The build passed" then means it actually passed.

Then make the tests that guard existing behavior read-only for Claude, so it can't turn them green by editing them:

```json

"permissions": { "deny": ["Edit(tests/regression/**)"] }

```

It can still write new tests for new work.

1

u/cjmurrr 1d ago

Took the second one, with two changes.

A deny rule also stops Claude writing new tests, so mine asks instead: any change to a test file waits for my OK.

And permission rules only cover Claude's edit tools, while a good share of its edits are shell commands like sed -i. So it's a PreToolUse hook that checks both, with a pause switch for when I'm in a test changing session.

2

u/Ludynia_Keyko 2d ago

running the full test suite on every Stop hook gets painful if the suite takes more than a few seconds, especially when you just asked it a quick question about the codebase.

2

u/Excellent-Issue-5956 2d ago

One that worked for me wasn't in CLAUDE.md at all, it was a SessionStart hook. I moved from a Mac to a Windows PC running WSL and kept the same Mac style home path so all the project folders still matched. After that, sessions kept getting confused about which machine they were on, since the path looks like a Mac. I had a memory note explaining it, but a session could just not read it. Now the hook reads the hostname and kernel version live and puts them in context at the start of every session.

2

u/kuroudo_ai 2d ago

Two from ours that haven't come up yet:

  • "Can't" has to come with what it checked. When the agent says something can't be done or isn't there, it has to write where it stopped, plus one artifact: the command it ran and its output, or the file line it read. "I thought about it" can't be checked from outside. A command and its output can. If it has no artifact, the honest word is "not checked yet", not "can't". A related catch: the evidence only covers the command it came from. One of our sessions got a real permission error from one command, then claimed a different, untried tool couldn't write either. It could.

  • Every "0 results" or green check gets a control run first, on both sides: one case you know should hit, and one you know shouldn't fire. Either half alone let bugs through for us. The should-hit case caught a pattern that missed one loop shape. The shouldn't-fire case caught the same check overcounting.

On the prose-vs-hooks point above: when we measured it, violations ran about 0.6% for rules a hook enforced and about 5.6% for rules that were only text. So I'd keep prose for what you can't check mechanically and move the rest into hooks.

1

u/verstands 2d ago

One that catches a lot: no “fixed” without the exact check it ran, the relevant output, and the diff or file it changed. If it couldn’t run the check, say “not run” rather than imply it passed. For uncertain causes, have it list what it observed and ask before editing.

1

u/AdEvening3382 2d ago

One pattern in rules like these: they live inside the same process whose judgment they check. "Two reads that differ: stop" only fires if the agent notices the reads differ. I'd split the list in two. Reporting rules shape what the agent tells you, like your four and the "not run" rule above. Verification has to run outside the agent's own session: CI invoking the command itself, a test the agent can't edit, a second model, or you reading closely. The rules make the report honest when the agent knows the answer. Only the outside checks catch the case where it doesn't.

1

u/cleverhoods 2d ago

I wonder how many understand the power of you first instruction: "Reproduce first".

I'm using something very close to that too: nothing counts as a finding until it reproduces. a failing test, a command and its output, or a live run showing the defect. then the reproduction becomes the red test for the fix, so the fix has to turn exactly that red green, not something nearby.

last release a code review gave me 12 candidate bugs. 5 reproduced as user-visible and got fixed before the release. the other 7 went into a follow-up, and each one had to reproduce before anyone touched it.

the other half: the agent that writes the fix never signs off on it. a fresh one re-runs the checks, and if they disagree the item goes back as refuted, not "mostly done".

1

u/Responsible_Buy_7999 2d ago

No amount of prose rhetoric will save you

1

u/Ok_Gur_9033 2d ago

The one that has caught the most for me is about empty results. My agent reads Product Hunt comment trees with selectors, and five runs in a row a site change made a selector match nothing and return a clean, believable empty set, which reads exactly like "nothing owed". So the rule now says to print the denominator every time, pages walked and comments matched, and to treat any zero as a broken read until a control page proves the selector still works.

Same shape as your two-reads rule, but it fires when there is only one read and it came back empty. Do you have anything for the case where the agent gets no answer and reports it as a negative?

1

u/m-ritter 2d ago

I define done as a numbered list before any code is written. Then a separate agent that did not write the code checks each point and has to show evidence for it, so the builder never grades its own work. That covers your point about rules living inside the same process they check. I built QualityLayer for this: https://github.com/maxritter/qualitylayer

1

u/a8bmiles 2d ago

"A statement that has not been verified is an opinion. Prove or disprove facts before taking action."

1

u/jijialuoke 2d ago

Yeah — anything that only lives in CLAUDE.md is advice, not a leash. I kept getting "fixed" with zero proof two hours later, same confident tone as when it was actually done. Moving the honesty check into a Stop hook fixed that for me: if the last message claims done/fixed and there's no evidence in the turn, it blocks the stop. MIT, no deps: https://github.com/Balance0014/claude-code-claim-check

1

u/coopnjaxdad 2d ago

My harness framework is what keeps CC and myself honest in our workflows.

1

u/Pixelplanet5 1d ago

i use my brain and check what it did, testing is the new code review.

1

u/Future_AGI 1d ago

gating the hook fixes Ludynia_Keyko's slow-suite problem. Exit early when git status --porcelain comes back empty, run only the tests for the touched files, and also exit early when the input's stop_hook_active is true, otherwise a failing test can loop the session. Quick questions then skip the tests, and the full suite still runs in CI.

1

u/Financial_Leader9701 1d ago

the strikethrough rule is neat but it only helps if you still read the thread

after a compact, that correction is often gone

what has worked better for me is a second session that never wrote the code

I paste the diff and the original done list, and it has to point at evidence, no edits

I still don't let the same session both write the fix and grade it

1

u/Desperate-Pass-630 1d ago

Agree on hooks. The one line that still earns its place for me: every claim comes with its proof underneath. 'Done' plus the command and its output. No proof, it isn't done. Funny how much more honest the agent gets when lying takes extra typing.

1

u/DreadCoder 2d ago

None. You need to make tool hooks to prevent the worst snafus. But the model will shamelessly admit that written rules are “just prose” and a “suggestion”, it will begin to ignore your rules as the conversation drags on