Codex CLI 使用笔记
太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处

Codex CLI 使用笔记

Codex CLI 是一个能直接进项目干活的开发助手。除了回答问题,它还可以读代码、改文件、运行命令,并根据错误输出继续处理。

这篇只记录我使用 Codex CLI 的经验。它适合在本地仓库中排查问题、修改代码、整理文档,也能接手一些重复但仍需要判断的工程任务。

这里只写常用流程。完整的安装和配置说明请看 Codex 官方文档

安装

已经安装 Node.js 和 npm 的话,可以直接运行:

npm install -g @openai/codex

安装后先确认命令可用:

codex --version

如果提示 codex: command not found,通常是 npm 的全局命令目录没有加入 PATH,需要检查本机的 Node/npm 配置。

登录

第一次使用前先登录:

codex login

有浏览器时会打开网页登录;远程服务器或无头环境可以改用设备码:

codex login --device-auth

登录信息保存在本机的 Codex 配置目录中。~/.codex/auth.json 是敏感文件,不要提交到 Git,也不要粘贴到聊天、工单或日志中。

启动

进入项目目录后直接启动:

cd /path/to/project
codex

如果任务很明确,也可以使用非交互模式:

codex exec "阅读 README,并总结这个项目的启动方式"

我平时更常用交互模式:可以一边看它的判断,一边补充上下文;任务复杂时,也方便随时打断或调整方向。

Shell 不是无关细节

Codex 可以调用终端,但命令文本最终由宿主提供的 Shell 解析。PowerShell、Git Bash、WSL Bash 和传统 cmd.exe 处理路径、引号、管道、环境变量、脚本后缀和命令查找的方式并不相同。忽略这一层,很容易把 Shell 的启动或初始化问题误判成 Codex、项目代码或其他 CLI 的问题。

在 Windows 上,我现在默认使用 MSI 安装的 PowerShell 7:

C:\Program Files\PowerShell\7\pwsh.exe

可以先确认当前进程确实是预期的 PowerShell:

$PSVersionTable.PSVersion.ToString()
(Get-Process -Id $PID).Path
(Get-Location).Path
Get-Command pwsh, git, node, npm, rg |
  Select-Object Name,Source,Version

我曾遇到过一次启动故障。当时使用的是 Microsoft Store 目录下的 PowerShell 7.6.3:

C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.3.0_x64__8wekyb3d8bbwe\pwsh.exe

它在 Codex 的受管终端中连续启动失败,而且错误发生在 PowerShell 执行命令之前:

CreateProcessAsUserW failed: 1312
指定的登录会话不存在。可能已被终止。

这类错误通常出在宿主创建进程时使用的 Windows 登录会话或令牌上,和 PowerShell 脚本、仓库代码没有直接关系。改用 MSI 路径后,同一环境里的 PowerShell 7.6.3、当前目录和普通命令都恢复正常。如果 PowerShell 能在自己的终端中启动,但 Codex 仍然报 1312,可以先重启 Codex 刷新登录会话,再确认它实际调用的 pwsh.exe 路径。

# 安装 MSI 版本的 PowerShell 千万千万千万不要用 MSIX 安装包的 PowerShell
winget install --id Microsoft.PowerShell --source winget --installer-type wix

Git Bash、WSL Bash 和裸 bash

安装 Git for Windows 后通常会有 Git Bash,但直接输入 bash,启动的不一定是它。我在本机运行:

Get-Command bash | Select-Object Name,Source

返回的是:

C:\Windows\System32\bash.exe

这个程序是 WSL 启动器,不是 Git Bash。Git Bash 的实际路径是:

C:\Program Files\Git\bin\bash.exe

所以需要 Unix Shell 时,最好明确选择 Git Bash,不要只写含义不确定的 bash。登录模式也会影响结果:我在本机以非登录模式启动 Git Bash 时,/usr/bin 没有正确加入 PATHheadcygpath 等命令无法找到,npm 甚至误触发了 WSL。改为登录模式后,MSYSTEM=MINGW64 和完整的 PATH 得到初始化,Git、Node、npm、ripgrep 以及路径转换都恢复正常。

