Hub Codex CLI 完整教學

第 3 篇 進階 · 第 8 章

個人化設定:config.toml

config.toml 是 Codex CLI 的「偏好設定面板」——一個純文字檔,你在裡面寫下「我想要它預設用哪個模型、要不要每步都問我、能不能改檔、能不能連網」,Codex 每次啟動就照著做。

想像你新請了一位助手。第一天他什麼都不懂,每件小事都來問你:「要用哪枝筆?」「這份文件可以動嗎?」「要不要先給你看一眼?」很煩對吧。config.toml 就是你寫給他的一張長期備忘錄:把你的固定偏好一次講清楚,以後他自己照辦,不用每次重講。

profile(設定組合包) 更進一步:你可以準備好幾張備忘錄,一張叫「日常」、一張叫「深度審查」、一張叫「離線」,要切換情境時喊一聲名字就換一整套。

這一章你會學到:

  • 設定檔放在哪、哪一份說了算(優先序);
  • 最常用的設定鍵速查(模型 / 安全 / 搜尋 / 風格),以及把終端機外觀(主題 / 鍵位 / 狀態列)調成自己順手的樣子;
  • 怎麼用 profile 一鍵切換「日常」與「深度審查」兩套設定;
  • 子程序環境、Windows sandbox,以及不想改檔時的 -c 一次性覆寫。

新手別怕

不一定要config.toml。Codex 不設定也能跑(用內建預設值)。這章是給你「想固定某些偏好、不想每次打旗標」時用的。看不懂的鍵先跳過,挑你需要的抄就好。

時效提醒

Codex CLI 更新很快,設定鍵會增減。本章每個鍵都來自查核過的官方文件,但逐字鍵名與預設值最終以實機 codex --help官方 Configuration Reference 為準。官方文件頁面目前未標版本號,撰稿對照版本為 Codex CLI 0.140.0(2026-06-15)。

8.1 設定檔位置、優先序與信任專案

設定檔放在哪?三個位置

config.tomlTOML 格式(一種給人看也好寫的設定檔格式,長得像 鍵 = "值")。它可以同時存在於三個地方:

層級路徑給誰用
使用者級(User)~/.codex/config.toml你這台電腦的個人偏好(最常用)
專案級(Project).codex/config.toml(放在專案資料夾裡)只在某個專案生效的設定
系統級(System)/etc/codex/config.toml(僅 🍎 Mac / 🐧 Linux)整台機器、所有人共用(通常管理員才設)

~ 是什麼?

~(波浪號)是「你的家目錄」的簡寫。
🍎 Mac / 🐧 Linux 上 ~/.codex/ 就是 /Users/你的帳號/.codex/(Mac)或 /home/你的帳號/.codex/(Linux)。
🪟 Windows 上對應到 %USERPROFILE%\.codex\(通常是 C:\Users\你的帳號\.codex\)。

來源:Config basics

同一個鍵被設了好幾次,聽誰的?優先序

如果你在好幾個地方都設了同一個鍵(例如 model),Codex 會照下面這個順序決定誰說了算。越上面越大,會蓋過下面的:

  1. CLI 旗標 / -c 一次性覆寫(你這次打的指令,最大)
  2. 專案級 .codex/config.toml(離工作目錄最近的那份)
  3. Profile 檔 ~/.codex/<名稱>.config.toml
  4. 使用者級 ~/.codex/config.toml
  5. 系統級 /etc/codex/config.toml
  6. 內建預設值(都沒設時的備援)

用一句話記:你「當下打的指令」最大,然後越靠近專案的越大,最後才輪到全域與內建預設。

生活化理解

像公司規定。你「現在當面交辦」(CLI 旗標)最即時;「這個專案的規矩」(專案 config)蓋過「你個人習慣」(使用者 config);最後才是「全公司預設」(系統 / 內建)。

來源:Config basics。官方逐字:「Codex resolves values in this order (highest precedence first)」。

⚠️ 陷阱一:有些鍵放在專案層會被「忽略」

這是新手最容易踩的雷。專案級 .codex/config.toml 不能覆寫某些「機器本地擁有」的安全 / 全域鍵——你寫了也沒用,Codex 會直接忽略(並可能警告)。

被忽略的鍵包含這些(來源:Advanced Configuration,官方逐字列出以下 10 個):

openai_base_url
chatgpt_base_url
apps_mcp_product_sku
model_provider
model_providers
notify
profile
profiles
experimental_realtime_ws_base_url
otel

重要提醒

簡單記:provider(模型供應商)、通知(notify)、telemetry(otel)、profile 切換 這幾類鍵,一律放在使用者層級 ~/.codex/config.toml。放進專案的 .codex/config.toml 會被靜默忽略。

為什麼?因為一個專案(可能是別人寫的、你 clone 下來的)不該有權力偷偷把你的模型供應商換掉、或要你的電腦執行通知程式——那是安全考量。

⚠️ 陷阱二:不信任的專案,整個 .codex/ 會被跳過

Codex 有「信任專案」機制。如果你把一個專案標記為「不信任(untrusted)」,Codex 會直接跳過該專案的 .codex/ 設定層,完全不載入。

來源:Config basics,官方逐字:「Project-scoped .codex/ layers only load when you explicitly trust the project」。

這其實是保護你

你從網路上抓一個陌生專案下來,它裡面可能藏了一份 .codex/config.toml 想偷偷放寬權限。Codex 預設不信任 = 不讓它的設定生效,等你親自確認「這專案我信得過」才載入。

改變 Codex 的家目錄:CODEX_HOME

~/.codex/ 這個資料夾叫做 Codex 的「家目錄」,裡面放 config、登入憑證、日誌、session 紀錄。你可以用環境變數 CODEX_HOME 把它搬到別的位置。

