SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

為什麼 coding agent 會忽略你的指示?

指示檔案說要停止,coding agent 卻照做。了解 context window、harness、規則載入時機與內容衝突,先診斷原因,再決定是否重寫規則。

為什麼 coding agent 會忽略你的指示

coding agent 會忽略你的指示,原因有 4 種,而且都不是因為你的語氣太客氣。規則可能根本不在 context window 中。規則可能太模糊,無法用來判斷某個動作。context 中的其他內容可能與規則矛盾,通常是 agent 剛讀取的程式碼。或者規則仍已載入,但位於目前 turn 很前面的內容,agent 會依據距離較近的內容工作。

每種原因都有對應的修正方法,因此第一步是區分這些原因。使用大寫字母或 IMPORTANT 並不能診斷問題。以下以 Claude Code 為實例,因為截至 August 2026,其載入與壓縮行為已有詳細文件說明。其他工具的細節不同,但大致上的行為相同。

先釐清 2 個術語。context window 是模型在特定 turn 看到的文字區塊,包括 system prompt、你的指示檔案、對話,以及 agent 讀取過的所有檔案。harness 是模型周邊的程式,也就是從磁碟讀取檔案並組合該文字區塊的程式。這篇文章中的幾乎所有抱怨,實際上都是在抱怨 harness,而不是模型。

指示檔案是訊息,不是設定

指示檔案不是設定檔。執行環境不會讀取 CLAUDE.md 並強制套用其中內容。執行框架會從磁碟讀取檔案,再將文字貼入對話。在 Claude Code 中,這些內容會以放在 system prompt 後方的 user message 傳送,因此模型看到這些規則的方式,與看到你輸入的其他內容相同。

這會導致一個令人不安的結果。你的規則會與視窗中的所有其他文字競爭,而且權重相同。規則只是一項主張。代理程式剛開啟的檔案則是證據。兩者不一致時,證據往往會勝出;系統也不會產生錯誤,因為從模型的角度來看,沒有任何事情出錯。

官方文件已清楚說明這一點:指示檔案會被視為內容,而不是受強制執行的設定。若要無論模型如何決定都阻止某項操作,就需要使用 hook,而不是寫下一句話。請記住這項原則。本文末尾的大多數修正方式,都是將這項原則套用到特定案例。

會載入哪些指示檔案,以及載入時機

Claude Code 會從啟動所在的目錄,沿著目錄樹向上搜尋。從檔案系統根目錄到工作目錄之間的每個 CLAUDE.md 和 CLAUDE.local.md,都會在啟動時完整載入。這些檔案會依序串接,因此距離啟動位置最近的檔案最後讀取;在同一個目錄中,.local 檔案會附加在主要檔案之後。

工作目錄下方子目錄中的檔案,載入方式不同。它們不會在啟動時載入,而是在代理程式讀取該目錄中的檔案時載入。.claude/rules/ 中帶有 paths: frontmatter 欄位的路徑範圍規則也是如此:只有在讀取符合條件的檔案時,這些規則才會加入內容,而不是每一輪都載入。

這項差異可以解釋相當多已回報的失敗案例。你將規則放在 packages/api/CLAUDE.md 中,詢問 API 相關問題,但代理程式從未開啟 packages/api/ 下的檔案,因此直接回答。這不是因為規則遭到忽略,而是因為規則從未載入。如果你的儲存庫將指引分散在 monorepo 中每個套件的指示檔案,每次都應先檢查這一點。

還有另一個載入陷阱,也是「代理程式忽略我的指示」最常見的原因:Claude Code 讀取的是 CLAUDE.md,不是 AGENTS.md。如果儲存庫統一使用 AGENTS.md,但沒有 CLAUDE.md,Claude Code 就完全沒有可載入的內容。支援的銜接方式是建立 CLAUDE.md,並讓第一行為 @AGENTS.md;這會在啟動時匯入該檔案,之後再放置 Claude 專用的備註。如果沒有其他內容要新增,也可以使用符號連結。至於哪些內容原本就應放在該檔案中,則是另一個問題,詳見將代理程式指示與人類文件分開。