进入 Git Bash 后可以这样确认环境:

printf 'bash=%s\n' "$BASH_VERSION"
printf 'msystem=%s\n' "$MSYSTEM"
printf 'shell=%s\n' "$SHELL"
printf 'path=%s\n' "$PATH"
command -v git node npm rg pwsh
cygpath -w "$PWD"

$SHELL 只是一个环境变量,不一定对应当前进程。判断 Bash 环境时,$BASH_VERSION$MSYSTEMPATH 和具体命令的解析结果更可靠。

我现在的选择

  • Windows 本机仓库、文件系统、进程、注册表和系统工具:默认 PowerShell 7。
  • 项目自带 .sh、文档明确使用 POSIX 语法或命令依赖 sedawkhead:显式使用 Git Bash,并确保登录环境已经初始化。
  • 真正需要 Linux 用户空间、Linux 包或 Linux 路径语义:使用已经安装发行版的 WSL,不把 WSL 启动器和 Git Bash 混为一谈。
  • Linux 或 macOS:按项目约定使用 Bash、Zsh 或其他本机 Shell。
  • cmd.exe:只作为 PowerShell 或 Bash 无法创建进程时的临时诊断后备,不作为默认开发环境。

排查 Shell 问题时,我会按下面的顺序逐层确认:

  1. 宿主能否创建 Shell 进程。先看 CreateProcessAsUserW、登录会话、权限和可执行文件路径。
  2. Shell 是否完成初始化。检查 Profile、登录模式、PATHMSYSTEM 和其他环境变量。
  3. 命令是否被正确解析。检查引号、空格、中文路径、管道、重定向、通配符,以及 PowerShell 和 POSIX 的语法差异。
  4. 目标程序是否真的启动。确认 Git、Node、npm、ripgrep 或项目脚本的版本与实际路径。
  5. 前面四层都正常,再查仓库代码、依赖和配置。

codex doctor 可以辅助检查本地安装、配置、认证、运行时、Git 和终端问题,但进程创建与 Shell 解析仍要自己判断。

常用命令

日常使用主要是下面几个命令:

codex --version
codex login
codex doctor
codex
codex exec "你的任务"

进入交互界面后,我常用这些斜杠命令:

/status
/model
/review
/exit

/status 可以查看当前任务、上下文用量和速率限制。

显示上下文统计

长任务很容易忽略上下文用量。剩余空间不多时,Codex 可能压缩历史。压缩本身没有问题,但在复杂修改中,提前知道还剩多少上下文更方便安排后续工作。

可以在 ~/.codex/config.toml 中固定显示底部状态栏:

[tui]
status_line = ["model-with-reasoning", "context-remaining", "current-dir"]

保存配置并重新打开 Codex 后,底部会显示模型、剩余上下文和当前目录。

更详细的信息可以通过 /status 查看:

/status

我的本地配置

Codex 的个人配置文件位于:

$HOME/.codex/config.toml

这份配置会影响所有受信任的项目。我把日常开发限制在工作区沙箱内,同时允许沙箱访问网络:

model = "MODEL_NAME"
model_reasoning_effort = "medium"
approvals_reviewer = "auto_review"

sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = true

workspace-write 允许 Codex 修改当前工作区,network_access = true 则允许沙箱访问 npm、文档服务和其他开发资源。danger-full-access 会放开更多系统限制,我在日常开发中通常用不到。

我还开启了底部状态栏:

[tui]
status_line = ["model-with-reasoning", "context-remaining", "current-dir"]

状态栏会持续显示当前模型、推理强度、剩余上下文和工作目录。修改配置后需要重新打开 Codex,已有会话不会自动加载全部新配置。

MCP 配置

我的本地配置保留了三个 MCP:Context7、CodeGraph 和 OpenAI Developer Docs。基本配置如下。认证 token 不要写进文章、仓库或截图:

[mcp_servers.context7]
url = "https://mcp.context7.com/mcp"

[mcp_servers.context7.http_headers]
CONTEXT7_API_KEY = "REDACTED_CONTEXT7_API_KEY"

