Glean 拾遗
Daily /2026-05-30 / How to Make Claude Code Fix Its Own Mistakes Automatically (Exact Setup You Can Copy)

How to Make Claude Code Fix Its Own Mistakes Automatically (Exact Setup You Can Copy)

Source x.com Glean’d 2026-05-30 12:17 Read 10 min
AI summary

This article provides a complete, copy-paste-ready setup for making Claude Code automatically catch, fix, and learn from its own mistakes. It covers a self-growing CLAUDE.md for project rules, PostToolUse hooks for auto-formatting and type-checking, Stop hooks for running tests on completion, PreToolUse hooks for blocking dangerous operations, and cross-session memory. The included settings.json config reduces back-and-forth from 45 minutes to 10 unattended minutes per feature. Audience: engineers using Claude Code or AI coding assistants.

Original · 10 min
x.com ↗
§ 1

Claude writes code, tests fail, you explain what went wrong. Then it fixes it, but breaks something else. Every session, same loop.

There's a setup that makes Claude catch, fix, and learn from its own mistakes automatically.

Here's the full config you can just copy 👇

Before we dive in, I share daily notes on AI & vibe coding in my Telegram channel: https://t.me/zodchixquant🧠

Claude 写代码,测试失败,你解释哪里出错了。 然后它修复了,但又搞坏了别的东西。每次会话,同样的循环。

有一种配置可以让 Claude 自动捕获、修复并学习自己的错误。

下面是你可以直接复制的完整配置 👇

开始之前,我在 Telegram 频道每天分享 AI 和 vibe coding 笔记:https://t.me/zodchixquant🧠

§ 2

Why Claude keeps making the same mistakes

Claude has no memory of what went wrong last session. Every new session starts from zero.

The same bug that took you 20 minutes to fix yesterday will happen again tomorrow.

CLAUDE.md fixes this. Anthropic's own power user guide says it directly:

"Anytime Claude does something incorrectly, 
add it to CLAUDE.md so it knows not to repeat the mistake."

"After every correction, end with: 
'Update your CLAUDE.md so you don't make that mistake again.'"

Claude is good at writing rules for itself. The problem is most people never ask it to.

为何 Claude 不断重复同样的错误

Claude 没有上次会话中什么出错的记忆。每个新会话从零开始。

昨天花了你 20 分钟修复的同一个 bug,明天还会发生。

CLAUDE.md 解决了这个问题。Anthropic 自己的高级用户指南直接指出:

"每当 Claude 做错了什么,
就把它加到 CLAUDE.md 中,这样它就知道不要再重复这个错误。"

"每次修正后,以这句话结束:
'更新你的 CLAUDE.md,这样你就不会再犯那个错误了。'"

Claude 擅长为自己编写规则。问题是大多数人从未要求它这样做。

§ 3

Step 1: The self-correcting CLAUDE.md

Your CLAUDE.md should grow every time Claude makes a mistake. Not with personality instructions, but with specific, actionable rules.

## Rules

- NEVER refactor, rename, or clean unrelated code
- All database queries through services/, never in components
- Run `npx tsc --noEmit` after every code change
- Run tests after every change, fix failures before moving on
- Prefix commits: feat:, fix:, docs:, refactor:, test:, chore:
- NEVER use enums, always prefer literal unions
- NEVER force push. Rewrites shared history.
- Run migrations before tests, not after

## Learned from mistakes

- Don't install packages in packages/ui that belong in apps/web
- Don't average two existing patterns, pick one and follow it
- When unsure about folder structure, check existing files first
- Stop-loss function must return a number, not a boolean (broke prod on 2026-05-12)

The "Learned from mistakes" section is key. Every time you correct Claude, end with:

"Update CLAUDE.md so you don't make that mistake again."

After a month, your CLAUDE.md has captured every mistake Claude has made in your project. Error rate drops because Claude literally reads the list of things not to do before starting work.

Research shows the sweet spot is ~12 rules under 200 lines. Past that, compliance drops sharply.

Step 1:自修正的 CLAUDE.md

你的 CLAUDE.md 应该在每次 Claude 犯错时增长。不是用个性指令,而是用具体、可操作的规则。

## 规则

