本日核心價值 (Core Focus): 用 Codex CLI 在 OS 強制的 Sandbox 裡改檔與跑測試:互動模式預設多為 workspace-write + on-request;
codex exec預設 read-only,寫入必須加--sandbox workspace-write。禁止為了方便打開 danger-full-access。
概念說明與實戰情境 (Overview)
ChatGPT 能產出計畫與 diff,但無法在你的工作區實際編譯、跑 pytest、看紅燈。Codex CLI 把模型放到本機 Sandbox:可讀工作區、可(在授權模式下)寫檔、預設不能出網。開發者要掌握三個 mode、保護路徑、以及互動 vs codex exec 的預設差異。弄錯預設值時,最常見的失敗是「exec 什麼都沒寫入」或「為了 git commit 關掉整個沙箱」。這兩個坑都可以先核對旗標避開。
關鍵操作與範例 (Implementation & Example)
安裝 Codex CLI(官方套件 @openai/codex),然後在 repo 根目錄啟動。互動模式對已納入版本控制的資料夾,通常建議 Auto:workspace-write + on-request 核准;網路預設關閉,要出網必須另外打開。非 git 資料夾則常從 read-only 起跳,需你明確信任工作目錄。
npm install --global @openai/codex
cd /path/to/repo
codex
等價的顯式啟動:
codex --sandbox workspace-write --ask-for-approval on-request
三種 sandbox mode 必須分清:
| Mode | 能力 | 何時用 |
|---|---|---|
read-only |
讀檔、回答、規劃;寫檔與多數命令需核准或直接被拒 | 審 diff、問架構、CI 只讀掃描 |
workspace-write |
在工作區讀寫與跑命令;網路由設定另開,預設 OFF | 實作功能、跑測試、修紅燈 |
danger-full-access |
無 OS sandbox、可搭配關閉核准(--yolo) |
幾乎不該用;僅在外層已有強隔離(例如受控容器)且文件明確要求時 |
即使在 workspace-write,下列路徑仍是 read-only(遞迴保護):.git(含 gitdir: 指向的真實 Git 目錄)、.agents、.codex。因此 agent 不能在沙箱裡直接改歷史或覆寫 agent 設定來自我放行。commit 留在你自己的終端或外層腳本。
互動與非互動的預設不同,這是今日最重要的操作差異:
| 介面 | 預設 sandbox | 要改檔時 |
|---|---|---|
互動 codex(常見 Auto) |
多為 workspace-write + on-request;network OFF |
通常可直接編輯工作區,出網或出工作區需核准 |
codex exec |
read-only | 必須加 --sandbox workspace-write |
# 只讀:適合問問題。此命令不會改檔。
codex exec "Summarize how OrderService.GetTotal is tested."
# 要改檔、跑測試:一定要 workspace-write
codex exec --sandbox workspace-write \
"Implement plan.json. Run pytest -q. If tests fail, fix until green. Do not use the network. Do not modify .git."
Windows 讀者注意實作分叉:原生 Windows 走 Windows sandbox(config.toml 的 [windows] sandbox = "unelevated" 或 "elevated");在 WSL2 則走 Linux 的 bwrap + seccomp。WSL1 自 Codex 0.115 起不再支援 Linux sandbox。IDE 在 Windows 上若有 WSL2,可設 chatgpt.runCodexInWindowsSubsystemForLinux: true,讓命令與核准語意跟 Linux 一致。不要假設「Windows 原生」與「WSL」的拒絕行為完全相同;寫入失敗時先用 codex sandbox windows / WSL 內的 Linux sandbox 命令測單一指令。
耐久規則不要靠聊天記憶。在 CLI 對專案目錄執行 /init,產生 AGENTS.md 草稿,再改成團隊真正的 build / test / 禁令。/init 只是 scaffold,不應原樣提交。
# AGENTS.md
## Repo
- Backend: C# (.NET 8) under src/
- Tests: Python pytest under tests/ for the pricing helper used by the service
- Database: PostgreSQL
## Commands
- Unit tests: `pytest -q`
- Solution tests: `dotnet test`
## Constraints
- Smallest diff. No new dependencies unless asked.
- PostgreSQL only for SQL.
- Do not change files under .git, .agents, or .codex.
- Network is off unless the user enables it. Do not request danger-full-access.
## Done
- pytest -q exits 0
- Summarize changed files and the test command
個人預設放 ~/.codex/config.toml,專案覆寫放 .codex/config.toml(需信任專案才會載入)。下面示範「互動偏 Auto、exec 仍請在命令列顯式傳 sandbox」的寫法;不要把 danger-full-access 寫進預設。
# ~/.codex/config.toml
approval_policy = "on-request"
sandbox_mode = "workspace-write"
# 預設不要開網路
[sandbox_workspace_write]
network_access = false
# Windows 原生時才有意義;WSL2 使用 Linux sandbox
# [windows]
# sandbox = "unelevated"
驗證迴圈(generate → pytest → fix)應寫進 codex exec 的任務,而不是靠你在聊天裡來回貼錯誤。先放一個會失敗的測試,再讓 Codex 實作。
# tests/test_pricing.py
from pricing import apply_discount
def test_apply_discount_ten_percent():
assert apply_discount(200, 0.10) == 180
def test_apply_discount_zero_rate():
assert apply_discount(200, 0) == 200
pytest -q
# 預期 FAIL:pricing.py 尚未實作或未套用折扣
codex exec --sandbox workspace-write "$(cat <<'EOF'
Read tests/test_pricing.py.
Implement pricing.py so pytest -q passes.
Do not add dependencies. Do not use the network.
Do not touch .git, .agents, or .codex.
If pytest fails, fix the code and run pytest -q again until it passes
or you are blocked by missing context (then stop).
EOF
)"
pytest -q
# 預期 PASS 後再由人工 git add / git commit
對照 Day 03:先通過 CodeChangePlan,再把 test_command 原樣傳入 exec。計畫是 high 或 blocked 就不要啟動 Codex。對照 Day 04:AGENTS.md 放「這個 repo 怎麼測」;prompts/test.md 放「測試要覆蓋哪些 Edge Case」。重複的長規則只保留一份。
把 verify loop 寫成外層契約,而不是口頭習慣。codex exec 的任務必須包含四句:實作計畫、跑測試、失敗則修、禁止網路與保護路徑。exec 結束後,本機或 CI 再跑一次 相同 test_command,兩次都必須 exit 0。Sandbox 內的綠燈不能單獨當合併條件:模型可能刪 assertion 換綠燈,這要靠 diff review 與 Day 04 的 review 模組擋下來。
網路維持關閉,直到任務明確需要套件下載或呼叫內部 API。打開網路時用 sandbox_workspace_write.network_access,不要為了 dotnet restore 直接切 danger-full-access。Windows 原生先確認 [windows] sandbox;同一條 pytest 若被拒,改到 WSL2 重跑,並比對拒絕原因。團隊應選定一種執行環境寫進 AGENTS.md,避免「我這邊可以、CI 不行」來自兩套 sandbox 實作。核准策略維持 on-request:出工作區、出網、破壞性操作要停下來問人。把核准設成 never 又開可寫沙箱,等於把 Day 01 的閘門拆掉。
注意事項與常見失敗 (Pitfalls)
codex exec 沒加 --sandbox workspace-write: 預設 read-only,模型「說已改檔」但工作區沒有 diff。修法:凡需要寫入或產生測試產物的 exec,一律顯式 workspace-write。官方已把舊的 codex exec --full-auto 標成相容路徑並會警告,不要再當新腳本預設。git commit 或出網改開 danger-full-access / --yolo: 等於拿掉 OS sandbox 與核准。修法:commit 在沙箱外執行;需要網路時用 [sandbox_workspace_write] network_access = true 或核准流程,而不是全關沙箱。.git: 保護路徑仍 read-only,hook 或設定不會被 agent 偷偷改掉。修法:把這三個目錄當政策,不要設計依賴 agent 自己 commit 的流程。pytest 可能一邊過一邊被擋。修法:團隊統一「原生 Windows」或「WSL2」其一;IDE 可強制 WSL2。WSL1 不要用。/init 產生的 AGENTS.md 原樣提交: scaffold 不含你的真實測試指令。修法:立刻改成可複製執行的 pytest -q / dotnet test,並寫明禁止事項。pytest -q 當獨立閘門。本日總結 (Takeaways)
codex exec 預設 read-only,改檔要加 --sandbox workspace-write。read-only 與 workspace-write;把 danger-full-access 視為事故選項而非加速器。.git、.agents、.codex 在 workspace-write 下仍 read-only。codex /init 產生 AGENTS.md 後必須改成真實命令;config.toml 設 sandbox_mode,不要預設開網路。codex exec --sandbox workspace-write → pytest → 紅燈再修 → 人工 commit。明日預告 (Next)
明日進入 Day 06 Function Calling 實戰 (上):讓 ChatGPT 自動鏈接外部 API 與資料庫,把「模型只能改檔」擴成「依契約呼叫外部工具」,並與今天的 Sandbox 邊界一起設計。