[mcp_servers.codegraph]
command = "codegraph"
args = ["serve", "--mcp"]

[mcp_servers.openaiDeveloperDocs]
url = "https://developers.openai.com/mcp"

Context7 用来查第三方库和云服务的当前文档,CodeGraph 用来查当前仓库的符号与调用关系,OpenAI Developer Docs 则负责 OpenAI 产品文档。问题确实需要这些能力时再调用;简单的文件任务没有必要绕一层 MCP。

API key、登录凭据和其他 token 都是敏感信息。真实值只放在本机配置或密钥管理系统中,不提交到 Git,也不复制到公开文章。

是否需要安装或关闭 MCP

为了节省上下文,没有必要先关闭工具。减少无关读取和长输出通常更有效。只有启动速度、内存、CPU 或工具列表的固定成本已经明显影响使用时,我才会关闭不常用的能力。

没有安装某个 MCP,Codex 也照样能完成很多任务。整理文章、操作 Git、定位配置和小范围修改代码,通常用 rggit diff、文件读取和少量命令输出就够了。MCP 是增强能力,不是每项任务的前置条件。

我把这些增强项分成常用和按需两类:

  • context7:只在我明确指定时查询第三方文档。它不再是框架问题的默认入口,也不能越过项目本地文档和官方网站。
  • codegraph:理解代码结构、符号关系、调用链和影响范围。大仓库里它比纯文本搜索更适合作为第一轮定位工具,可以先让 Agent 知道模块之间的关系,再决定具体读哪些文件。

它们会增加一些本地进程和固定的工具说明。codegraph 能省去在复杂代码关系里反复运行 rg、来回读文件的麻烦;Context7 即使已经配置,也只代表工具可用,不代表每个框架问题都应该调用。

但它们不该成为所有任务的入口。修改 Markdown、查固定字符串、看配置或做单文件小改动时,rg 和直接读取文件更快。我的判断方式很简单:

  • 问题依赖“当前版本文档”:先读项目本地文档,再查官方网站或官方仓库。
  • 用户明确要求使用 Context7:再调用 context7
  • 问题依赖“代码结构关系”:用 codegraph
  • 问题只是“文本在哪里”:用 rg
  • 问题只是“这个文件怎么改”:直接读文件和看 diff。

可按需关闭的插件:

  • 文档、表格、演示、PDF 类插件;
  • 浏览器、Chrome、Computer Use 类插件,前提是不需要 Codex 做页面验证或浏览器自动化。

看到很多后台进程时,先分清它们是 MCP、插件进程还是项目服务;发现背景信息占用较高时,先检查上下文中是否堆积了长输出和无关文档。我更在意读取范围与输出长度,而不是一股脑关掉所有工具。

安装 Context7(可选)

只有确实需要 Context7,并且了解它的费用和调用方式时,才有必要把它接入 Codex。安装 MCP 不应同时写入“所有框架问题都必须调用”的全局规则;工具是否可用和任务是否需要使用,是两件不同的事。

npx ctx7 setup --codex

安装后可以在提示中明确指定 Context7,验证链路是否可用:

使用 Context7 查询 Next.js 15 App Router 的当前文档,并说明 route handler 的缓存行为

如果 Codex 能通过 Context7 定位官方文档,并据此回答问题,说明链路已经可用。

安装 CodeGraph

codegraph 用来给代码仓库建立结构索引。仓库中已有 .codegraph/ 索引时,Codex 可以先用它理解符号、调用链和影响范围;没有索引就继续使用普通文件搜索。

# 安装
npm i -g @colbymchenry/codegraph

# 初始化
codegraph install

安装完成后,进入目标仓库初始化索引:

cd /path/to/project
codegraph init

也可以显式传入路径:

codegraph init /path/to/project

初始化后,仓库中会出现 .codegraph/ 目录。有了索引,Codex 就可以先用 CodeGraph 理解代码结构,再决定要读哪些具体文件。这个仓库已经建立索引,所以遇到代码定位、调用链和影响面分析时,我会先从 CodeGraph 入手。

常用命令:

codegraph status
codegraph sync
codegraph explore "这个模块的入口和调用关系是什么"
codegraph node "src/path/to/file.ts"
codegraph query "handleSubmit"
codegraph callers "handleSubmit"
codegraph callees "handleSubmit"
codegraph impact "handleSubmit"
codegraph files
codegraph help
codegraph help explore

我最常用 codegraph explorecodegraph node。前者一次返回与问题相关的符号、源码片段和调用路径,后者读取指定符号或文件并附上行号。status 用来确认索引状态,sync 用来增量更新索引。

是否初始化取决于仓库规模和任务类型。只写文章或改少量配置时,没有索引也不碍事;需要跨模块理解代码时,再建立 .codegraph/ 索引更合适。

Context7 自动调用规则的问题

我后来发现,Context7 被频繁调用,不只是因为 MCP 已经配置好了,更直接的原因是全局 AGENTS.md 把它写成了强制前置步骤。原规则使用了 wheneverUse even when you think you knowAlways start with resolve-library-id 这类措辞:只要问题涉及库、框架、SDK、API、CLI 或云服务,Codex 就必须先请求 Context7。

这条规则的问题不只是范围太宽。Context7 是可能产生费用的第三方服务,但规则没有要求先检查项目中的本地文档,也没有要求用户明确同意。后面的排除项看似限制了使用范围,正常的框架配置、API 查询、版本迁移和调试却仍然都会触发。

在这个项目里,apps/blog/AGENTS.md 已经有一条 Next.js 规则:

# Next.js: ALWAYS read docs before coding

Before any Next.js work, find and read the relevant doc in
`node_modules/next/dist/docs/`.

它要求编码前读取项目中实际安装版本的 Next.js 文档,但没有明确禁止 Context7。全局规则和项目规则并不冲突,于是 Codex 会同时执行两件事:先读本地文档,再调用 Context7。npm workspace 还会提升依赖,因此这个仓库的文档实际位于根目录:

node_modules/next/dist/docs/

另外,已安装的 $HOME/.agents/skills/context7-mcp/SKILL.md 也可能声明“提到 React、Next.js 等框架就自动触发”。只修改全局 AGENTS.md,却继续保留这个自动触发条件,仍然可能产生不必要的请求。

仅凭这些规则不能断定 Context7 本身具有恶意,但这种写法确实带有明显的特定服务导流倾向:它消除了 Agent 根据本地资料和任务类型作判断的空间,也没有照顾调用成本。我的调整原则是,本地、版本匹配的资料优先,付费第三方服务只能显式选择,不能成为所有技术问题的默认入口。

全局 AGENTS.md 可以改成下面这样:

## Documentation

- 优先读取项目中与实际安装版本对应的本地文档、类型、源码和测试。
- 对于 Next.js,如果存在 `node_modules/next/dist/docs/`,必须优先使用该目录。
- 本地资料不足时,查询对应项目的官方网站或官方仓库。
- 不得自动调用可能产生费用的第三方文档服务。
- 只有用户明确指定 Context7 时才可调用 Context7。

对应的 Context7 Skill 也应卸载,或者把触发条件改为“用户明确要求使用 Context7”。否则 Skill 仍可能绕过上面的使用原则。对于常见 Web 开发问题,我现在按下面的顺序选择资料:

  1. 项目中的本地文档、类型、源码、测试和锁定的依赖版本。
  2. 框架或工具的官方网站、官方仓库和 release notes。
  3. Web 平台问题优先查 MDN Web Docs
  4. 需要统一搜索多个 API 文档时,可以使用支持离线阅读的 DevDocs
  5. 只有明确需要 Context7 的检索能力,并且接受相应费用时,才主动指定它。

Next.js 官方文档还提供了适合工具检索的 llms.txt。本地文档缺失时,可以直接读取官方资料,不必先经过第三方聚合服务。

Skills:查找与安装

Skill 是一组可复用的 Agent 工作说明,通常保存在 SKILL.md 中。它可以补充某个领域的工作流,例如 Next.js 约定、浏览器自动化、系统化调试、数据分析或创建新 Skill。Skill 和 MCP 不是一回事:MCP 提供工具与外部数据,Skill 说明处理任务的方法和检查项。

