#AI學習 #Claude Code #環境變數 #feature flag
今天的主軸不是寫了什麼新東西,而是踩到一個讓我重新思考「工具透明度」的雷。一行兩天前自己加進 shell 設定的環境變數,把另一個完全無關的功能靜靜地關掉,沒有任何警告、沒有任何錯誤訊息——直到我自己去問才知道。
今日最有感的事
一行環境變數,靜悄悄關掉整個功能
事情是這樣開始的:早上想用 /remote-control 從手機連回電腦上的 Claude Code session,發現怎麼按都沒反應。我之前明明都還能用,於是先讓 Claude 直接跑指令拿真實錯誤訊息,結果跳出來一句很直白的話:
Remote Control requires feature-flag evaluation, which is disabled because DISABLE_GROWTHBOOK is set.
順著這條線回查我自己的 ~/.zshrc,第 18–20 行寫著:
1# Claude Code ultrawork / Workflows 功能(胡嘉璽 2026-05-27 FB 貼文發現的開關)
2export CLAUDE_CODE_WORKFLOWS=1
3export DISABLE_GROWTHBOOK=1
時間線立刻接上了。兩天前(5/27)為了打開 Workflows / ultrawork 加了這兩行,結果其中 DISABLE_GROWTHBOOK=1 把整套 feature-flag 評估都關掉,順帶把 /remote-control 也擋了。這代表我把兩個本來不應該綁在一起的設定綁在一起,自己給自己挖了個洞。
實測也很乾脆——把那行拿掉之後,/remote-control 立刻恢復;Workflows 只靠 CLAUDE_CODE_WORKFLOWS=1 就能用,根本不需要 DISABLE_GROWTHBOOK=1 陪跑。
真正讓我有感的是 GitHub Issue #61825
故事如果只到「自己亂設環境變數活該」就太普通了。真正值得看的是派出去的 sub-agent 引用了一條 GitHub Issue,編號很具體:anthropics/claude-code#61825。
說實話我第一反應是懷疑 agent 是不是捏造(具體編號 + 完美對應論點,是典型 fabrication 警訊)。所以我用 gh api 和瀏覽器雙線去驗,結果——它是真的。issue 標題是這樣寫的:
CLAUDE_CODE_WORKFLOWS env var silently gates the workflows feature even when tengu_workflows_enabled is true (same pattern as #50083)
裡面甚至附了反編譯出來的 v2.1.150 gating 邏輯:
1function RB() {
2 if (JM$ !== void 0) return JM$;
3 if (!uH(process.env.CLAUDE_CODE_WORKFLOWS)) JM$ = !1; // env 沒設就直接 false
4 else JM$ = v$("tengu_workflows_enabled", !0); // flag check 永遠到不了
5 return JM$;
6}
白話翻一下:就算 Anthropic 官方在 GrowthBook 那邊把 tengu_workflows_enabled flag 開給你了,只要 CLAUDE_CODE_WORKFLOWS 環境變數沒設,整段判斷直接短路回 false,flag 永遠不會被讀到。你就是看不到 workflows 功能,而且沒有任何提示告訴你「因為某環境變數的關係所以被擋」。
而且這條 issue 的狀態更耐人尋味:closed as not_planned,建立後十分鐘就被關。標題還明白寫「same pattern as #50083」——也就是說,這個「env var 短路擋掉 feature flag」的設計是已知、且官方標記不修的既定行為,不是 bug。
我從這次踩雷學到的三件事
第一,遇到「之前能用,現在不行」,第一動作是跑指令拿真實錯誤訊息,不是猜。 我今天稍早就有同款教訓——上次以為是版本或帳號 entitlement 問題,繞了一大圈,結果只要跑一次 claude remote-control --help 就會直接告訴你「DISABLE_GROWTHBOOK is set」。錯誤訊息往往比我們想像的更直白,問題是我們常常不去看它。
第二,環境變數是一種隱形耦合。 CLAUDE_CODE_WORKFLOWS 和 DISABLE_GROWTHBOOK 在 FB 貼文裡被綁在一起傳出來,看起來像「一組設定」,但實際上兩者一個是必要、一個是多餘且有副作用。更直白地說:別人給你的環境變數設定,跟別人給你的處方藥一樣,要先搞清楚每一條的作用機轉,不能整包貼上。
第三,silent failure 才是最難 debug 的失敗模式。 Issue #61825 的真正價值不在它被修不修,而在它揭露了 Claude Code 的設計選擇——用環境變數做 hard gate、且不對使用者報「為什麼沒生效」。這跟急診裡「沒症狀的隱性病灶」是同個道理:沒抱怨的東西,最容易漏掉。以後遇到「某 Claude Code 功能我以為打開了但其實沒生效」,第一個要查的就是有沒有環境變數在背後當守門員。
Sub-agent 引用 issue,這次我學到的另一件事
順帶補一個 meta 心得:今天派的 sub-agent 在報告裡引用了 issue #61825,當下我直覺懷疑它捏造,因為「具體編號 + 完美佐證」是 LLM hallucination 的典型形狀。結果這次它沒捏造,但它也錯了一個地方——它說 issue「未被關閉」,事實上是 closed as not_planned。
這個經驗讓我把「驗證 sub-agent 引用」的 SOP 再加一條:不只驗 issue 存不存在,還要驗它的狀態(open/closed)、關閉原因(fixed / not_planned / wontfix)、以及對應的程式碼版本。Issue 裡那段反編譯邏輯是 v2.1.150 的,我手上跑的是 2.1.154,理論上「移除環境變數會失效」這結論可能已經過時,要看官方有沒有修。雖然從 not_planned 看起來大概率沒修,但驗證的習慣不能因為「大概率」就省略。
今日收集的資源
GitHub Issue #61825:CLAUDE_CODE_WORKFLOWS 環境變數靜悄悄擋掉 workflows 功能
- 連結:https://github.com/anthropics/claude-code/issues/61825
- 今天主軸那條 issue。揭露 Claude Code 用環境變數做 hard gate、繞過 GrowthBook flag 評估的設計選擇,狀態是 closed as not_planned(已知不修)。遇到「某功能我以為打開了但沒生效」時,第一個要回查的就是這類隱藏開關。
Claude Code 官方 changelog
- 連結:https://code.claude.com/docs/en/changelog
- 用來對照「我手上跑的版本」跟「issue 裡提到的版本」之間有沒有相關修補。今天還沒細讀,留著作為日後追 Claude Code 行為變化時的固定查證點。
Claude Code Workflows 官方文件
- 連結:https://code.claude.com/docs/en/workflows
- 官方對 Workflows / ultrawork 的說明。配合 issue #61825 一起看,可以對「環境變數開關」跟「官方推薦啟用方式」之間的落差有更清楚的判斷。
Firebase Storage 連結
- 連結:https://firebasestorage.googleapis.com/.../
- 今天工作流程中跑到的一個 Firebase Storage URL,留作日後追蹤。
ECG Smith Search 邊緣函式
- 連結:https://ftnrvkvzzvlfvdqirhxq.supabase.co/functions/v1/ecg-smith-search
- 自家 ECG Weekly / Smith 全站搜尋的 Supabase edge function endpoint。今天
/search影片連結顯眼化改版後,這條 endpoint 是底層被打的入口之一,留紀錄方便日後追查。
急專大補帖 UI/UX 改造 preview 站
- 連結:https://er-quiz-app-v2-git-fix-ui-ux-2026-05-agoodbears-projects.vercel.app
- 今天下午 5 個 Opus agent 平行改造後的 Vercel preview。中途踩了一個雷:preview 環境沒設
VITE_SUPABASE_*變數導致白屏,補上後正常,最後 merge 上 production。又一條「環境變數靜悄悄害死整個 app」的案例——跟今天主軸是同款故事的兩個版本。