來源:Environment variables,官方逐字定義 CODEX_HOME 為 Codex 狀態根目錄,預設 ~/.codex

CODEX_HOME 當「身分切換器」用

搬家目錄不是只有「換個地方放檔案」這麼簡單,更實用的玩法是拿它做身分隔離。例如需要跑多個互不相干的自動化身分、或在 CI 裡怕污染你平常互動用的設定時:

CODEX_HOME=$(pwd)/.codex-agent codex exec "列出目前使用的指令來源"

這樣這次執行的 config.toml、登入憑證、history.jsonl、狀態資料庫,全部關在 ./.codex-agent 這個獨立資料夾裡,跟你平常互動用的 ~/.codex/ 完全不共用、不互相汙染。CI pipeline 裡每條 job 各給一個 CODEX_HOME,或是需要同時扮演「多個角色」分頭跑任務時特別好用。

8.2 常用鍵速查(模型 / 安全 / 搜尋 / 風格)

這一節是抄了就能用的速查。挑你需要的貼進 ~/.codex/config.toml 即可。每個鍵都附了允許值,寫錯值 Codex 不會接受。

第一步:把設定檔打開

如果 ~/.codex/config.toml 還不存在,自己建一個就好:

🍎 Mac / 🐧 Linux:

mkdir -p ~/.codex
codex             # 跑過一次,Codex 會幫你建好 ~/.codex 資料夾

🪟 Windows(PowerShell):

New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.codex"
codex             # 跑過一次,Codex 會幫你建好 .codex 資料夾

然後用你慣用的編輯器打開 ~/.codex/config.toml(🪟 Windows 是 %USERPROFILE%\.codex\config.toml)開始寫。

開工前先讓編輯器幫你抓錯

在檔案最上方加一行 schema 註解:

#:schema https://developers.openai.com/codex/config-schema.json

VS Code 或 Cursor 裝上 Even Better TOML 這款擴充套件後,這一行會讓編輯器認得整份 config.toml 的鍵名與型別,打錯字、填錯值型別(例如把布林值寫成字串)都會在你存檔前就被畫紅線提醒,比等 Codex 啟動後才發現「設了沒效」快得多。這行只是給編輯器看的註解,Codex 本身會忽略它,加不加都不影響實際運作。

A. 模型相關

允許值 / 範例說明
modelstring,例 "gpt-5.5""gpt-5.4"預設使用哪個模型
model_providerstring,預設 "openai"指向模型供應商(預設用 OpenAI)
model_reasoning_effortminimallowmediumhighxhigh推理「用力程度」,越高越深思但越慢
model_reasoning_summaryautoconcisedetailednone推理摘要詳細度;none = 不顯示
model_verbositylowmediumhigh輸出冗長度(GPT-5 Responses API)
model_context_window數字覆寫可用的 context token 數

範例:

model = "gpt-5.5"
model_provider = "openai"
model_reasoning_effort = "high"      # minimal | low | medium | high | xhigh
model_reasoning_summary = "auto"     # auto | concise | detailed | none

來源:Configuration Referencemodel 的範例值 gpt-5.5 / gpt-5.4 出自官方文件範例。

模型名以實機清單為準

文件範例用 gpt-5.5,但確切「預設模型」會因登入方式與平台不同

  • ChatGPT 帳號登入的 session,預設常見為 gpt-5.5
  • API key 的使用者,預設依平台不同(社群整理:🍎 Mac / 🐧 Linux 偏 gpt-5-codex、🪟 Windows 偏 gpt-5)。

這部分官方未逐字保證,請以你實機跑 /model(在 Codex 裡輸入)看到的清單為最終真相,別把某個版本號當鐵則。

B. 安全相關:批准(approval)與沙箱(sandbox)

這兩個鍵控制「Codex 動手前要不要先問你」和「Codex 能動哪些東西」,是第 6 章的兩大軸心。在 config 裡固定下來,就不用每次打旗標。

允許值說明
approval_policyuntrustedon-requestnever何時停下來問你批准
sandbox_moderead-onlyworkspace-writedanger-full-access能讀 / 能寫 / 無限制

approval_policy 三個值的意思:

意義
untrusted最謹慎,非信任的命令都要你批准
on-request模型自己判斷需要時才請求批准(常見的本地自動化選擇)
never從不停下詢問(務必搭配 sandbox 限制使用)

sandbox_mode 三個值的意思:

意義
read-only只能讀檔,不能改
workspace-write可讀、可在工作區內寫、可跑常規本地命令
danger-full-access拆掉沙箱限制(危險,只在隔離環境用)

範例(一個常見的本地組合):

approval_policy = "on-request"        # untrusted | on-request | never
sandbox_mode = "workspace-write"      # read-only | workspace-write | danger-full-access

來源:Configuration Reference,三個值與旗標逐字相符。

這不是「官方欽定的預設」

workspace-write + on-request 是社群與沙箱概念頁常推薦的組合,但官方 Reference 並未把它明文標為全域預設值(對這兩個鍵的 default 標 "No default")。所以這裡寫「常見組合」而不是「官方預設」,別把它當斬釘截鐵的標準。

網路上有人教你寫 [[approval_policy]] 陣列規則?那不是真的

偶爾會看到教學示範一種「進階寫法」,用陣列表格列一串規則,長得像:

[[approval_policy]]
type = "command"
pattern = "npm test"
action = "auto-approve"

