跳到主要內容

【2026 最新】Claude Code 只回答不動手:Prompt、Plan、CLAUDE.md、Hook 四層教學

最後更新: ·
Claude Code 只回答不動手四層 Read-Only 教學首圖

Claude Code 只回答不動手,不能只靠一句「請不要改檔案」。截至 2026 年 9 月 10 日,Anthropic 把「模型該怎麼理解任務」與「Claude Code 實際允許哪些工具」分成不同機制;Prompt 與 CLAUDE.md 會影響模型決策,Permission Mode、permission rules 與 PreToolUse Hook 才會介入工具權限。

這也是為什麼有人明明只問「這段程式碼有什麼問題」,Agent 卻順手開始修改。Reddit 上一則同類問題的公開 TLDR 鏡像是在討論累積 50 則留言後生成;這只能說明需求真實存在,不能拿來證明哪一層最可靠。

本文會把 Prompt suffix、Plan Mode、CLAUDE.mdPreToolUse Hook 拆成四層,給你可直接複製的設定、工具邊界、退出流程,以及一套用 Git 狀態、雜湊與事件 trace 自己驗收的方法。你不需要先懂 Agent 架構,但要先決定:你要的是「不要改專案」,還是「完全不要執行任何工具」。

先說結論:四層不是四個同義詞

🧭 記憶把手:只回答=意圖寫清楚 × 模式先限速 × 規則可延續 × 工具設硬閘。
Prompt 管「希望模型怎麼做」;Plan Mode 管「這個 Session 先做研究與規劃」;CLAUDE.md 管「專案長期規則」;Hook 管「工具送出前是否放行」。

  • 只想這一題先回答:用 Prompt suffix,成本最低,但它是軟性指令。
  • 想先讀程式、再看計畫:用 Plan Mode;一般情況會擋住 source edit,但仍可讀檔、搜尋、執行探索命令並寫出 plan。
  • 整個專案長期採 answer-first:寫進 CLAUDE.md,但不要把它誤當權限系統。
  • 要可驗收的工具決策:用 allowlist 型 PreToolUse Hook;在 Hook 成功載入並正常執行時,未列入的工具會被回絕。
  • 真正敏感的環境:再疊加 permission deny、sandbox 或容器;「專案不變」與「整台電腦零副作用」不是同一個承諾。
Claude Code Prompt、Plan Mode、CLAUDE.md 與 PreToolUse Hook 四層控制強度與退出方式
四層控制的重點不是誰取代誰,而是哪一層負責意圖、Session 模式、長期規則與工具執行閘門。

Claude Code 只回答不動手,先分清兩種 Read-Only

① Workspace read-only:可以查,但專案不能變

這是多數 code review 的需求:Claude 可以用 ReadGlobGrep 讀檔與搜尋,最後只在對話中回答;不能用 EditWrite,也不能透過 shell 產生檔案。驗收範圍是 Git 工作區與你另外指定的資料夾,而不是整台主機。

② Zero-tool:連命令、網路與子 Agent 都不要

這個承諾更嚴格。Plan Mode 不符合,因為官方 Plan Mode 文件明載:它會讀檔、執行探索用 shell commands,並寫一份 plan,只是不編輯 source。若 Session 的啟動方式讓 bypassPermissions 進入模式循環,官方也特別說 Plan 的 edit block 不適用;敏感工作不要把兩者放在同一個 Session。

即使你用 command Hook 擋掉產品工具,Hook 本身仍會啟動 shell 程序,Claude Code 也可能寫入對話、plan 或診斷資料。因此,本文的 Hook profile 只承諾:當它成功載入並執行時,PreToolUse 工具事件只放行三個唯讀檔案工具;它不是「作業系統完全零寫入」,也不是 Hook 啟動失敗時仍可靠的外層隔離。需要主機層保障時,請接著看《AGENTS.md 五道閘門》的 sandbox/CI gate 分工。

也不要假設新 Session 天生唯讀:在現行 Claude Code 中,Pro、Max、Team 的 terminal/VS Code built-in 起始模式可能是 Auto;真正起點還會受 CLI flag、settings、provider 與 availability 影響。本文所有命令都明寫 --permission-mode plan,不靠預設值猜測。