確認檔案已載入後再改寫

在確認 agent 能看見檔案前,不要修改文字。這裡有兩項檢查,先執行成本較低的檢查。

在工作階段中執行 /context。此命令會依類別列出目前的內容,其中 Memory files 清單會列出實際載入的每個指示檔案。未出現在清單中的檔案不在對話內容中,因此你寫入其中的任何內容都不會生效。/memory 會列出檔案位置並開啟檔案供編輯,也會列出尚不存在的檔案。

若要取得更確切的結果,請記錄載入事件。每當 CLAUDE.md 或規則檔案進入內容時,InstructionsLoaded hook event 都會觸發。其 matcher 會說明載入原因:session_start、nested_traversal、path_glob_match、include 或 compact。將以下內容放入 .claude/settings.json:

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "matcher": "nested_traversal",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> /tmp/instructions-loaded.log"
          }
        ]
      }
    ]
  }
}

hook 會將 payload 以 JSON 形式寫入 standard input,因此 cat 會附加完整記錄。工作時使用 tail -f /tmp/instructions-loaded.log 監看記錄。此事件會忽略 exit status,因此 hook 只能觀察,無法阻止載入。如果你預期巢狀檔案應在某個工作階段載入,但該檔案始終未出現在記錄中,請停止改寫文字。問題出在檔案位置。

長時間工作階段對規則的影響

這裡有兩種不同的影響,必須採取不同的應對方式。

距離。 第 1 輪中指定的規則,在第 90 輪時仍位於內容視窗內,但此時會與最近 90 輪、且更貼近目前工作內容的文字競爭。你無法透過設定消除這種影響,但可以測量它。在新的工作階段中執行相同工作。如果規則在新工作階段中有效,卻在長時間工作階段的後段失效,原因就是距離。

壓縮。 內容視窗填滿時,harness 會摘要目前為止的對話,然後從該摘要繼續。能保留下來的內容,取決於摘要器判定哪些資訊重要;這不一定符合你的判斷。Claude Code 會依不同機制說明結果,而且差異很大。專案根目錄 CLAUDE.md 與未指定範圍的規則,在壓縮後會從磁碟重新注入。Auto memory 也會從磁碟重新注入。包含 paths: frontmatter 的規則會遺失,直到再次讀取相符的檔案。子目錄中的巢狀 CLAUDE.md 檔案會遺失,直到再次讀取該子目錄中的檔案。

依照這份表格排列指示後,脆弱程度的順序就很明顯。只輸入聊天中的規則,是工作階段中最脆弱的內容:只有在摘要碰巧保留它時才會持續有效。位於 packages/api/CLAUDE.md 的規則次之,因為它只載入一次,之後可能被摘要移除,且只有在該目錄中再次讀取時才會回來。專案根目錄檔案中的規則最穩定,因為每次都會從磁碟重新讀取。

因此,如果某項指示必須在整個工作階段中持續有效,就應放在不含 paths: frontmatter 的專案根目錄檔案中。其他安排都屬於取捨,應該在了解目的後再刻意選擇。管理內容視窗中保留的內容說明 /compact 搭配 focus 引數,以及不相關工作之間的 /clear;這兩者都會影響摘要器決定你的規則內容的頻率。

為什麼周邊程式碼會勝過規則

這是人們最常描述、卻最少正確診斷的失敗情況。你的檔案寫明資料庫存取必須經由 repository layer。代理程式卻撰寫了直接呼叫 ORM(object relational mapper)的 handler。這不是因為它忽略了你的風格要求,而是因為證據數量勝出。

規則描述偏好。程式碼展示實例。代理程式開啟即將編輯的模組中 3 個檔案,而這 3 個檔案都直接呼叫 ORM 時,context 的一方是 1 句抽象描述,另一方則是 3 個具體、近期且符合任務的範例。複製本機模式通常是正確行為。這裡之所以錯誤,是因為你知道 context 不知道的資訊:那些檔案是 legacy code。