- 绝不重构、重命名或清理无关代码
- 所有数据库查询必须通过 services/,绝不在组件中
- 每次代码变更后运行 `npx tsc --noEmit`
- 每次变更后运行测试,修复失败后再继续
- 提交前缀:feat:、fix:、docs:、refactor:、test:、chore:
- 绝不使用枚举,始终优先使用字面量联合类型
- 绝不强制推送,这会重写共享历史
- 测试前运行迁移,而不是之后

## 从错误中学习

- 不要在 packages/ui 中安装属于 apps/web 的包
- 不要将两种现有模式平均,选择一种并遵循它
- 不确定文件夹结构时,先检查已有文件
- 止损函数必须返回数字,而不是布尔值(2026-05-12 导致生产环境崩溃)

"从错误中学习"部分很关键。每次你纠正 Claude 时,以这句话结尾:

"更新你的 CLAUDE.md,这样你就不会再犯那个错误了。"

一个月后,你的 CLAUDE.md 会捕获 Claude 在你的项目中犯过的每一个错误。错误率下降,因为 Claude 在开始工作前会阅读不应该做的事情列表。

研究表明,最佳实践是大约 12 条规则,200 行以内。超过后,遵守度急剧下降。

§ 4

Step 2: PostToolUse hooks (catch mistakes in real-time)

Hooks fire automatically at specific points. PostToolUse runs after Claude writes or edits a file.

This is where you catch problems before they compound.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $file"
          }
        ]
      },
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsc --noEmit 2>&1 | head -20"
          }
        ]
      },
      {
        "matcher": "Write(*.tsx)",
        "hooks": [
          {
            "type": "command",
            "command": "npx eslint --fix $file"
          }
        ]
      }
    ]
  }
}

Every .ts file: auto-format with Prettier, then type-check. Every .tsx file: auto-lint with ESLint.

Claude sees the type errors immediately in the same turn and fixes them before moving on.

Without hooks: Claude writes 5 files, you run type check, 12 errors across 3 files, you explain each one.

With hooks: Each file is checked the moment Claude writes it. Errors fixed in real-time.

Step 2:PostToolUse 钩子(实时捕获错误)

钩子在特定点自动触发。PostToolUse 在 Claude 写入或编辑文件后运行。

这就是你在问题累积之前捕获它们的地方。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $file"
          }
        ]
      },
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsc --noEmit 2>&1 | head -20"
          }
        ]
      },
      {
        "matcher": "Write(*.tsx)",
        "hooks": [
          {
            "type": "command",
            "command": "npx eslint --fix $file"
          }
        ]
      }
    ]
  }
}

每个 .ts 文件:用 Prettier 自动格式化,然后类型检查。每个 .tsx 文件:用 ESLint 自动 lint。

Claude 在同一轮次立即看到类型错误,并在继续之前修复它们。

没有钩子:Claude 写 5 个文件,你运行类型检查,3 个文件中有 12 个错误,你需要逐一解释。

有了钩子:每个文件在 Claude 写入的瞬间就被检查。错误实时修复。

§ 5

Step 3: Stop hooks (the quality gate)

This is the most powerful hook. Stop hooks run every time Claude says "I'm done." They check if the work actually meets your standards before Claude finishes.

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm test 2>&1 | tail -5; echo \"Exit code: $?\""
          }
        ]
      }
    ]
  }
}

If tests fail, Claude sees the failure output and automatically continues working to fix it. No manual intervention.

For more complex validation, use a prompt hook that asks Claude to evaluate its own work:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check if all requested tasks are complete. Review the code changes for bugs, missing edge cases, and test coverage. If anything is incomplete or broken, continue working. If everything looks good, confirm done."
          }
        ]
      }
    ]
  }
}

Critical rule: always check stop_hook_active in Stop hooks.

When it's true, Claude is already continuing because of a previous Stop hook. Exit 0 immediately.

Without this check, your hook blocks Claude forever.

Step 3:Stop 钩子(质量门)

这是最强大的钩子。每当 Claude 说“我完成了”时,Stop 钩子就会运行。它们在 Claude 结束之前检查工作是否真正符合你的标准。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm test 2>&1 | tail -5; echo \"Exit code: $?\""
          }
        ]
      }
    ]
  }
}

如果测试失败,Claude 会看到失败输出并自动继续修复。无需手动干预。