可以直接用 npx skills 查找和管理 Skill,无需先全局安装 CLI。搜索时使用具体的任务关键词,结果只作为候选:

npx skills find <任务关键>

也可以在 skills.sh 按主题、来源和安装量浏览。找到候选项后,我会先看仓库来源、适用的 Agent 和最近维护情况,再决定是否安装。Skill 会改变 Agent 的行为,安装第三方 Skill 和安装依赖一样,都应该先审阅来源与 SKILL.md,不能只看名称。

安装 find-skills

如果想让 Codex 根据任务推荐 Skill,可以先安装 find-skills

npx skills add vercel-labs/skills --skill find-skills

安装后,可以直接向 Codex 提问:

帮我找一个适合检查 Next.js 性能的 skill,并比较来源、安装量和适用范围

find-skills 只负责发现候选项,不会替你判断它们是否值得安装。仓库来源、权限范围、维护状态和 SKILL.md 内容仍需自己确认。

常用 Skill 查找清单

搜索时直接描述任务,不必预设某个关键词一定对应可用的 Skill:

# 进入交互式搜索
npx skills find

# 按任务关键词搜索
npx skills find <任务关键>

npx skills add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices

搜索结果只是候选索引。安装前要确认来源仓库和 SKILL.md;如果只想查看仓库提供了哪些 Skill,可以使用:

npx skills add OWNER/REPO --list

常用管理命令:

# 查看已安装的 Skill
npx skills list

# 查看某个仓库提供的 Skill,不安装
npx skills add OWNER/REPO --list

# 安装指定 Skill;默认安装到当前项目
npx skills add OWNER/REPO --skill SKILL_NAME

# 全局安装,供所有项目使用
npx skills add OWNER/REPO --skill SKILL_NAME --global

# 更新已安装的 Skill
npx skills update

# 删除不再使用的 Skill
npx skills remove SKILL_NAME

项目级安装便于随项目复现,全局安装更适合个人通用工作流。Skill 也不是越多越好:每个已启用的 Skill 都会增加说明成本,还可能改变 Agent 的处理方式。我的做法是一次只安装一个候选项,确认它确实改善了结果,再决定是否长期保留。

项目信任和记忆

我还启用了记忆功能,并把当前项目标记为受信任:

[features]
memories = true

[memories]
disable_on_external_context = true
generate_memories = true
use_memories = true

[projects."/path/to/trusted-project"]
trust_level = "trusted"

项目设为 trusted 后,Codex 才会加载其中的 .codex/ 配置。只对自己确认过的仓库开启它;面对不熟悉的项目,不要为了省事直接设为信任。

使用习惯

我习惯把 Codex 当成一个会动手的同事,而不是搜索框。命令示例也不默认使用 Bash:Windows 本机任务优先用 PowerShell 7,遇到 POSIX 脚本再明确切换到 Git Bash。代码块会标注实际使用的 Shell,免得把不同语法混在一起。

简单问题直接问就行。涉及代码修改时,最好说明边界,例如修改哪个目录、哪些文件不要动、完成后运行什么检查。稳定的仓库规则可以写进 AGENTS.md,不用每次重复交代。

涉及提交身份、提交边界、测试是否应该沉淀成回归用例这类协作规则,可以单独参考《Agent 协作中的提交与测试边界》。

Codex 改完后,我仍然会看一遍 diff。它能省时间,但最终确认改动的人还是自己。

工具进程和上下文不是一回事

使用 Codex 时,如果看到很多后台进程,或发现背景信息已经占用了不少 token,很容易以为每次对话都读取了大量仓库内容。其实这是两件事:本机运行了哪些工具进程,以及当前模型上下文中装进了哪些内容。

MCP server、插件运行时、代码索引服务和浏览器控制桥接都可能表现为本地进程。它们负责向 Codex 提供不同能力,例如:

  • codegraph:为仓库建立代码图谱,支持查符号、调用链、影响范围等结构化代码问题。
  • context7:按需查询库、框架、SDK、CLI、云服务的当前文档。
  • 文档类插件:处理 PDF、Word、PPT、表格等文件。
  • 浏览器类插件:控制内置浏览器、Chrome 或桌面应用。

