Claude Code 揾卡咗 4 個鐘嘅 bug:log 倒推、git bisect、minimal repro 三個 pattern
撞到一個 bug 卡足 4 個鐘,直接叫 Claude「fix」通常出個亂作嘅 patch。教你 3 個有紀律嘅 debugging pattern:log 倒推、git bisect 配 AI 寫 predicate、minimal repro。香港 solo dev 同細 team 實戰角度。
情境
下晝 2 點,你撞到一個 bug。
3 點:你以為睇到原因,改完,bug 仲喺度。 4 點:你問 Claude Code「fix this bug」,貼咗 50 行 code 落去。Claude 出一個睇落幾合理嘅 patch。一 apply、一 run,bug 仲喺度。 5 點:你再貼多 200 行 context,Claude 出另一個 patch。Apply 落去,今次連帶整爛咗另外兩個 test。 6 點:你開始懷疑自己係咪做緊呢一行。
呢個係典型 AI 輔助 debugging 嘅 anti-pattern:
- 你冇 isolate 個 bug,淨係將 symptom 同一大堆 code 掟畀 Claude
- Claude 唔知道你已經試過啲乜,每次都重新亂作一個「最合理」嘅 fix
- 你嘅信心隨住 patch 一個個失敗而遞減,最後連最基本嘅 hypothesis 都唔敢信
有紀律咁 debug 嘅核心:收窄 search space,再請 Claude 落手。下面 3 個 pattern 係我自己 solo dev 撞牆撞出嚟嘅 SOP。
跟住做
1. 第一守則:唔好問 Claude「fix this」
撞到 bug 第一個動作,唔係開 Claude Code。係攞張紙寫低:
- Symptom:你睇到乜嘢(error message、輸出錯咗、UI 壞咗)
- Expected:應該係點
- Last known good:上次正常嗰個 commit / 時間
- What changed:你最近改咗乜
- What you tried:已經試過嘅 hypothesis(即使試完冇用都寫低)
呢張紙先係你畀 Claude 嘅 context。冇呢張紙,你即係叫 Claude 喺漆黑入面摸路。
# 開個 scratch file 寫低,唔好淨係留喺腦
$ cat > .debug-notes.md <<'EOF'
SYMPTOM: API /api/orders 返 500,error log 寫 "undefined is not iterable"
EXPECTED: 返 order list
LAST KNOWN GOOD: 噚日 commit 8a3f2c1
WHAT CHANGED: pull 咗 main,merge 咗 feature/discount
TRIED:
- restart server → 冇用
- clear cache → 冇用
EOF
2. Pattern A:用 log 倒推
呢個係最少人用嘅 pattern。流程:
- 加 log(你親手加,唔好叫 Claude 加 — 你最清楚邊度可疑)
- Reproduce 一次
- 將 log 輸出完整貼畀 Claude,叫佢提 hypothesis
- Claude 出 hypothesis,你決定下一個 log 加喺邊
關鍵 prompt:
我撞到一個 bug。Symptom 同 context 喺 .debug-notes.md,請先讀。我啱啱喺 src/api/orders.ts line 42-58 加咗 log(見以下 output)。Reproduce 一次出嚟係:[log dump 貼喺度] 請: 由 log 倒推最有可能嘅 root cause(列 2-3 個 hypothesis,按可能性排) 對最有可能嗰個 hypothesis,建議下一個應該加 log 嘅位(精確到 file + line + log 乜 variable) 唔好提議 fix。我哋而家係 investigation phase。 如果 log 唔足以分辨幾個 hypothesis,直接講「需要更多 log」,唔好估。
呢個 prompt 嘅紀律:禁止 Claude 提議 fix。Investigation 同 fix 係兩個階段,溝埋一齊就會亂作。
3. Pattern B:git bisect 配 Claude 寫 test predicate
如果你知道某個 commit 之前正常、而家壞咗,但中間隔住 30-100 個 commit — git bisect 係黃金工具,但 90% 開發者都唔識用 automated mode。
# Manual mode(慢,每步要你手動 test)
git bisect start
git bisect bad HEAD
git bisect good 8a3f2c1
# Automated mode(快,畀 script run)
git bisect run ./check-bug.sh
關鍵:個 check-bug.sh 要 exit 0 = good、exit 1 = bad、exit 125 = skip。寫呢個 predicate script 正正係 Claude 嘅強項:
我要 git bisect run 一個 bug。Bug 嘅 minimal repro 步驟: pnpm install pnpm dev 起 server curl localhost:3000/api/orders 應該返 200 + JSON array 而家壞咗:返 500,error message 含 "undefined is not iterable" 請寫一個 check-bug.sh: Exit 0 如果 /api/orders 返 200 Exit 1 如果 返 500 Exit 125 如果 pnpm install 或 pnpm dev 起唔到(compile error 唔算 bug,bisect 應該 skip) 收尾:每次執行完要 kill 咗個 server,唔好霸住個 port 加 timeout 防 server hang。
跑完 git bisect run,Claude 寫嘅 bisect script 會自動做 binary search,5-7 步就揾到出事嗰個 commit。然後你再丟畀 Claude:「呢個 commit 點解搞爛咗個 endpoint?」呢個 context 窄好多,亂作嘅機率都低好多。
4. Pattern C:抽個 minimal repro 出嚟畀 Claude 專心睇
最後一個 pattern 用喺hypothesis 已經收窄、但就係 fix 唔到嘅情況。
開一個新 folder,將 bug 抽出嚟做一個獨立 repro:
mkdir ~/bug-repro-orders
cd ~/bug-repro-orders
# 抽出 minimum code:1-2 個 file,去除晒所有唔相關嘅 dependency
然後喺呢個 minimal folder 入面開 Claude Code:
呢個 folder 係一個 minimal reproduction,得 2 個 file 同 30 行 code。Bug:[symptom]。請: 逐行讀晒 2 個 file(唔好 sample,逐行) 列出每個 expression 嘅 type 同預期 value 指出邊一行係 root cause + 點解 提議 fix,並解釋點解呢個 fix 唔會 break 其他 case 呢個 repro 已經 minimal,唔好叫我加 context。
呢個 pattern work 嘅原因:Claude 喺 200 行 code 入面注意力會散晒,但得 30 行佢就真係可以逐行 reasoning。你嘅工作係幫佢收窄,唔係餵多啲 context 落去。
變化
變化 1:race condition / concurrency bug
Race condition 最陰濕 — 跑 100 次得 3 次 fail。直接貼 code 畀 Claude 冇用,因為 symptom 唔穩定、唔可重現。
策略:先加 timing log(每個 critical section 入口同出口都 print 低 timestamp 加 thread / request id),跑 50 次,揀 fail 嗰幾次嘅 log 一次過貼畀 Claude,問佢「邊兩個 event 嘅 interleave 會搞成呢個 state」。Claude 對 concurrent reasoning 真係幾叻,但前提係你要畀佢timing data,唔係淨係畀 code。
變化 2:Heisenbug(manifestation 變嘅 bug)
Heisenbug 嘅特徵:你一加 log 佢就唔再出現、你用 debugger 佢又消失。背後通常係 memory ordering、timing 或者 optimizer 嘅行為。
呢類 bug 唔好叫 Claude 直接 fix。問法:「呢個 bug 消失嘅 pattern 暗示係邊類 root cause?」Claude 會列 5-6 個 category(race / undefined behavior / GC timing 等等),你逐個排除。呢個係 meta-debugging — 將 Claude 當成一個推理夥伴,而唔係一部 patch 生成機。
變化 3:production-only bug(本地 reproduce 唔到)
本地正常、production 先壞 — 通常係 env variable、data shape、scale 或者 timezone 引起。
你冇辦法喺本地 reproduce,所以重點係收集 production 上面嘅證據:error trace、相關 request payload(要 sanitize 走啲 PII)、env diff(local 同 prod 嘅 env variable 對比表)、出事前後 5-10 分鐘窗口嘅 log。
將呢啲一次過貼畀 Claude,問:「邊個 env diff 最能解釋呢個 trace?」直接問 fix 冇用,問 diff 嘅解釋力先有用。揾到出事嗰個 env / data shape,再喺本地用返嗰個 env 重新 reproduce,就跌返入 Pattern A / C。
拆解:點解 work,同邊度會仆街
跟到上面就已經用得。下面呢段係畀**想由「今次揾到個 bug」做到「以後撞咩 bug 都唔會被 Claude 帶住遊花園」**嘅人——初學者可以跳過,唔影響你跟住做。
呢套流程最唔老實嘅地方係:Claude 永遠都肯答你,但「肯答」唔等於「答啱」。佢唔會話「我唔知」,佢會自信咁畀你一個聽落好順嘅 root cause。呢幾個位就係佢扮自信、而你會中招嘅地方,你要預咗:
1. log dump 太長,真正出事嗰行被 truncate 咗 你貼成 500 行 log 落去,以為畀得越多越好。但 Claude 嘅 context 有上限,貼到中段佢嘅注意力已經散,關鍵嗰行隨時被你自己一拼貼蓋過去。
- 會出事:Claude 由一段唔相干嘅 log 推 root cause,講到頭頭是道,但完全係另一單嘢。
- 點救:貼之前自己 grep 走 health-check、heartbeat 嗰啲 noise,淨低 reproduce 前後嗰窗口;太長就分兩三段貼,每段叫佢只就嗰段提 hypothesis。
2. git bisect 撞到「壞咗但唔係呢個 bug」嘅 commit 中間有啲 commit 本身 compile 唔到、或者壞咗第二樣嘢。你個 predicate script 淨係 check「/api/orders 返唔返 200」,分唔清「呢個 bug」同「另一個 bug」,bisect 就會指錯 commit。
- 會出事:bisect 收斂到一個睇落無辜嘅 commit,你對住佢諗一個鐘都諗唔通,因為佢根本唔係元兇。
- 點救:predicate 要 check 到「呢個特定 symptom」(例如 grep 個 error message 含唔含 "undefined is not iterable"),唔好淨係 check status code;分唔開嘅 commit 一律 exit 125 skip,唔好當 good。
3. minimal repro 抽嘅過程已經整走咗個 bug 你抽 2 個 file 出嚟,順手簡化埋,結果 repro 唔到。你以為 bug 喺呢 30 行,但其實佢死喺你抽走咗嗰個 dependency 或者 config。
- 會出事:Claude 喺一個根本冇 bug 嘅 repro 上面逐行分析,然後砌一個解釋出嚟氹你,你跟住改完原本個 project 一樣壞。
- 點救:抽完即刻喺 minimal folder reproduce 一次,confirm 個 symptom 真係重現先畀 Claude;重現唔到,代表你抽嘅過程已經講緊一啲嘢——嗰個「抽走咗就無事」嘅嘢先係線索。
4. Claude 改完一個 test 過,以為搞掂,其實 break 咗你冇睇嗰啲 佢提個 fix,你 run 返你關注嗰個 case 過咗,就 commit。但呢個 fix 隨時靜雞雞改咗共用 function 嘅行為,整爛其他 path。
- 會出事:呢個 bug 好返,下個禮拜另一個 module 爆,你又卡多四個鐘,而且唔會聯想到係今次個 fix。
- 點救:apply fix 之前叫 Claude 列「呢個改動會掂到邊啲 caller / 邊啲 test」;apply 之後一定跑全套 test,唔好淨係跑你眼前嗰個。
5. 信錯 Claude 對你個 stack / 版本嘅「記憶」 問到行為細節(某個 API 喺邊個版本改咗、某個 flag default 係乜),Claude 會憑印象答,而你個 project 鎖嘅版本可能同佢記憶唔同。
- 會出事:佢引一個你版本根本冇嘅 behavior 去解釋個 bug,你照住信,愈查愈遠。
- 點救:涉及版本 / API 具體行為嘅 claim,叫佢明寫「呢個我唔肯定,你查 X」;自己開返 lockfile / 官方 doc 對一對,唔好當佢記得你個環境。
呢幾個位,就係「今次好彩揾到」同「以後揾 bug 都穩陣」之間嘅距離。Claude 永遠肯答,你嘅紀律就係幫佢收窄到佢答嗰句真係信得過。
一個紀律
Debugging 卡住嘅 4 個鐘,唔係「Claude 唔夠強」,係你冇 isolate 個 bug 就叫 Claude 落手。
AI 輔助 debugging 嘅心態唔應該係「Claude 係超人 senior,掟個 bug 過去佢自然識搞掂」。應該係「Claude 係個好叻嘅 pair partner,但收窄範圍嗰部分要你做埋」。
你嘅工作:
- Isolate(縮細 search space)
- Document(寫低 symptom、試過乜、hypothesis)
- 餵窄啲 context(畀 30 行,唔好畀 300 行)
- 禁止過早 fix(investigation 同 fix 唔好溝埋)
Claude 嘅工作:
- Hypothesize(由 log / diff / minimal code 倒推)
- Reason about edges(race、ordering、env diff)
- Generate tooling(bisect predicate、log probe、test case)
呢個分工做得好,4 個鐘嘅 bug 變 40 分鐘。做唔好,4 個鐘變 8 個鐘,仲要拖埋兩個整爛咗嘅 patch。
下次撞到 stuck bug,收手 5 分鐘:寫 .debug-notes.md、揀 Pattern A / B / C、再開 Claude。卡足 4 個鐘嘅 bug 通常唔係難,係你太快叫 Claude 出招。
文中工具 · 連結
- Claude Code CLI· 付費
開發者用 — terminal 入面同 Claude pair coding
睇完想同 Claude 一齊行一次?
撳一撳,就將成段 tutor 指示(連埋成篇文嘅內容)抄入剪貼簿。 貼入 Claude.ai 或 Claude Desktop,佢會用廣東話帶你一步一步行, 每步問你填關鍵位,最後畀返一個專為你情況寫嘅 prompt 帶走。
- 創作者 · 30 分鐘
Claude Code 由零安裝:Mac / Linux 30 分鐘起第一個 project
你睇 Twitter / HN 講 Claude Code,但搜尋「install」出咗 5 個矛盾教學,唔知由邊度開始。呢篇 30 分鐘有系統咁裝好 —— Mac / Linux 設定、API key、第一個 project 跑起、權限設定、常見安裝錯誤拆解。
- 打工仔 · 180 分鐘
Claude Code 處理舊 codebase:點樣接手一個 5 年舊項目
Claude Code 舊 codebase 接手指南:資深開發者接手一個 5 年舊項目。教你用 Claude Code 自動梳理架構、搵無用代碼 (dead code)、寫接手指南。
- 創作者 · 50 分鐘
Claude Code 行 TDD:你寫 test,Claude 寫 impl — pair-programming 模式真係 work
Claude Code TDD 工作流:你負責 test、Claude 負責 impl 嘅 pair programming 模式。red-green-refactor 具體 prompt + edge case ratchet + 邊類問題啱用 TDD。