因此,請將這項資訊寫入規則。明確說明自身反例的規則,才能在實際 repository 中持續有效。只陳述偏好的規則則無法做到。

新增的資料庫存取必須經由 app/repositories/。app/legacy/ 下的檔案仍會直接呼叫 ORM。那是舊程式碼,不是應遵循的模式。不要複製它。

真正發揮作用的是第 2 句。它在代理程式找到這些內容之前,先告訴代理程式將會看到什麼,以及應如何解讀。相同的修正方式也適用於任何明顯與 repository 不一致的規則:歷史紀錄未遵循的 commit 格式、測試套件中有一半未採用的測試配置,以及只適用於新程式碼的 import 慣例。只要程式碼與檔案內容不一致,就應在檔案中明確指出這項差異。

無法檢查的模糊規則,也就無法遵循

「撰寫乾淨的程式碼。」「不要過度工程化。」「保持簡單。」「小心處理遷移。」這些規則都無法針對特定操作進行測試,無論是由 agent 測試,還是由你測試。若 agent 收到一項無法用來檢查自身輸出的規則,就只能猜測,而你則憑感覺評分。

請對檔案中的每一行套用以下測試。寫出一個 shell 命令,讓規則被違反時以非零狀態結束。如果你無法寫出該命令,這項規則就無法檢查。比較以下範例:

  • 無法檢查:「讓函式保持精簡。」可檢查:「長度超過 60 行的函式,其上方必須有註解說明原因。」
  • 無法檢查:「測試你的變更。」可檢查:「執行 npm test,並在標記任務完成前貼上失敗數量。」
  • 無法檢查:「保持檔案井然有序。」可檢查:「HTTP handler 必須放在 src/api/handlers/。該目錄不得放置其他內容。」
  • 無法檢查:「正確格式化程式碼。」可檢查:「.ts 檔案使用 2 個空格縮排。」

「不要過度工程化」是人們最先放棄的規則,因為修正方式不是把句子縮短,而是把句子寫得更長:明確說明實際可行的最小變更是什麼,才能提供 agent 可用來比對自身 diff 的判準。

大小問題只是換了一種形式。Claude Code 的指引要求每個 instruction file 少於 200 行,並直接指出,檔案越長,遵循程度越低。700 行的檔案不代表指示更明確。它只是包含 700 行主張,彼此矛盾的機會更多,而且每一輪都會計入你的 context window,直接反映在 token 使用量中。將檔案分段,讓每項規則位於讀者可快速瀏覽的標題下,相關做法請參閱撰寫 agent 能夠執行的 instruction file。更好的做法,是刪除描述性內容,而非指示性內容:說明 handler 和 model 所在位置的目錄導覽,屬於 agent 可按需從解析後的 repository map查詢的結構,不必在每一輪都放入 context window。

十分鐘內完成診斷

依序執行下列步驟。直接跳到最後一步,往往只會得到一份充滿強硬規則、卻仍然無法運作的長檔案。

  1. 確認檔案已載入。 執行 /context,查看 Memory files 清單。如果找不到該檔案,請修正位置後停止。目前清單中的其他步驟都尚不適用。
  2. 在全新工作階段重現問題。 啟動新的工作階段,執行應觸發該規則的最小工作。在這裡成功,但於長工作階段失敗,表示問題可能與距離或壓縮有關。如果在這裡也失敗,問題就在規則本身。
  3. 排除競爭規則。 在現有程式碼已遵循該規則的目錄中,要求進行相同變更。如果遵循情況恢復,表示周遭程式碼的指示蓋過了你的句子。
  4. 搜尋衝突。 兩個檔案對同一行為提供不同指示,是已知的失敗原因:模型可能任意選擇其中一個,而且不會告訴你它這麼做。
  5. 讓規則可檢查後重新測試。 使用具體路徑與條件改寫規則。遵循率大幅提升,表示成因是原本的措辭。

第 4 步只需一個命令。搜尋所有指示來源中的相關主題,不要只搜尋你正在編輯的檔案:

grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/null

如果兩個檔案的內容不同,卻都命中同一主題,那就是問題所在。刪除其中一個。不要試圖用更強硬的措辭替它們排序,因為沒有可供申訴的排序引擎。

依影響力排序的修正方法

以下每個步驟的影響力都高於前一個步驟,但設定成本也更高。如果規則只需重新措辭即可解決,請從最上方開始。當規則重要到不能接受偶爾漏判時,就往下採用下一個步驟。

  1. 讓規則具體化。 指定路徑、命令或條件。加入代理程式會在儲存庫中找到的反證,如前文所示。這不需額外成本,卻能解決出乎意料多的問題。
  2. 將規則移到更接近其管轄範圍的位置。 例如巢狀的 CLAUDE.md、.claude/rules/ 中限定路徑範圍的規則,或直接放在檔案頂端的註解。如此一來,規則會與適用的程式碼在同一次讀取中載入。請接受這項取捨:以這種方式載入的內容會在下一次壓縮時被移除,並在下一次符合條件的讀取時恢復。
  3. 將強制執行移到 hook。 文字說明只能提出要求;hook 會做出決定。Hook 會在固定的生命週期事件中以程式碼執行,不論模型得出什麼結論,都會套用規則。
  4. 將規則交給確定性工具,並刪除文字說明。 例如格式化、import 順序、行長度、禁止的 import、提交訊息格式。使用 ruff format、prettier --write、eslint 或 pre-commit hook。格式化工具每次都能正確執行,而且不消耗 token。文字句子大多時候正確,但每次互動都會消耗 token。

完整說明步驟 3。假設 migration 檔案絕對不能由代理程式編輯。請將以下內容放入 .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
          }
        ]
      }
    ]
  }
}

再將以下內容放入 .claude/hooks/guard-migrations.sh:

#!/usr/bin/env bash
set -euo pipefail

path=$(jq -r '.tool_input.file_path // empty')