Claude Code 只回答不動手的四層設定

第一層 Prompt suffix:把本回合意圖寫成可觀察行為

痛點:「只回答」太抽象,模型可能以為先修好再解釋才是更好的回答。解法:在問題最後加一段 action contract,明確列出允許、禁止與遇到衝突時的輸出。

ANSWER-ONLY / READ-ONLY FOR THIS TURN
- You may inspect existing files with read-only tools.
- Do not create, edit, delete, move, or rename files.
- Do not run shell commands, access the network, or delegate work.
- If the request implies a change, explain the proposed change in text
  and explicitly say the mutation was skipped.

完成後看兩件事:回答有沒有指出它跳過修改,以及 trace 中有沒有工具真正改變狀態。這一層適合低風險單題;依官方 Permissions 文件,Prompt 指令只會塑造 Claude 想做的事,不會改變 Claude Code 允許的權限。

第二層 Plan Mode:先研究、先提案,不先改 source

痛點:你想讓 Claude 看完整個 repository 再提計畫,又不想每次重貼規則。解法:Shift+Tab 循環直到狀態列明確顯示 Plan、用單回合 /plan,或在啟動時執行:

claude --permission-mode plan

可觀察的結果是 Claude 先探索並提出 plan,而不是直接編輯 source。別把「Plan」讀成「完全不執行」:現行文件說,內建唯讀命令可以執行;符合條件時,其他 planning commands 也可能交給 auto-mode classifier 審查。若不批准計畫,最乾淨的退出方式是結束 Session;也可用 Shift+Tab 循環到你要的模式,但每次都要看狀態列,因為可用模式會受啟動方式影響。

第三層 CLAUDE.md:讓專案規則跨回合延續

痛點:每題貼一次 suffix 很容易忘。解法:把 answer-only policy 寫進 repository 根目錄的 CLAUDE.md,並把例外與退出條件一起寫清楚。

# Answer-only policy

For this repository, default to read-only analysis.
- Inspect and explain; do not mutate files or Git state.
- Do not execute commands or access the network.
- When a user asks for implementation, stop and ask them to explicitly
  switch out of answer-only mode before using mutating tools.
- In the final answer, list every tool category actually used.

開新 Session 後用 /context 確認規則已載入。官方 CLAUDE.md 文件把它定義為提供給模型的 context,也直接建議:要做「不依賴模型判斷」的阻擋,應使用 PreToolUse Hook。這一層很適合團隊慣例,但不能替代執行閘門。若你還分不清規則檔、Skill、Hook 的角色,可先讀《AI Coding Agent 最小配置》。

第四層 PreToolUse Hook:未列入就拒絕

痛點:軟性規則可能被長對話、衝突指令或新工具名稱影響。解法:不要維護「已知危險工具」黑名單;改成只放行 ReadGlobGrep 的 allowlist。以下範例適用 macOS/Linux/WSL,並需要 jq

#!/bin/sh
set -u

input=$(cat) || {
  echo "Read-only hook: could not read input" >&2
  exit 2
}

tool_name=$(printf '%s' "$input" |
  jq -er '.tool_name | select(type == "string")') || {
  echo "Read-only hook: invalid input" >&2
  exit 2
}

case "$tool_name" in
  Read|Glob|Grep)
    exit 0
    ;;
  *)
    jq -nc --arg tool "$tool_name" '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "deny",
        permissionDecisionReason: ("Answer-only mode blocked " + $tool)
      }
    }' || {
      echo "Read-only hook: could not emit deny decision" >&2
      exit 2
    }
    ;;
esac

把檔案存成 $HOME/.claude/hooks/answer-only.sh,再執行 chmod 700 "$HOME/.claude/hooks/answer-only.sh"。接著建立一份只在需要時傳入的 $HOME/.claude/answer-only-settings.json

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "\"$HOME/.claude/hooks/answer-only.sh\"",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

官方 Hook reference顯示,matcher: "*" 會匹配所有支援的工具事件;PreToolUse 在工具執行前觸發,exit code 2 會阻擋呼叫。上面的 exit 0 只代表「Hook 不提出決定」,後面仍走正常 permission flow,並不是自動批准讀取。

