How to Make Claude Code Stop Making Stuff Up When It Doesn't Know (Exact Setup Inside)

@0x_rody
АНГЛІЙСЬКА2 місяці тому · 06 черв. 2026 р.
346K
256
29
8
1.2K

Коротко

This guide provides a comprehensive 4-layer framework to prevent Claude Code from hallucinating functions or tests by implementing strict honesty rules, verification protocols, and automated linter hooks.

Claude Code lies to your face every day. Made-up functions, fake imports, "tests pass" when nothing ran. The fix is a 4-layer setup that makes lying expensive.

Claude tells you the bug is fixed. Two hours later you find out the function it called never existed.

Most devs learn to double-check everything and blame the model. The real fix catches every lie before it leaves your machine.

Here's the full honesty setup 👇

rody - inline image

Why Claude makes stuff up in the first place

Claude is a text predictor. When it doesn't know something, it predicts text that looks right. Made-up function names look like real ones. Confidently delivered nonsense reads the same as confidently delivered truth.

You can't tell the difference until your code breaks two hours later in a way that takes another hour to debug.

The fix isn't a smarter model. It's making Claude's output checkable in real time and making "I don't know" cheaper than guessing.

4 layers below. Together they cut fabrication to roughly zero.

rody - inline image

Layer 1: The CLAUDE.md honesty rules

The first layer is a set of rules in CLAUDE.md that tell Claude exactly when to admit uncertainty and exactly how. Drop this in your project root:

markdown
1## Honesty rules (read every turn)
2
3Before claiming a function, class, or import exists, verify it by reading
4the file or running a grep. Never fabricate symbols.
5
6If you cannot verify something, say "I haven't verified this" explicitly.
7Do not write code that depends on the unverified claim.
8
9If a task asks you to use a library you've never seen referenced in this
10project, ask before adding it.
11
12If a task involved tests or builds, do not claim success unless you
13actually ran the test or build command in this session.
14
15Never invent error messages, API responses, or stack traces. If you
16didn't see them, say so.
17
18When you genuinely don't know, the correct answer is "I don't know" or
19"I need to check first." Both are better than a confident guess.

These rules look obvious.

They aren't, because by default Claude is optimized to look helpful, and "I don't know" feels unhelpful unless you give it explicit permission.

The last line is the most important one. It's the "I don't know" license, and most people never grant it.

Layer 2: The verification-before-write pattern

The second layer forces Claude to verify before it writes. Add this to CLAUDE.md under the honesty rules:

markdown
1## Verification protocol
2
3Before writing or editing code that uses a symbol (function, class, type,
4constant), do one of:
5
61. Read the file where it's defined and confirm the signature
72. Run `grep -r "symbolName" .` or use the Glob tool to find it
83. Check package.json, requirements.txt, Cargo.toml, or equivalent for
9 the dependency
10
11If you skip verification, prefix the code with a comment:
12`// UNVERIFIED: I have not confirmed this symbol exists`
13
14Plan-then-execute mode is preferred for any task touching more than one
15file. Use Shift+Tab to enter plan mode before starting.

This costs Claude a few extra tool calls per session. It saves you the hours you would've spent debugging fake function calls.

Layer 3: The hooks that catch lies in real time

The third layer is hooks in settings.json that run a type checker or linter every time Claude writes a file. If Claude invented an import, the checker fails instantly, and Claude has to fix it before claiming the task is done.

json
1{
2 "hooks": {
3 "PostToolUse": [
4 {
5 "matcher": "Write(*.ts|*.tsx)|Edit(*.ts|*.tsx)",
6 "hooks": [
7 { "type": "command", "command": "npx tsc --noEmit --pretty false 2>&1 | head -20" }
8 ]
9 },
10 {
11 "matcher": "Write(*.py)|Edit(*.py)",
12 "hooks": [
13 { "type": "command", "command": "ruff check --quiet $file && pyright $file 2>&1 | head -20" }
14 ]
15 },
16 {
17 "matcher": "Write(*.rs)|Edit(*.rs)",
18 "hooks": [
19 { "type": "command", "command": "cargo check --message-format=short 2>&1 | head -20" }
20 ]
21 }
22 ]
23 }
24}

Hook output goes back to Claude as context. If tsc says "Cannot find module 'foo'", Claude sees it immediately and fixes the fabricated import. No invented code survives a PostToolUse check.

For tasks involving tests, add a Stop hook that runs the suite before Claude can declare the session done:

json
1"Stop": [
2 {
3 "hooks": [
4 { "type": "command", "command": "npm test 2>&1 | tail -30" }
5 ]
6 }
7]

Now Claude can't say "done, tests pass" without actually running them. The hook runs them.

The result goes back to Claude. If they fail, Claude has to fix them or admit they don't pass.

Layer 4: The fact-checker subagent

The fourth layer is a subagent whose only job is to review Claude's claims before they ship.

Drop this in .claude/agents/fact-checker.md:

yaml
1---
2name: fact-checker
3description: Use this agent after Claude has made claims about what code does, what tests passed, or what a library supports. Invoke before any commit, before any user-facing summary, and after any task that involved new dependencies.
4tools: Read, Grep, Glob, Bash
5model: sonnet
6---
7
8You verify claims, you do not write code.
9
10When invoked, do this:
11
121. Identify every factual claim in the recent conversation. Examples:
13 "the function X does Y", "the tests pass", "library Z supports W",
14 "this import is correct".
15
162. For each claim, verify it independently:
17 - Code claims: read the actual file and confirm
18 - Test claims: run the tests yourself
19 - Library claims: check the actual package or its docs
20 - Import claims: confirm the package is in the dependency manifest
21
223. Produce a report:
23 - VERIFIED: claim, evidence (file:line or command output)
24 - WRONG: claim, what's actually true
25 - UNVERIFIABLE: claim, why you couldn't check it
26
27Never accept "trust me" claims. Never make claims of your own. If you
28can't verify, the correct output is UNVERIFIABLE.

Invoke this agent before commits or before sharing results with your team. It catches the lies the other 3 layers missed.

rody - inline image

The "I don't know" license

Claude was trained to be helpful, and admitting ignorance feels unhelpful. So it guesses, and the guess looks right.

The fix is granting permission to not know. CLAUDE.md is half of it. Your reaction is the other half. Reward "I haven't verified this" with patience and you get honest Claude every session. Punish it with frustration and Claude goes back to guessing.

Not a config, a habit. The most underrated fix in the stack.

How to tell it's actually working

Three signs in your daily sessions.

Claude asks before adding dependencies. "Should I add X or use the stdlib?" instead of silent npm install.

Claude references file:line when it talks about existing code. "validateToken in src/auth/middleware.ts:47 does Y" instead of "the validateToken function does Y."

tsc and your linter stop screaming. Hooks catch the rare fabrications instantly and Claude self-corrects, so by the time you look, the lies are gone.

Not seeing these after a day or two? One layer isn't loaded. Usually CLAUDE.md, wrong location or wrong name.

rody - inline image

Common mistakes that keep Claude lying

CLAUDE.md is too long. Claude reads the first part and skims the rest. Honesty rules in the first 50 lines.

Hooks log silently. If output doesn't reach stdout, Claude doesn't know it lied. Make sure hook output goes back to the session.

You skip plan mode. That's where Claude exposes wrong assumptions before writing. Skip it and you skip the cheapest moment to catch lies.

You don't call the fact-checker. A subagent only works if you actually invoke it. Make @fact-checker part of your commit flow.

You react badly to "I don't know." Punish honesty once and Claude goes back to guessing. The other 3 layers don't stick without this one.

rody - inline image

The 5-minute honesty audit

1 minute: copy the CLAUDE.md honesty rules and verification protocol into your project root.

1 minute: copy the hooks block into ~/.claude/settings.json or .claude/settings.json.

2 minutes: create .claude/agents/fact-checker.md with the template above.

1 minute: run a task you'd normally double-check. Watch for tsc output coming back to Claude. Confirm Claude says "verified" or "I haven't verified this" explicitly.

Done. Fabrication drops from "every other session" to "rare and caught immediately." The model didn't get smarter. Your setup did.

Thanks for reading!

rody - inline image
Збереження в один клік

Використовуйте YouMind для AI-глибокого читання віральних статей

Зберігайте джерела, ставте цілеспрямовані запитання, підсумовуйте аргументи та перетворюйте віральні статті на корисні нотатки в одному AI-робочому просторі.

Дослідити YouMind
Для авторів

Перетворіть свій Markdown на охайну статтю для 𝕏

Коли ви публікуєте власні лонгріди, зображення, таблиці та блоки коду роблять форматування в 𝕏 складним. YouMind перетворює повну чернетку в Markdown на чисту статтю для 𝕏, готову до публікації.

Спробувати Markdown для 𝕏

Більше патернів для аналізу

Останні віральні статті

Переглянути більше віральних статей