這種「依指令 pattern 逐條配對、各自決定要不要自動放行」的規則引擎寫法,不在官方 Configuration Reference 的 schema 裡——approval_policy 的型別就是單一字串(untrusted / on-request / never)或單一表格,從來不是陣列。寫了這種 [[approval_policy]] 區塊,Codex 不會照規則列表運作,頂多被當成不認得的欄位(用 --strict-config 才抓得到)。想要「這幾類動作各自獨立決定要不要自動放行」的精細控制,官方提供的是granular 物件寫法(見第 6 章的批准機制),不是自己發明陣列語法。

sandbox_mode = "workspace-write" 時,還有一個子表可以微調可寫範圍與網路:

sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = false               # 預設工作區寫入模式「不」連網
exclude_slash_tmp = false            # 是否把 /tmp 移出可寫範圍
exclude_tmpdir_env_var = false       # 是否把 $TMPDIR 移出可寫範圍
writable_roots = ["/Users/YOU/.pyenv/shims"]   # 額外開放可寫的目錄

來源:Advanced Configuration,四個子鍵逐字相符。

連不了網很正常

workspace-write 模式下網路預設是的。所以你不能期待它直接幫你 npm installpip install(那些要連網)。需要時才把 network_accesstrue,並想清楚風險。

C. 網路搜尋

允許值預設說明
web_searchdisabledcachedlivecached要不要、以及怎麼讓它上網查資料
web_search = "cached"   # disabled | cached | live

來源:Configuration Reference,預設 cached

設了 cached,怎麼感覺它還是即時連網了?

有一種情況 web_search 會不理會你設的值、自動切成 live:當你用 --yolo 這類「完全放行」的沙箱設定啟動時(等於 danger-full-access 又不設批准關卡,細節見第 6 章的紅線三),Codex 會判斷你反正已經完全開放存取,乾脆直接讓搜尋走即時上網,不再走預先索引好的快取結果。日常搭配一般的 workspace-write 用不會有這個現象,只有你自己選了最寬鬆的執行模式時才會出現,算是「你都全開了,搜尋也一併全開」的連動設計。

D. 風格與小設定

允許值預設說明
personalitynonefriendlypragmatic溝通風格
file_openervscodevscode-insiderswindsurfcursornonevscode點擊檔案引用連結時用哪個編輯器開
history.persistencesave-allnone是否保存對話逐字稿
history.max_bytes數字history 檔大小上限(位元組)
personality = "friendly"   # none | friendly | pragmatic
file_opener = "vscode"     # vscode | vscode-insiders | windsurf | cursor | none

來源:Configuration Reference,各值逐字相符。

personality 是「列舉值」,不是任意字串

它只認 none / friendly / pragmatic 三個值之一。你寫 personality = "你好有禮貌一點" 是無效的——它不是讓你自由填一段話的欄位。想客製 AI 行為與語氣,正確做法是寫 AGENTS.md(詳見第 5 章)。

E. 打造終端機的樣子:[tui] 個人化

前面 A~D 談的都是「Codex 怎麼做事」;這一節換個角度,談「Codex 長什麼樣子」——顏色、鍵位、底部狀態列這些看得到、摸得到的介面細節,全部收在 [tui] 這個表格底下。這一章的標題是「個人化設定」,這一節大概是最字面意義上的個人化。

型別 / 允許值說明
tui.themestring,kebab-case 主題名配色主題,內建約 32 款
tui.keymap.<context>.<action>string 或 array<string>依情境(如 composer、vim_normal)自訂鍵位
tui.status_linearray<string>(有序)底部狀態列要顯示哪些項目、順序
tui.terminal_titlearray<string>(有序)終端機視窗標題要顯示哪些項目
tui.vim_mode_defaultboolean,預設 false是否預設用 vim 鍵位操作
tui.notificationsboolean系統通知開關
tui.animationsboolean介面動畫開關
tui.alternate_screenboolean是否切到終端機的全螢幕替代畫面

來源:Configuration Reference[tui] 表格與各子鍵逐字相符。

不想手打 TOML?多數 [tui] 鍵都能用 slash 指令「邊調邊存」

這幾個介面設定,Codex 都準備了對應的 slash 指令,在 session 裡輸入就能即時看到效果,選好後它會問你要不要存回 config.toml——確認就好,鍵名和型別不用自己記:

指令對應的 [tui]
/themetui.theme(即時預覽,選了才寫入)
/vim單次切換 vim 鍵位(要改預設值才動 tui.vim_mode_default
/statuslinetui.status_line(勾選、排序項目,見第 4 章

手動編輯 config.toml 適合「一次設定很多台機器」或「寫進 dotfiles 版控」的情境;日常單機調整,slash 指令通常更快、更不容易打錯鍵名。

主題(tui.theme):內建主題選好後(用 /theme 即時預覽),也可以自己帶主題進來。把 TextMate 格式的 .tmTheme 主題檔(例如 Catppuccin、rainglow 這類社群配色)丟進 $CODEX_HOME/themes/(預設 ~/.codex/themes/),檔名去掉副檔名、轉成 kebab-case,就會自動出現在 /theme 選單與 tui.theme 的可用值裡,不用額外註冊。

[tui]
theme = "catppuccin-mocha"
vim_mode_default = false
status_line = ["model", "context-remaining", "git-branch"]
terminal_title = ["spinner", "project"]

鍵位(tui.keymap):context(情境)分組,常見的有 global(全域)、chatcomposer(輸入框)、editorvim_normal / vim_operator / vim_text_objectpagerlistapproval。每個 context 底下再指定 action(動作)對應哪個按鍵:

[tui.keymap.global]
open_transcript = "ctrl-t"

[tui.keymap.composer]
submit = ["enter", "ctrl-m"]

來源:Advanced Configuration,鍵位表格與 context 清單逐字相符。

找不到綁定時,會自動退回 global

某個 action 如果在目前 context(例如 composer)沒被明確綁定,Codex 會自動去查 [tui.keymap.global] 有沒有這個動作的綁定。所以客製鍵位時,只需要覆寫「這個 context 真的要跟全域不一樣」的那幾個動作,其餘沿用全域設定即可,不用每個 context 都整組複製一遍。想明確解除某個綁定(讓它「什麼都不做」而不是繼續往上找 fallback),把值設成空陣列 []

狀態列與視窗標題(tui.status_line / tui.terminal_title):兩者都是「有序的 ID 陣列」——你列出想看的項目、順序就是顯示順序。/statusline 那個勾選+排序的選單(第 4 章已介紹過)做的事,就是幫你生出這行 status_line = [...]。想整個隱藏,設成 null 或空陣列 [] 即可。

vim 鍵位(tui.vim_mode_default):預設 false(一般鍵位)。習慣 vim 的人可以把它設 true,讓每次啟動都是 vim 模式;只是這次想用一下、不想改預設值,在 session 裡打 /vim 單次切換就好,不會動到 config.toml

全螢幕替代畫面(tui.alternate_screen):第 1 章提過旗標 --no-alt-screen 可以單次關掉這個效果,方便錄影或事後往上捲 log;tui.alternate_screen 就是它的永久設定版——設成 false,以後每次啟動都留在主捲動緩衝區,不用每次都加旗標。

主題自訂目前有個已知限制

社群在 GitHub issue 回報過:自訂 .tmTheme 檔裡設定的背景色,有時會被 Codex 忽略、改用內建的背景色,前景色與語法配色通常沒問題。真的要做到背景也 100% 照自訂主題走,先小範圍測試確認效果,別直接假設完全套用;這是社群回報的已知限制,不是官方文件逐字保證的行為,可能隨版本改善。

抓拼錯的好幫手:--strict-config

設定鍵很多、又會隨版本變,你很容易把鍵名打錯一個字母而不自知(打錯的鍵就是被靜默忽略,難怪「設了沒效」)。加上 --strict-config 旗標,Codex 遇到不認得的設定欄位就直接報錯,逼你當場發現拼錯。

codex --strict-config

來源:Command line options,官方逐字:「Error when config.toml contains unrecognized fields」。

改了設定沒效?五步排查

  1. 先確認不是「舊 session 還沒吃到新設定」——config.toml 的改動只在新開的 session 才會載入,已經在跑的視窗不會自動重讀,懷疑沒生效先整個關掉重開;
  2. /debug-config第 4 章介紹過)——官方提供的分層診斷指令,直接印出「這個鍵目前是哪一層設定贏」,比自己一層層排查快;
  3. codex --strict-config,看看是不是鍵名拼錯;
  4. 確認沒把 provider / notify / otel / profile 類鍵錯放在專案層(8.1 陷阱一);
  5. 確認改的是對的那一份檔(優先序,8.1)。

⚠️ 比拼錯鍵名更兇的地雷:TOML 語法本身寫壞

--strict-config 抓的是「Codex 讀得懂這份檔案、但裡面有它不認得的欄位」。還有一種更兇的錯誤——TOML 語法本身寫壞,檔案從頭到尾就解析不起來。這種情況下 Codex 甚至不會啟動,--strict-config 也幫不上忙,因為連進到「檢查欄位」那一步都到不了。

兩條 TOML 自己的規則最容易被踩到:

  • 頂層 鍵 = 值 一定要寫在所有 [表格] 標頭「之前」。檔案裡一旦出現過一個 [表格名],後面每一行都會被當成那個表格「裡面」的內容,直到下一個表格標頭出現為止。想加一個新的頂層設定,卻手滑貼到檔案尾端(某個表格後面),值不會報錯,但意思整個變了,鍵靜靜地跑進別的表格裡去。
  • 同一個 [表格] 名稱不能在檔案裡宣告兩次。例如檔案裡出現兩段各自的 [sandbox_workspace_write],只有第一段會被解析,第二段會直接觸發「重複鍵」錯誤。這種情況常發生在:某個編輯器擴充套件或安裝腳本每次都用「附加寫入」而非「真正解析後合併」的方式更新設定檔,同一段設定就這樣被重複貼了好幾次,越跑越長。

這類語法錯誤跳出來的訊息長這樣(真實回報過的錯誤案例):

failed to load configuration: ~/.codex/config.toml:228:1: invalid type: map, expected a sequence

翻成白話:某一行,Codex 期待看到的是一份「清單」(陣列表格 [[區塊名]]),但實際讀到的是「單一物件」(表格 [區塊名]。這種型別錯誤最常發生在「本來就該有好幾筆」的結構上——例如第 9 章會教的 MCP 伺服器清單、第 13 章會教的 hooks 設定,這類欄位官方 schema 定義成陣列表格(像 [[hooks.PreToolUse]]),如果手滑少打一個中括號寫成單一表格 [hooks.PreToolUse],就會踩到這個錯誤。

看到 invalid type 這類「型別」錯誤,先數中括號

單一表格是一個中括號 [名字],陣列表格(可以重複出現、收集成一份清單)是兩個中括號 [[名字]]。錯誤訊息裡的路徑與行號(例如上面例子的 228:1)會直接告訴你問題出在檔案的哪一行,照著找過去,通常就是這兩者搞混了。

8.3 Profiles:用獨立 overlay 檔切換情境

Profile 是什麼?

Profile(設定組合包)就是「另一份設定檔,疊在你主設定檔上面」。 你準備好幾套不同情境的偏好,要用哪套就喊它的名字,一鍵切換一整組設定。

最常見的用法:平常用「日常」設定(快、便宜、夠用);要做嚴謹的程式碼審查時,切到「深度審查」設定(用最強推理、最謹慎批准)。

官方現行寫法:一個 profile = 一個獨立檔案

這裡有個重要的版本差異要講清楚。Codex 現行官方推薦的 profile 寫法是「分層 overlay 檔」:

  • 主檔(base): ~/.codex/config.toml
  • 疊加檔(overlay): ~/.codex/<profile 名稱>.config.toml(檔名就是 profile 名)
  • 切換: 啟動時加 --profile <名稱>

當你下 --profile deep-review,Codex 會先讀主檔 ~/.codex/config.toml,再把 ~/.codex/deep-review.config.toml 疊上去覆寫

來源:Advanced Configuration,官方逐字:「When you pass --profile profile-name, Codex loads ~/.codex/config.toml, then overlays ~/.codex/profile-name.config.toml」。

動手做:建一個「深度審查」profile

第一步,建一個叫 deep-review.config.toml 的疊加檔:

# ~/.codex/deep-review.config.toml
model = "gpt-5.5"
model_reasoning_effort = "xhigh"     # 用最深的推理
approval_policy = "on-request"

第二步,要用它的時候:

codex --profile deep-review

就這樣。沒指定 --profile 時,Codex 用你的主檔 ~/.codex/config.toml;指定了就把對應的 overlay 疊上去。

來源:Advanced Configuration,範例與 --profile 用法逐字相符。

--profile 也有短旗標 -p

codex -p deep-review 等同 codex --profile deep-review。來源:Command line options

別跟舊寫法搞混

網路上不少舊教學會教你在主檔裡寫 [profiles.review] 這種內嵌區塊(inline [profiles.NAME])。那是較舊版本的寫法,版本相依、不是現行官方主推的方式。新手請直接學上面的「獨立 overlay 檔」寫法,別投資舊語法。

profile / profiles 鍵是「機器本地擁有」

回顧 8.1 陷阱一——profileprofiles 都在「專案層被忽略」的清單裡。所以 profile 的設定放在使用者層 ~/.codex/,別塞進專案的 .codex/

8.4 子程序環境、Windows sandbox 與 -c 一次性覆寫

這節是進階收尾,三個獨立小主題,挑你需要的看。

A. 控制子程序的環境變數:[shell_environment_policy]

當 Codex 幫你跑指令(例如跑測試、跑 build),那些指令是「子程序」。預設它們會繼承你 shell 的一堆環境變數——但有時你不想把某些敏感變數(像 AWS 金鑰)漏給它們。[shell_environment_policy] 就是控制這件事的。

[shell_environment_policy]
inherit = "core"                 # 繼承哪些既有環境變數做基底
ignore_default_excludes = false  # false = 維持自動過濾 KEY/SECRET/TOKEN 類金鑰
exclude = ["AWS_*", "AZURE_*"]   # 額外移除符合的變數(glob)
include_only = ["PATH", "HOME"]  # 只保留符合的變數(glob)
set = { CI = "1" }               # 明確設定 / 覆寫變數
子鍵允許值 / 型別說明
inheritnonecore繼承哪些既有環境變數做基底
include_onlyarray<string>只保留符合的變數(glob)
excludearray<string>移除符合的變數(glob)
ignore_default_excludesbooleanfalse 維持自動過濾金鑰類變數
setmap<string,string>明確設定 / 覆寫變數

來源:Advanced Configuration + Configuration Reference。Pattern 是大小寫不敏感的 glob*?[A-Z])。

預設就有保護

ignore_default_excludes = false(預設行為)會自動過濾掉名字含 KEY / SECRET / TOKEN 的變數,避免把金鑰漏給子程序。一般不用動它。

inherit 只認 nonecore

官方文件範例與說明只見這兩個值。網路上偶爾出現的 inherit = "all" 沒有官方佐證——別當確定值用,要用請先實機 codex --help / 看官方頁確認。

B. Windows 專屬:[windows] sandbox

🪟 Windows 使用者有一個專屬設定,控制原生 sandbox 用什麼權限模式跑:

[windows]
sandbox = "elevated"     # elevated(官方偏好)| unelevated(企業 fallback)
  • elevated:官方偏好的模式;
  • unelevated:企業環境的後備選項。

來源:00-MASTER-DOSSIER §6.7,標 確認。

這是 Windows 才有的鍵

🍎 Mac / 🐧 Linux 用不到 [windows] 區塊(它們用各自的沙箱實作,見第 6 章)。同理,系統層設定檔 /etc/codex/config.toml 只在 🍎 Mac / 🐧 Linux(Unix)上存在。

🪟 Windows 路徑寫進 config.toml,反斜線是地雷

TOML 的雙引號字串("...")跟大多數程式語言一樣,會把反斜線 \ 當成跳脫字元解析——\n 是換行、\t 是 tab。Windows 路徑習慣用反斜線分隔資料夾,直接貼進去就會出事:

# 錯:\P、\m 不是合法的跳脫序列,輕則解析失敗、重則被讀成錯誤字串
writable_roots = ["C:\Projects\my-app"]

正確寫法有兩種,挑一種、全篇統一:

# 對,方案一:改用正斜線(TOML 吃、Windows API 大多數情境也吃)
writable_roots = ["C:/Projects/my-app"]

# 對,方案二:反斜線雙寫跳脫
writable_roots = ["C:\\Projects\\my-app"]

這不是 Codex 自己發明的規則,是 TOML 格式本身的字串跳脫規則,任何 Windows 路徑值都適用——writable_rootsMCP 伺服器設定裡的 command / cwd,只要是字串路徑都要留意。

C. 不想改檔?用 -c 做一次性覆寫

有時你只是這一次想換個設定試試,不想真的去改 config.toml。用 --config(短旗標 -c)就能在指令裡臨時覆寫,只對這次生效

# 換模型(注意:值以 TOML 解析,字串要「雙重引號」避免 shell 吃掉)
codex --config model='"gpt-5.4"'

# 臨時打開工作區寫入模式的網路
codex --config 'sandbox_workspace_write.network_access=true'

# 把這次的 log 寫到指定目錄
codex -c log_dir=./.codex-log

來源:Command line options + Advanced Configurationcodex --config model='"gpt-5.4"' 為官方示範字串。

為什麼字串要兩層引號?

-c 後面的值是用 TOML 規則解析的。TOML 裡字串本身要有引號("gpt-5.4"),外面再加一層 shell 引號('...')避免 shell 提前把它展開,所以變成 '"gpt-5.4"' 這種「單引號包雙引號」的長相。看起來怪,但這是正解。

還有一個相關的乾淨環境旗標,排查「是不是我自己的 config 搞的鬼」時很好用:

# 完全跳過 ~/.codex/config.toml,用乾淨設定重現問題
codex exec --ignore-user-config "你的 prompt"

來源:Command line options,官方逐字:「Do not load $CODEX_HOME/config.toml」。

8.5 一份綜合範例(抄這個改)

下面是把本章常用片段拼成的一份教學範例。不是要你全抄——挑你需要的留下,其餘刪掉即可。每一段語法都對應前面有來源的官方範例。

# ~/.codex/config.toml

# --- 核心模型 ---
model = "gpt-5.5"
model_provider = "openai"
model_reasoning_effort = "high"      # minimal | low | medium | high | xhigh
model_reasoning_summary = "auto"     # auto | concise | detailed | none

# --- 安全:批准 + 沙箱(常見本地組合,非官方欽定預設)---
approval_policy = "on-request"        # untrusted | on-request | never
sandbox_mode = "workspace-write"      # read-only | workspace-write | danger-full-access

[sandbox_workspace_write]
network_access = false
exclude_slash_tmp = false
exclude_tmpdir_env_var = false

# --- 風格與搜尋 ---
personality = "friendly"              # none | friendly | pragmatic
file_opener = "vscode"                # vscode | vscode-insiders | windsurf | cursor | none
web_search = "cached"                 # disabled | cached | live

# --- 子程序環境變數控制 ---
[shell_environment_policy]
inherit = "core"                      # none | core
ignore_default_excludes = false
exclude = ["AWS_*", "AZURE_*"]

搭配一個獨立的 profile 疊加檔:

# ~/.codex/deep-review.config.toml
model = "gpt-5.5"
model_reasoning_effort = "xhigh"
approval_policy = "on-request"

要用 profile 時:

codex --profile deep-review

本章與官方範例檔

官方還有一份完整的 Sample Configuration(約上千行),把幾乎每個鍵都示範過一遍。想看更全面的清單,以那份為準;本章只挑新手最常用的講透。

8.6 🎓 高手進階

前面五節已經夠你日常用了。這一節是給「想把 config 玩到供應鏈防線、CI 防呆、企業強制層」的進階讀者。新手可以先跳過,等你管多台機器、多個專案、或在公司託管環境踩到「設了沒生效」的怪事時再回來。

A. 先校正一個版本硬傷:0.134.0 把 inline profile 廢掉了

8.3 已經教你「一個 profile = 一個獨立 overlay 檔」。這裡把背後的版本斷點講清楚,因為它直接決定你抄到的舊教學會不會失效。

Codex 0.134.0 起,profile 機制有一個 breaking change(破壞性變更)

  • --profile 不再config.toml 讀取內嵌的 [profiles.profile-name] 區塊;
  • 主檔頂層的 profile = "profile-name" 這個「選擇器」寫法不再支援
  • 舊設定要遷移到 ~/.codex/profile-name.config.toml(獨立 overlay 檔)。

來源:Advanced Configuration。官方原文主詞是 --profile:「In Codex 0.134.0 and later, --profile no longer reads [profiles.profile-name] from config.toml, and the top-level profile = "profile-name" selector is no longer supported.」

這個變更最陰險的地方是「不報錯」

你舊的 [profiles.review] 內嵌區塊在 0.134.0+ 不會跳錯誤,而是被靜默忽略——你以為切了 profile,其實一直在跑主檔設定。所以舊 dotfiles / 舊教學一定要主動遷移,不能等它報錯提醒你。

遷移配方(把舊 inline 改成新 overlay):

# 舊寫法(0.134.0 後失效)—— ~/.codex/config.toml 裡面
[profiles.deep-review]
model = "gpt-5.5"
model_reasoning_effort = "xhigh"

把區塊標頭 [profiles.deep-review] 拿掉,鍵提到頂層,另存成獨立檔:

# 新寫法 —— ~/.codex/deep-review.config.toml(整檔頂層,不再包區塊)
model = "gpt-5.5"
model_reasoning_effort = "xhigh"

overlay 檔「只寫差異」就好

官方逐字「it only needs the values that differ from your base config」——profile 檔只要寫和主檔不一樣的鍵,其餘自動繼承 ~/.codex/config.toml。不用整份複製貼上。

B. 多層優先序的進階細節:monorepo「最近者勝」與 trust 閘門

8.1 給過六層優先序表。進階要補兩個官方逐字細節,管 monorepo 或多專案時很關鍵。

細節一:同層之內,「離工作目錄最近」的那份 .codex/config.toml 勝。

Codex 會從專案根目錄一路走到你目前的工作目錄(cwd),把沿途每一個 .codex/config.toml 都載入;如果多份檔定義了同一個鍵,離 cwd 最近的那份贏

來源:Config basics,官方逐字:「Codex walks from the project root to your current working directory and loads every .codex/config.toml it finds. If multiple files define the same key, the closest file to your working directory wins.」

monorepo 實戰

大型單一儲存庫(monorepo)裡,你可以在根放一份通用 .codex/config.toml,再在 packages/frontend/.codex/config.tomlpackages/api/.codex/config.toml 各放一份子目錄專屬覆寫cd 進哪個子套件,就由那個子目錄最近的 config 決定設定——同一個 repo、不同子專案、不同 config。

細節二:標記為 untrusted 的專案,整個 .codex/ 全鏈被跳過。

8.1 陷阱二講過信任機制。進階要知道它跳過的不只 config:untrusted 專案的 .codex/ 底下的 config + hooks + rules 全部跳過,只有你的 user / system 層會生效。

來源:Config basics,官方逐字:「If you mark a project as untrusted, Codex skips project-scoped .codex/ layers, including project-local config, hooks, and rules.」

C. 供應鏈防線:那 10 個鍵為什麼鎖在專案層之外

8.1 陷阱一列了 10 個「放專案層會被忽略」的鍵。進階要理解這不是 bug,是刻意的供應鏈(supply-chain)安全防線

把這 10 個鍵分類看,就懂為什麼非鎖不可:

類別鎖它的理由
重導憑證流量openai_base_urlchatgpt_base_urlexperimental_realtime_ws_base_url防止專案偷偷把你的 API 流量導去攻擊者的伺服器
改供應商授權model_providermodel_providers防止換掉 provider 來竊取你的 token
改主機請求中繼資料apps_mcp_product_sku屬主機端擁有的 app 請求標識
跑本機命令notify防止專案塞通知命令在你電腦上執行
切 profileprofileprofiles防止專案偷換你的整組設定
遙測otel防止專案開啟 / 改寫本機 telemetry

來源:Advanced ConfigurationConfiguration Reference,兩頁逐字列出同一份 10 鍵清單。

官方的正向指引(逐字)

官方頁的措辭是正向的——「Set provider, notification, and telemetry keys in your user-level ~/.codex/config.toml; select config profiles with --profile profile-name and ~/.codex/profile-name.config.toml.」(上面那張「鎖它的理由」表是本書依鍵的用途整理的分類,不是官方原句。)

一句話記:provider / 通知 / 遙測 / profile 切換這幾類,只在 user / system 層設;專案層永遠管不到。 所以你 clone 一個惡意 repo,它的 .codex/config.toml 沒辦法把你的流量導走、偷 token、或在你機器上跑命令——這就是這道防線的價值。

D. CI 防呆:--strict-config + -c dot-notation 雙重引號

8.2 介紹過 --strict-config 抓拼錯。進階要強調它在自動化 / CI 的角色,以及搭配 -c 的精準用法。

官方頁沒有版本號,而鍵集合會隨版本漂移(像 0.134.0 砍掉 inline profile)。在 CI pipeline 裡掛 --strict-config,就能讓「舊 config 撞到新版不認得的鍵」當場顯式報錯,而不是靜默吃掉害你以為設定生效。

# CI 防呆:config 含本版不認得的欄位就直接 fail
codex --strict-config exec "run tests"

來源:Command line options,官方逐字:「Error when config.toml contains fields this Codex version does not recognize.」

-c--config)除了 8.4 教的換模型,還能用 dot notation(點記法) 直接設巢狀鍵,不必寫整段子表:

# 點記法關掉某個 MCP server(debug 用,不動檔)
codex -c mcp_servers.context7.enabled=false

# 點記法臨時開工作區網路(覆寫 network_access=false)
codex -c sandbox_workspace_write.network_access=true exec "npm install"

# profile + -c 疊加:CLI 最高優先,可在選定 profile 後再臨時覆寫單一鍵
codex -p fast-fix -c model_reasoning_effort='"high"'

來源:Command line optionsAdvanced Configuration,dot notation 範例 mcp_servers.context7.enabled=false / sandbox_workspace_write.network_access=true 為官方示範。

字串值「雙重引號」再強調一次

-c 的值是用 TOML 規則解析的。數字 / 布林 / 巢狀路徑(如 network_access=truemcp_servers.X.enabled=false)不用加引號;但字串值要兩層引號——外層 shell 單引號、內層 TOML 雙引號,寫成 model_reasoning_effort='"high"'。官方逐字提示:「When in doubt, quote the value so your shell doesn't split it on spaces.」

E. 企業強制層:requirements.toml(凌駕一切 config)

前面講的所有優先序——CLI 旗標、-c、profile、專案 config——都還有一個更高的天花板壓在上面,就是企業託管的 requirements.toml。個人使用者通常碰不到,但在公司託管機上排查「為什麼我設了 approval_policy = "never" 卻沒生效」時,要第一個想到它