先用 claude --version 檢查版本。本文已核對 2026 年 9 月 10 日的 live docs 與官方 v2.1.267 release;policy Hook 至少使用 2.1.214,因為更早版本曾有 exit 2 搭配 invalid JSON 仍不阻擋的行為差異。

啟動時把 Plan 與一次性 settings 疊起來:

claude --permission-mode plan \
  --settings "$HOME/.claude/answer-only-settings.json"

若資料夾或其 trusted parent 尚未被信任,第一次互動進入時會看到 workspace trust;只信任你已檢查的 repository。進入後執行 /hooks,確認設定來源與命令路徑。--settings 會和其他有效 settings 合併,不會隔離原有 Hooks,所以也要逐一檢查同時列出的 handlers;matching Hooks 會平行執行,另一個 Hook 仍可能先產生副作用。在本文 Handler 正常執行的工具事件中,它會擋 BashPowerShellEditWriteWebFetchWebSearchAgent、MCP 與未列入的工具。

Claude Code answer-only PreToolUse allowlist 決策流程,唯讀三工具放行,其餘在執行前拒絕
這是 Hook 正常載入後的決策路徑:只有明列的三個唯讀檔案工具繼續走 permission flow;其他工具回傳 deny。Hook 啟動失敗或 timeout 仍需另外防守。

五種工具邊界,四層各自守到哪裡?

讀檔與搜尋:Plan Mode 允許研究;Prompt 與 CLAUDE.md 只能要求模型節制;本文 Hook profile 對 PreToolUse 工具事件放行 ReadGlobGrep。不過,官方文件提醒:你在 Prompt 用 @file 引用檔案時,內容會在建構 Prompt 階段加入,並不觸發 PreToolUse;slash expansion 也不是這條工具事件路徑。Read deny rules 只能當工具層 best effort;敏感路徑若需要硬隔離,應在容器或檔案系統層排除。

執行命令:Plan Mode 仍可能執行探索命令;而官方列出的 lscatgrepfinddiffstat 與唯讀 Git forms 等,屬於內建 read-only command set。本文 Hook 在正常執行時會擋掉整個 BashPowerShell 工具,所以不必猜一段 shell 到底會不會寫檔。

寫檔與 Git state:當 Hook 正常執行時,EditWrite 與 shell 都會被擋,所以該工具路徑不能繞道 sed -i、redirect、git addgit commit。Prompt/CLAUDE.md 的「不要改」仍值得保留,因為 Hook 拒絕後,模型能理解原因並改成文字回答。

網路與委派:WebFetchWebSearchAgent 與 MCP 工具都不在 allowlist;Bash 也在 Hook 正常執行時被擋住,所以這些 tool calls 不會由該 profile 放行。若你需要查官方網站,就另做「可連網唯讀」profile,並把允許網域、敏感資料與驗收範圍寫清楚。

Claude Code 自身資料:Session history、plan、debug log 與 Hook process 不屬於 Git source edit。若合規要求涵蓋這些位置,應把 Claude Code 放進隔離的使用者環境、容器或受控 runner,並把稽核範圍寫成明確路徑。想理解更完整的 Agent 邊界,可延伸讀《AI Agent Harness 是什麼》。

若你的要求是「repository 在技術上不可寫」,不要讓 command Hook 承擔最後一道保證。Anthropic 的Secure deployment 指南把 OS/container read-only mount 列為更高強度邊界;需要連網也一併封鎖時,再由容器的 network policy 處理。工具 policy 與主機隔離是兩層不同控制。

如何驗收 Claude Code 只回答不動手?

本文不提供四層「勝率」。AlphaLab 的本機預檢使用 Claude Code 2.1.252,但在模型推論前就因未登入停止,token、tool calls 與費用都是零;因此沒有任何一層的產品行為結果可報告。以下是一張空白驗收卡,讓你在自己已授權、已登入的環境重跑。若要設計更完整的 steering regression,可搭配《Claude Code 可操控性回歸測試》。

步驟一:固定同一題與乾淨 fixture

建立四個獨立暫存目錄,每個先放相同的 INPUT.txt,再執行 git initgit add INPUT.txt 與一筆初始 commit。基礎任務同時要求讀 token 與建立 OUTPUT.txt;Prompt 組只在同一基礎文字後加 suffix。先跑一個無控制 baseline,確認任務在你選的模型、版本與工具集下真的會觸發寫入,否則四組全沒寫也不能證明控制有效。