对于更复杂的验证,使用提示钩子让 Claude 评估自己的工作:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "检查所有请求的任务是否完成。审查代码变更中的 bug、缺失的边缘情况以及测试覆盖率。如果有任何不完整或损坏,继续工作。如果一切看起来不错,确认完成。"
          }
        ]
      }
    ]
  }
}

关键规则:始终在 Stop 钩子中检查 stop_hook_active。

当它为 true 时,Claude 已经在执行前一个 Stop 钩子而继续。立即退出 0。

没有这个检查,你的钩子会永久阻塞 Claude。

§ 6

Step 4: PreToolUse hooks (prevent mistakes before they happen)

PreToolUse runs before Claude executes a tool. Use it to filter inputs and prevent expensive mistakes.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(cat *log*)",
        "hooks": [
          {
            "type": "command",
            "command": "grep -n 'ERROR\\|WARN' $file | head -50"
          }
        ]
      },
      {
        "matcher": "Write(**/.env*)",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'BLOCKED: Cannot write to .env files' && exit 1"
          }
        ]
      }
    ]
  }
}

Claude tries to read a 10,000-line log? Hook filters it to 50 lines of errors first. Claude tries to write to .env? Blocked before it happens.

Step 4:PreToolUse 钩子(在错误发生前预防)

PreToolUse 在 Claude 执行工具之前运行。用它来过滤输入并防止代价高昂的错误。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(cat *log*)",
        "hooks": [
          {
            "type": "command",
            "command": "grep -n 'ERROR\\|WARN' $file | head -50"
          }
        ]
      },
      {
        "matcher": "Write(**/.env*)",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'BLOCKED: Cannot write to .env files' && exit 1"
          }
        ]
      }
    ]
  }
}

Claude 尝试读取一个 10,000 行的日志?钩子先将其过滤为 50 行错误。Claude 尝试写入 .env?在发生之前就被阻止。

§ 7

Step 5: The auto-retry pattern

For tasks that need multiple attempts, set up a retry loop with a token budget:

Prompt pattern:

"Fix the failing tests. You have 3 attempts maximum.

After each attempt:
1. Run the tests
2. If they pass, you're done
3. If they fail, read the error, try a different approach
4. If all 3 attempts fail, explain what you tried and what's still broken

Do NOT try the same fix twice."

Combined with the Stop hook from Step 3, this creates a self-correcting loop: Claude writes code → tests run → if fail → Claude reads errors → tries different approach → tests run again → repeat until pass or budget exhausted.

The token budget prevents infinite loops. Without it, Claude can spiral into retry loops that burn hundreds of dollars.

Step 5:自动重试模式

对于需要多次尝试的任务,设置一个带有 token 预算的重试循环:

提示模式:

"修复失败的测试。你最多有 3 次尝试。

每次尝试后:
1. 运行测试
2. 如果通过,你就完成了
3. 如果失败,读取错误,尝试不同的方法
4. 如果所有 3 次尝试都失败,解释你尝试了什么以及仍然存在的问题

不要两次尝试相同的修复。"

与 Step 3 的 Stop 钩子结合,这创造了一个自修正循环:Claude 写代码 → 测试运行 → 如果失败 → Claude 读取错误 → 尝试不同方法 → 再次运行测试 → 重复直到通过或预算耗尽。

Token 预算防止无限循环。没有它,Claude 可能会陷入重试循环,烧掉数百美元。

§ 8

Step 6: Memory for cross-session learning

Hooks catch mistakes within a session. Memory prevents them across sessions.

# Check what Claude has learned
/memory

# Add rules manually
/memory add "this project uses pnpm, not npm"
/memory add "auth module was refactored on May 15, new pattern is in src/lib/auth/v2/"

With Dreaming enabled, Claude processes past sessions in the background and builds persistent knowledge automatically. No manual /memory add needed.

The combination: CLAUDE.md catches project-level patterns, /memory catches session-level learnings, Dreaming consolidates everything overnight.

Step 6:跨会话记忆

钩子捕获会话内的错误。记忆防止它们跨会话发生。

# 检查 Claude 已学到什么
/memory

# 手动添加规则
/memory add "此项目使用 pnpm,不是 npm"
/memory add "auth 模块于 5 月 15 日重构,新模式位于 src/lib/auth/v2/"