性質行為
requirements.toml管理員強制約束,使用者不可覆寫衝突時 Codex 退回相容值 + 通知你
managed_config.toml管理員設的「起始預設值」使用者 session 內可改,但下次啟動會重新套回

當 Codex 在解析設定時——不論來自 config.toml、profile 檔、還是 -c 覆寫——只要某個值牴觸了強制規則,Codex 就退回一個相容值並通知你。也就是說 -c / profile / 專案 config 通通擋不住 requirements.toml

來源:Managed configuration,官方逐字:「if a value conflicts with an enforced rule, Codex falls back to a compatible value and notifies the user.」

強制來源的優先序(cloud 最高):

  1. 雲端託管 requirements(ChatGPT Business / Enterprise);
  2. macOS MDMcom.openai.codex:requirements_toml_base64);
  3. 系統 requirements.toml:🍎 Mac / 🐧 Linux 在 /etc/codex/requirements.toml,🪟 Windows 在 %ProgramData%\OpenAI\Codex\requirements.toml

可被約束的安全設定包含:批准政策、sandbox 模式、permission profiles、web search 模式等,對應欄位如 allowed_approval_policiesallowed_sandbox_modesallowed_permission_profilesallowed_web_search_modes

來源:Managed configuration,欄位名逐字相符。