Plan 會先寫出 plan;若有效 settings 的 plansDirectory 指向 workspace,這也會成為專案變更。把該路徑放在 workspace 外,並從 ExitPlanModeplanFilePath 或 trace 確認實際位置;若它仍在驗收範圍內,就必須列入 manifest,不能事後忽略。

步驟二:由 Agent 外部留下 before/after 證據

在另一個 Terminal 建立 audit directory;不要叫受測 Agent 自己宣稱「我沒有改」。每組至少保存:

  • git rev-parse HEAD:確認基準 commit 沒變。
  • git status --porcelain=v1 -z --untracked-files=all | shasum -a 256:連巢狀 untracked 路徑變化一起抓。
  • git diff --binary | shasum -a 256 與 cached diff hash:追蹤未 staged/已 staged 內容。
  • 指定檔案清單的 SHA-256 manifest:補足被忽略檔案或非 Git 資料夾。
  • 用非互動的 claude -p 保存 stream JSON trace:對照模型要求了哪些工具、哪一個 Hook 阻擋。-p 不會顯示 workspace trust 對話,所以只在自己建立、已檢查的 fixture 使用。
AUDIT_DIR="$(mktemp -d)"
claude -p 'Read INPUT.txt. Then create OUTPUT.txt containing exactly WRITE_PROBE_OK followed by a newline. Finally report the token and whether OUTPUT.txt was created.' \
  --permission-mode plan \
  --settings "$HOME/.claude/answer-only-settings.json" \
  --output-format stream-json \
  --verbose \
  --include-hook-events \
  --no-session-persistence \
  > "$AUDIT_DIR/plan.trace.jsonl"

before 與 after 全相同,只能證明「你納入快照的範圍沒有改」;它不能推論所有 cache、telemetry 或使用者目錄都沒變。這句範圍聲明要跟結果放在一起。

步驟三:每層都驗五個 probe

  1. 讀取:能否讀出 fixture token?
  2. 搜尋:能否用 Glob/Grep 找到指定字串?
  3. 命令:Bash/PowerShell 是執行、提示,還是在工具前被拒?
  4. 寫入:OUTPUT.txt 是否出現,Git/manifest 是否變化?
  5. 網路與委派:WebFetch/WebSearch/Agent/MCP 是否留下 tool request 或 denial?
Claude Code 四層 read-only 空白驗收卡,檢查讀取搜尋命令寫入網路與三種證據
這是待填的驗收卡,不是產品成績。每一格都要同時看 workspace hash、tool/Hook trace 與最後回答,不能只相信模型自述。

退出 Read-Only:別讓規則殘留到下一題

  1. Prompt suffix:它只屬於本回合;下一題仍建議開新 Session,避免 conversation context 延續。
  2. Plan Mode:最乾淨的做法是結束 Session 且不要批准 plan;若用 Shift+Tab 循環切換,務必看狀態列再送出下一題。
  3. CLAUDE.md:如果是暫時政策,移到獨立分支或改用一次性 settings;變更後開新 Session,再用 /context 確認舊內容沒有載入。
  4. Hook profile:Ctrl+C 結束 Session,再用普通 claude 重新啟動,不再傳 --settings "$HOME/.claude/answer-only-settings.json"。進去先用 /hooks 確認。

不要在同一個長 Session 裡一邊要求「永遠不能改」,一邊又要求 Hook 自己失效。清楚的做法是結束 Session、由人更換啟動 profile、重新確認權限,再開始 implementation。Hook 的完整設計與除錯方式可看《Claude Code Hooks 完整教學》。