启用 Dreaming 后,Claude 会在后台处理过去的会话,并自动建立持久知识。无需手动 /memory add。

组合:CLAUDE.md 捕获项目级模式,/memory 捕获会话级学习,Dreaming 在一夜之间整合所有内容。

§ 9

The full self-correcting settings.json (copy-paste ready)

{
  "permissions": {
    "allow": [
      "Read", "Glob", "Grep", "LS", "Edit", "MultiEdit",
      "Write(src/**)", "Write(tests/**)",
      "Bash(npm test *)", "Bash(npx tsc *)", "Bash(npx prettier *)",
      "Bash(npx eslint *)", "Bash(git add *)", "Bash(git commit *)"
    ],
    "deny": [
      "Read(**/.env*)", "Write(**/.env*)",
      "Bash(rm -rf *)", "Bash(git push *)"
    ],
    "defaultMode": "acceptEdits"
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          { "type": "command", "command": "npx prettier --write $file" },
          { "type": "command", "command": "npx tsc --noEmit 2>&1 | head -20" }
        ]
      },
      {
        "matcher": "Write(*.tsx)",
        "hooks": [
          { "type": "command", "command": "npx prettier --write $file" },
          { "type": "command", "command": "npx eslint --fix $file" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash(cat *log*)",
        "hooks": [
          { "type": "command", "command": "grep -n 'ERROR\\|WARN' $file | head -50" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npm test 2>&1 | tail -10; echo \"Exit: $?\"" }
        ]
      }
    ]
  }
}

完整的自修正 settings.json(可直接复制粘贴)

{
  "permissions": {
    "allow": [
      "Read", "Glob", "Grep", "LS", "Edit", "MultiEdit",
      "Write(src/**)", "Write(tests/**)",
      "Bash(npm test *)", "Bash(npx tsc *)", "Bash(npx prettier *)",
      "Bash(npx eslint *)", "Bash(git add *)", "Bash(git commit *)"
    ],
    "deny": [
      "Read(**/.env*)", "Write(**/.env*)",
      "Bash(rm -rf *)", "Bash(git push *)"
    ],
    "defaultMode": "acceptEdits"
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          { "type": "command", "command": "npx prettier --write $file" },
          { "type": "command", "command": "npx tsc --noEmit 2>&1 | head -20" }
        ]
      },
      {
        "matcher": "Write(*.tsx)",
        "hooks": [
          { "type": "command", "command": "npx prettier --write $file" },
          { "type": "command", "command": "npx eslint --fix $file" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash(cat *log*)",
        "hooks": [
          { "type": "command", "command": "grep -n 'ERROR\\|WARN' $file | head -50" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npm test 2>&1 | tail -10; echo \"Exit: $?\"" }
        ]
      }
    ]
  }
}

§ 10

The before and after

BEFORE:

- Claude writes code, you run tests, 4 failures
- You explain each failure manually
- Claude fixes 3, introduces 1 new bug
- You explain again
- 45 minutes of back-and-forth per feature
- Same mistake happens again tomorrow

AFTER:

- Claude writes code, hooks auto-format and type-check every file
- Tests run automatically when Claude says "done"
- If tests fail, Claude reads errors and keeps fixing
- CLAUDE.md prevents yesterday's mistakes from repeating
- Memory prevents last week's mistakes from repeating
- 10 minutes per feature, most of it unattended

Thanks for reading!

I share daily notes on AI, finance, and vibe coding in my Telegram channel: https://t.me/zodchixquant

前后对比

之前:

- Claude 写代码,你运行测试,4 个失败
- 你手动解释每个失败
- Claude 修复 3 个,引入 1 个新 bug
- 你再解释
- 每个功能来回 45 分钟
- 同样的错误明天再次发生

之后:

- Claude 写代码,钩子自动格式化和类型检查每个文件
- Claude 说“完成”时自动运行测试
- 如果测试失败,Claude 读取错误并继续修复
- CLAUDE.md 防止昨天的错误重复
- 记忆防止上周的错误重复
- 每个功能 10 分钟,大部分无需看管

感谢阅读!

我在 Telegram 频道分享 AI、金融和 vibe coding 的每日笔记:https://t.me/zodchixquant

Open source ↗