case "$path" in
  */migrations/*)
    echo "Files under migrations/ are written by hand. Stop and ask first." >&2
    exit 2
    ;;
esac

exit 0

執行 chmod +x .claude/hooks/guard-migrations.sh,然後啟動新的工作階段,要求代理程式編輯 migrations/ 下的檔案。編輯會遭到拒絕,並將你的訊息作為原因傳回。PreToolUse 的結束狀態為 2 時,會在工具呼叫執行前將其阻擋;你的 stderr 文字會以阻擋訊息的形式傳給模型。${CLAUDE_PROJECT_DIR} 會解析為專案根目錄,因此無論代理程式目前位於哪個目錄,hook 都能正常運作。代理程式不必同意規則、記住規則,或仍在內容中保留規則。編輯不會發生。

如果只是沒有邏輯的單純禁止規則,將 permissions.deny 放入設定中即可達到相同效果,也不需要維護 script;權限模式會決定哪些操作可在不先詢問你的情況下執行。如果某項指示確實必須位於系統提示層級,而不是使用者訊息中,--append-system-prompt 可以將它放在該層級。不過,每次呼叫都必須傳入這項設定,因此更適合 script,而不是互動式工作。

你無法僅靠指示消除的問題

請明確區分哪些部分由你負責。放置位置、措辭、檔案之間的衝突,以及檔案大小,都是作者的問題,也應由作者修正。其餘則屬於模型行為,無法僅靠更好的措辭消除。

同意不等於遵從。 代理程式可能會確認規則、正確重述規則,卻在兩次工具呼叫後違反規則。這種確認不會產生任何成本,也無法預測後續行為。不要把它視為修正,也不要把它算作測試。

有些習慣會持續出現。 例如加入註解、加入防禦性錯誤處理、撰寫結尾摘要,以及執行下一個直覺上應執行的命令。即使規則禁止這些行為,它們仍會以較低而非零的頻率再次出現。你可以測量自己的發生率:在全新的工作階段中執行相同工作 10 次,並計算違規次數。若該數字必須為零,就必須把規則移出提示內容。工作尚未完成一部分卻宣告完成,屬於相同類型的習慣;修正方式不是改寫措辭,而是採用結構化方法:unlazy skill 會以 Depth Tree 取代該句,並要求代理程式先通過 gate 檔案,才能宣告完成。

你目前的工作階段本身會成為範例。 如果代理程式在第 12 輪違反規則,而你放任不管,該違規行為就會以示範形式留在內容中,而且比規則新得多。發現違規時,應立即修正。未修正的違規行為會教導整個工作階段後續的行為。

指示檔案不是安全邊界。 它只能塑造行為,無法強制執行。凡是遺漏會造成重大損失的事項,例如憑證或破壞性命令,都應交由權限或 hook 控制。讓代理程式無法接觸秘密對資料採用相同原則:不要要求代理程式不要讀取某個檔案,而是讓該檔案實際上無法讀取。

簡而言之,先證明檔案已載入,再讓規則具備可檢查性,將規則移到受其規範的對象旁邊;如果遺漏率仍然重要,就不要只依賴文字描述。代理程式無法忽略的規則,從未真正要求代理程式遵守。

FAQ

Claude Code 為什麼忽略我的 CLAUDE.md?

先確認它是否已載入,不要直接假設它遭到忽略。執行 /context,查看 Memory files 清單;未列在其中的檔案不在目前對話中。指示檔會在 system prompt 之後,以 user message 的形式傳入,並被視為上下文,而非強制設定,因此無法保證嚴格遵循。實務上通常有以下四種原因:檔案位於 agent 從未讀取的子目錄、兩個檔案的內容互相衝突而模型任意選擇其中一個、規則過於模糊而無法據此檢查操作,或周邊程式碼示範了與規則相反的做法。

在工作階段中途編輯指示檔會產生什麼影響?

對已存在於對話中的副本沒有影響。工作目錄上層的檔案會在啟動時完整載入,因此模型持有的內容是啟動當下的版本。若要載入編輯後的內容,請啟動新的工作階段,或要求 agent 使用一般檔案工具讀取該檔案;這會將目前版本以新的訊息加入對話。執行 compaction 後,系統會從磁碟重新讀取專案根目錄檔案,因此新版本也會在該時間點載入。

根目錄的 CLAUDE.md 與巢狀檔案內容衝突時,哪個檔案優先?

無法可靠地判定任何一個優先。系統會將找到的檔案串接到上下文中,而不是讓檔案彼此覆寫;載入順序是從檔案系統根目錄到工作目錄,因此距離工作目錄最近的檔案只會最後讀取。系統沒有用來解決矛盾的優先順序引擎,Claude Code 的文件也指出,互相衝突的規則可能會被任意處理。請將巢狀檔案撰寫成補充規則,並明確說明其適用路徑;不要試圖以規則層級壓過衝突內容,應直接刪除矛盾。

我的指示會在 /compact 後保留嗎?

取決於指示的載入方式。專案根目錄的 CLAUDE.md、未指定範圍的規則,以及自動記憶體,會在 compaction 後從磁碟重新注入。使用 paths: frontmatter 的規則,以及子目錄中的巢狀 CLAUDE.md 檔案,會遺失,直到再次讀取相符的檔案為止。只有輸入在聊天中的內容,是否保留取決於摘要器是否保留了該內容。若規則必須在整個工作階段中持續有效,請將它放在專案根目錄檔案中,且不要使用 paths: frontmatter。

何時應將規則改為 hook,而不是保留為文字?

當檢查可決定性地執行,且漏檢的成本高於撰寫小型 script 的成本時,就應該改用 hook。檔案路徑限制、commit 前必須執行的命令,以及禁止的工具呼叫,都符合這個條件。PreToolUse hook 若以 status 2 結束,會直接阻擋工具呼叫,並將 stderr 文字回傳給模型作為原因,因此無論規則是否仍存在於上下文中,都能持續生效。凡是 formatter 或 linter 能夠判定的內容,都應交由該工具負責,並從指示檔中完全刪除。