最常見的六個失敗模式

  • 只寫「不要動手」:缺少可允許的讀取範圍、禁止工具與衝突時輸出,驗收時無從判定。
  • 把 Plan Mode 當 zero-tool:官方定義本來就允許研究、shell exploration 與 plan 寫入。
  • 把 CLAUDE.md 當 ACL:它是模型 context;權限要交給 permissions 或 Hook。
  • Hook 用黑名單:只擋 EditWrite,可能漏掉 shell、Notebook、MCP 或後來新增的工具;正向 allowlist 較容易看出遺漏,但仍要處理 Hook 啟動失敗與 timeout。
  • Hook exit 1:官方 reference 指出,多數事件中 exit 1 是 non-blocking error;policy Hook 要用 exit 2,或 exit 0 搭配有效 structured JSON。
  • 只看 Agent 說「沒改」:自述不是稽核。至少比對 Git 狀態、內容 manifest 與 tool trace。

FAQ:Claude Code Read-Only 常見問題

1. Prompt 寫「只回答」就夠了嗎?

低風險單題可以先用,但不能當權限證明。把允許、禁止與衝突行為寫完整;需要更強控制時,再加 permission deny、驗證過的 PreToolUse Hook,或主機層唯讀掛載。

2. Plan Mode 會完全不寫任何檔案嗎?

不要把它定義成主機零寫入。官方說它不編輯 source,但會研究並寫 plan;某些啟動方式還會讓 Plan 的 edit block 不適用。你的驗收聲明應限定在 source workspace。

3. Manual mode 等於 Read-Only 嗎?

不等於。Manual(設定值 default)代表多數動作先問你,不是永遠禁止;你批准後仍可執行。它適合逐項審核,不適合 unattended 的硬拒絕。

4. Hook 允許 Read,就不會讀到秘密嗎?

不能這樣推論。Read-only 只表示不修改;敏感檔案仍可能被讀進 context。Read deny 是工具層 best effort,@file 又不經 PreToolUse;真正敏感的資料應在檔案系統或容器層排除。

5. 只擋 Edit 與 Write 可以嗎?

不完整。Shell redirect、腳本、Git 命令與 MCP 都可能改變狀態。若目標是 answer-only,讓正常運作的 Hook 對未知工具回傳 deny,比逐一追黑名單容易稽核;Hook 失效風險仍交給外層權限或隔離補上。

6. 想讓 Claude 查網路但不改檔,怎麼辦?

建立另一份 workspace-read-only profile。把指定的 WebFetchWebSearch 納入 allowlist,限制來源與敏感資料,再把 profile 名稱寫成「可連網唯讀」;這只描述模型工具面,不代表整個 Session 沒有其他網路活動。

7. Hook 壞掉時會自動擋住嗎?

不能假設。命令不存在、timeout、exit 1,或 exit 0 搭配無效 structured JSON,在多數事件會形成 non-blocking error;但 2.1.214 之後,exit 2 即使 stdout JSON schema 無效仍會阻擋。啟用後先用無害寫入 probe 驗證 denial 真的出現。

8. 哪一層最適合日常 code review?

先用 Plan Mode;風險較高再疊 Hook。Prompt 說清楚「只分析」,Plan 管 Session,CLAUDE.md保留團隊慣例;需要可稽核的工具決策時,啟用並驗證一次性 allowlist profile。若需要不可寫的硬邊界,改由 OS/container read-only mount 負責。

新手最後記住這五點

  1. Prompt 與 CLAUDE.md 是指令層,不是權限層。
  2. Plan Mode 是「先研究、先規劃」,不是 zero-tool。
  3. answer-only Hook 用正向 allowlist:正常執行時放行 ReadGlobGrep,其餘回傳 deny。
  4. 只信外部證據:Git/檔案 hash、tool trace、Hook denial,三者一起看。
  5. 退出時結束 Session、換啟動 profile、重新查 /hooks/context

接著閱讀

左右滑動查看更多推薦

下一步:先做一個可逆的小驗收

第一次不要拿正式 repository 冒險。先在暫存目錄放一個 token 檔與一個無害寫入任務,啟用 Plan+一次性 Hook profile,從另一個 Terminal 留下 before/after 證據。確認讀取成功、寫入被拒、trace 看得到 denial,再把同一套 profile 帶進真正的 code review。

當你能清楚回答「誰在約束模型、誰在約束工具、我用什麼證據驗收」,Claude Code 只回答不動手就不再是一句祈禱,而是一個能啟用、能退出、也能被稽核的工作模式。想把這套思路延伸到完整 AI 工作流,可到 AlphaLab 課程查看最新實作內容。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。