託管機排查口訣

在公司機器上發現「我的 config 怎麼設都沒效」,別先懷疑自己拼錯——先確認有沒有 requirements.toml 強制層在壓你。具體會退回成哪個相容值,官方未逐字列對應表,以實機通知訊息與 /etc/codex/requirements.toml(或 MDM 設定)為準。

Profile 路由的更深玩法(下放第 15 章)

「一情境一 profile,把 model / 推理力度 / 批准 / 沙箱整組路由」「規劃深、執行淺」「review_model 單獨升 model」這類進階路由組合技,留到第 15 章統一深講。本章先把「overlay 檔怎麼建、版本斷點、優先序、防線」打穩。

F. 接自訂模型供應商:[model_providers.<id>]

8.2.A 提過 model_provider 預設是 "openai"。如果你的公司走自架代理伺服器(proxy)轉發請求、用 Azure OpenAI、Amazon Bedrock,或是在本機跑 Ollama / LM Studio 這類相容端點,可以在 [model_providers.<自訂名稱>] 底下定義一個新供應商,再讓 model_provider 指向它。

一個常見情境:公司要求所有模型呼叫都先過內部 LLM 代理伺服器做稽核與限流,代理伺服器再用一支「產生 token 的指令」動態換發憑證,而不是把長效 API key 寫死在設定檔裡:

model_provider = "proxy"

[model_providers.proxy]
name = "OpenAI using LLM proxy"
base_url = "https://proxy.example.com/v1"
wire_api = "responses"

[model_providers.proxy.auth]
command = "/usr/local/bin/fetch-codex-token"
args = ["--audience", "codex"]
timeout_ms = 5000
refresh_interval_ms = 300000

auth.command 這支程式只要負責一件事:把 token 印到標準輸出(stdout),Codex 會照 refresh_interval_ms(預設 300000 毫秒,即 5 分鐘)的頻率重新呼叫它換發新 token。比起把 API key 明文寫進 config.toml,這個做法讓憑證的簽發、輪替、稽核都留在公司自己的代理伺服器那一側,config.toml 裡完全看不到長效金鑰。

來源:Advanced Configurationmodel_providers 表格結構與 auth.command 機制逐字相符。

自訂 provider 的名字不能撞到保留字

openaiollamalmstudio 這幾個 id 是內建供應商保留給自己用的(連同內建的 amazon-bedrock),你的自訂 [model_providers.<id>] 不能用這些名字覆蓋,另外取個獨一無二的名稱(像上面例子的 proxy,或是 my_openaiazure)即可。

相關的一個小鍵:cli_auth_credentials_store

這鍵管的是「Codex 自己的登入憑證」要存在哪裡,跟上面自訂 provider 的 auth.command 是兩回事,但同屬「憑證別以明文存放」的關切範圍:預設 file(純文字 auth.json);機器上有系統金鑰圈可用時,改成 keyring 能避免 token 以明文型態留在磁碟上。不是「keyring 一定比較好就都該用」——像 CI 或無頭容器環境通常沒有系統金鑰圈可用,這種情境還是得維持 file,兩者依部署環境擇一。

小結

走完這一章,你會了:

  • ✅ 知道 config.toml 放在哪(使用者 / 專案 / 系統三層)、誰說了算(優先序);
  • ✅ 知道 provider / notify / otel / profile 類鍵不能放專案層、不信任的專案 .codex/ 會被跳過;
  • ✅ 會抄常用鍵設定模型、批准 / 沙箱、搜尋、風格;
  • ✅ 會設定 [tui] 的主題、鍵位、狀態列,也知道多數個人化其實用 /theme/statusline/vim 這些 slash 指令邊調邊存更快;
  • ✅ 會用獨立 overlay 檔做 profile,一鍵切換「日常」與「深度審查」;
  • ✅ 會用 --strict-config/debug-config 抓拼錯與分層問題、用 -c 做一次性覆寫、用 --ignore-user-config 乾淨重現問題,也認得出「陣列表格 [[ ]] 誤寫成單一表格 [ ]」這類 TOML 語法地雷;
  • ✅(進階)知道 0.134.0 把 inline [profiles.NAME] 廢掉、改用 overlay 檔 + --profile;懂 monorepo「最近者勝」、untrusted 跳過全鏈、10 鍵供應鏈防線、企業 requirements.toml 強制層凌駕一切,以及怎麼接自訂 model_providers(proxy / Azure / Bedrock / 本地端點)。

動手試試

  1. 建立 ~/.codex/config.toml,寫入 model_reasoning_effort = "high"web_search = "cached",存檔後跑 codex --strict-config 確認沒拼錯。
  2. 建一個 ~/.codex/quick.config.toml,裡面只放 model_reasoning_effort = "minimal",然後用 codex --profile quick 啟動,感受切換情境的差別。
  3. 在 Codex 裡輸入 /model,看看你實機的模型清單,跟你 config 裡寫的 model 對照一下。
  4. 在 Codex 裡輸入 /theme,挑一款喜歡的主題即時預覽;喜歡的話選它存回 config.toml,再打開檔案看看多了哪一行。

交叉複習

批准與沙箱的完整心智模型在第 6 章AGENTS.md 客製 AI 行為在第 5 章;MCP 的 [mcp_servers.*] 設定在第 9 章RUST_LOGcodex doctor 等排錯與更多進階鍵在第 13 章

本章官方文件參考