这些进程会占用 CPU 和内存,但不一定占满上下文窗口。上下文主要消耗在文本、工具说明、对话历史、工具输出、图片和文件引用上。

上下文主要由什么占用

一次对话的 token 用量通常来自以下几部分:

  1. 系统和开发者规则

    Codex 会注入安全、工具调用、协作模式、文件编辑、Git 和前端设计等规则。这是每次对话都会承担的基础成本,用户通常看不到完整内容。

  2. 当前仓库指令

    仓库根目录和子目录下的 AGENTS.md 会进入上下文。把稳定规则写进仓库很方便,不过规则本身也会占用上下文预算。

  3. 可用工具和插件说明

    启用的 MCP、插件、App 和 Skill 会向模型提供工具 schema 与触发说明。工具越多,固定成本越高。

  4. 已使用 skill 的完整说明

    Skill 列表只占一部分。任务触发某个 Skill 后,Codex 还会读取对应的 SKILL.md。这在查询 Codex 机制、云服务或框架当前用法时很有用,但仍应控制读取范围。

  5. 对话历史和工具输出

    命令输出、搜索结果、长日志和文档片段都会进入上下文。宽泛搜索和一次输出太多内容,是最常见的浪费。

  6. 图片和文件引用

    图片、文件路径和截图附带的信息也会占用上下文。

排查工具进程

先看当前启用的 MCP:

codex mcp list

如果要确认本机工具进程来自哪里,可以先在 Windows 上查看 node.exe 的命令行:

Get-CimInstance Win32_Process -Filter "name = 'node.exe'" |
  Select-Object ProcessId,CommandLine

Linux 或 macOS 下可以用:

ps -eo pid,ppid,pcpu,pmem,args |
  grep -Ei 'node|codegraph|mcp|codex' |
  grep -v grep

命令行参数可以帮助区分普通 node.exe、CodeGraph 服务、MCP stdio server、Codex runtime 和项目自己的服务。不要只看进程名,还要留意仓库路径、--mcpserve 等参数。

另行检查 node_repl

Get-Process node_repl -ErrorAction SilentlyContinue |
  Select-Object Id,ProcessName,CPU,WorkingSet,Path

Linux 或 macOS 下可以继续按进程名过滤:

ps -eo pid,ppid,pcpu,pmem,args |
  grep -Ei 'node_repl' |
  grep -v grep

node_repl.exe 是 Codex 自带的 runtime,不是项目中的 Node 服务。

控制上下文输出

Codex 自身机制可能随版本变化,这类问题值得查官方 manual。但不要上来就搜整份文档,否则很容易产生大量最后用不到的输出。我的做法是:

  • 先用目录或关键词定位章节;
  • 只读取 MCP、plugins、skills、app runtime 相关片段;
  • 搜索结果限制条数和上下文行数;
  • 对工具输出设置较小的输出上限;
  • 避免把长日志、长文档、完整配置一次性塞进上下文。

普通 Git 和文件任务也是如此。上下文窗口不是日志池;一次常规的合并、清理或验证,如果直接塞入完整的 git status、全量路径、git diff --check 警告和批量删除输出,很快就会消耗掉大量空间。

我通常先看计数和摘要:

git status --short | Measure-Object
git diff --stat
git diff --name-only | Select-Object -First 50
git ls-files <generated-dir> | Measure-Object

Bash 下对应写法:

git status --short | wc -l
git diff --stat
git diff --name-only | head -50
git ls-files <generated-dir> | wc -l

需要确认具体问题时,再按路径过滤或抽样:

git status --short -- AGENTS.md
git diff --cached --stat -- .archive
git diff --name-only --diff-filter=U

Bash 下这些 Git 参数本身不变:

git status --short -- AGENTS.md
git diff --cached --stat -- .archive
git diff --name-only --diff-filter=U

确实需要保留完整证据时,可以写入临时文件;对话中只回传数量、关键路径和少量失败样例。提交代码时同样如此,除非任务明确要求,不必默认展示完整 diff、git show 或长日志。

参考