把 Codex Home 从隐藏目录搬出来,用 Git 管理 AI 工作流资产

我最初把 Codex 的重要目录打成 zip,上传到云盘,方便电脑损坏或换设备时恢复。规则和 Skill 改得多了以后,压缩包开始不够用:

  • 每次备份都是一个新的压缩包,不容易看差异。
  • 只知道「备份了」,但不知道具体变了什么。
  • 想回到某个历史版本,需要先下载、解压、人工比较。
  • 想在多台设备之间同步,也不够自然。

我需要比较每次改动、找回旧规则,也想在多台设备间同步,于是改用 Git。我把适合同步的文件放进独立仓库,再用链接挂回 Codex 默认读取的位置。

先分清资产和运行态

Codex 的本地状态通常在 ~/.codex 下面。这个目录有点像一个 AI 工具的用户主目录:里面既有真正值得保存的长期资产,也有大量只属于当前机器、当前登录态和当前进程的运行状态。

我现在只把可读、可审查、可迁移的工作流资产放进仓库:

codex-home/
  AGENTS.md
  global/AGENTS.md
  agents_references/
  rules/
  skills/
  tools/
  env/

global/AGENTS.md 是 Codex 全局运行规则,比如希望 Codex 用什么语气、怎么协作、遇到某类任务先看什么引用。

agents_references/ 放全局规则引用的细节文档。全局入口只保留触发条件和路径,长规则拆到这里,能减少每次会话一上来就读进大量细节。

rules/ 是更细的命令或执行规则,适合长期稳定、跨任务复用的边界。

skills/ 保存可复用流程,比如文档整理、排障和工具操作。下次遇到类似任务时,Codex 可以加载对应 Skill,不必重新整理一遍操作规范。

tools/ 放可复用的小工具、脚本或 MCP server 源码。这里保存源码、README、lockfile 和必要配置,不保存依赖安装目录和运行缓存。

env/ 只适合私有仓库。它可以保存内部工具需要的环境变量文件,但不适合作为公开模板直接分发。如果仓库会公开,应该改成 .env.example 或文档说明,真实 env 留在本机。

这些内容的共同点是:它们能被人读懂,也能通过 Git 看到演进历史。

不该提交的是运行态:

auth.json
config.toml
sessions/
archived_sessions/
browser-profiles/
cache/
plugins/cache/
tmp/
.tmp/
*.sqlite
*.sqlite-shm
*.sqlite-wal
logs/
worktrees/
generated_images/
shell_snapshots/
node_modules/
.venv/
__pycache__/

auth.json、browser-profiles/ 可能包含登录态或凭证,不能进 Git。sessions/ 和 archived_sessions/ 体积会越来越大,也可能包含大量上下文和内部信息。*.sqlite、cache/、.tmp/、logs/ 都强依赖当前机器和当前版本,同步到另一台设备上价值不大,风险不少。

我按用途划分:规则、Skill 和工具源码需要同步,登录态、会话数据库和缓存留在各自机器上。

长期工作流资产与本机运行态分别管理

为什么不再把整个 ~/.codex 变成仓库

最直接的想法是:

cd ~/.codex
git init

然后配一个白名单 .gitignore,默认忽略所有内容,只放行明确要同步的文件。这个方案能工作,但长期维护会有两个问题。

第一个问题是日常查找。我经常要在编辑器里看 Skill、检查规则是否过期,把它们放进平时使用的代码目录后,这些操作会顺手很多。

第二个问题更实际:Codex 会持续向 ~/.codex 写入登录态、数据库、会话和缓存。即使 .gitignore 很严格,维护规则时仍然要不断分辨哪些目录能动、哪些文件只是程序正在使用的状态。

早期我也试过另一种更粗的做法:把 ~/.codex 整个迁到 ~/code/codex-home,再让 ~/.codex 指向它:

早期方案:整个运行目录指向仓库

这比直接在隐藏目录里维护舒服,但它仍然把运行态和可迁移资产放在同一个真实目录里。维护一段时间后,更清楚的做法是保留 ~/.codex 作为运行目录,只把需要长期维护的文件和目录软链出去。

现在的结构:运行态留在 ~/.codex

现在推荐的是细粒度软链。

真实仓库放在日常代码目录:

~/code/codex-home/

Codex 继续使用默认运行目录:

~/.codex/

两边通过少数软链接连起来:

运行入口分别链接到可迁移资产

这样,Codex 仍然从熟悉的位置读取规则、Skill 和工具;人维护的是一个普通 Git 仓库。登录态、会话、sqlite、浏览器 profile、插件缓存和临时目录继续留在 ~/.codex,不跟着仓库漂移。

skills/ 有一个小例外,值得单独说一下。Codex 可能会在 ~/.codex/skills/.system/ 下放系统生成的 Skill,这些内容不是我手写的工作流资产,也不应该提交到自己的仓库。

如果只把自己写的 Skill 一个个链接进去,通常碰不到它;如果为了省心,把整个 skills/ 目录链接到仓库里,.system/ 就可能出现在仓库工作区里。这个时候不需要把整个方案推倒,只要在仓库 .gitignore 里忽略:

skills/.system/

这里需要隔离的是系统生成内容。它和人工维护内容刚好落在同一个目录层级;把 .system/ 当成运行态处理,仍然可以保留整个 skills/ 目录链接的便利。

AGENTS.md 要拆成两层

把 Codex 资产放进一个仓库后,会遇到一个容易忽略的歧义:仓库根目录也可以有 AGENTS.md,而 Codex 自己的 home 目录也有 AGENTS.md。

如果同一个 AGENTS.md 既写仓库迁移方法,又写跨项目协作规则,链接到 Codex home 后,其他项目也会读到与它们无关的迁移说明。我把这两种用途拆开:

codex-home/
  AGENTS.md          # 只描述这个仓库怎么维护、怎么迁移
  global/AGENTS.md   # Codex 全局运行规则

然后让 Codex home 里的入口指向全局规则:

Codex 入口指向全局行为规则

这样,根 AGENTS.md 只回答仓库问题:这个仓库保存什么、不保存什么、新机器怎么链接、提交前怎么检查。global/AGENTS.md 只回答 Codex 行为问题:默认语言、协作方式、遇到 Figma 或浏览器任务时读什么 Skill。

global/AGENTS.md 里引用细节文档时,路径也应该写成 Codex home 视角:

${CODEX_HOME:-$HOME/.codex}/agents_references/browser-channel.md

不要写成简单的 agents_references/browser-channel.md。全局规则会在很多项目里生效,引用路径必须能从 Codex home 找到,而不是依赖当前工作目录刚好是 codex-home。

当前机器怎么迁移

如果一台机器已经在使用 Codex,迁移时不要一上来就动登录态和 session。更稳的顺序是:

  1. 在日常代码目录里创建或 clone 私有仓库。
  2. 把长期资产整理进仓库。
  3. 备份 ~/.codex 里同名文件或目录。
  4. 用软链接把仓库里的资产挂回 ~/.codex。
  5. 启动 Codex,确认规则和 Skill 能正常读取。
  6. 最后再提交和推送仓库。

准备仓库目录这一步仍然可以手动做:

mkdir -p ~/code/codex-home/global
cd ~/code/codex-home
git init
git branch -M main

再把已有资产放进仓库。不同机器的情况不一样,下面只表达路径关系,真正执行前先看清自己本机是否已有对应目录:

cp ~/.codex/AGENTS.md ~/code/codex-home/global/AGENTS.md
cp -R ~/.codex/rules ~/code/codex-home/rules
cp -R ~/.codex/skills ~/code/codex-home/skills

如果已经有 agents_references/、tools/ 或私有 env/,也可以按同样方式放进仓库。没有就先不创建空目录。

真正把仓库挂回 Codex home 时,现在更推荐走一个跨平台入口:

node tools/setup-codex-home.mjs --repo "$HOME/code/codex-home" --dry-run
node tools/setup-codex-home.mjs --repo "$HOME/code/codex-home"

Windows PowerShell 里仍然是同一个脚本,只是路径写法不同:

node .\tools\setup-codex-home.mjs --repo "$HOME\Desktop\code\codex-home" --dry-run
node .\tools\setup-codex-home.mjs --repo "$HOME\Desktop\code\codex-home"

--dry-run 只打印计划,不改文件。确认它会备份哪些旧路径、创建哪些链接以后,再跑真实命令。

这个脚本内部做几件事:

  • 已经是正确链接时直接跳过。
  • 已有普通文件或错误链接时,先备份成 .local-backup.<timestamp>。
  • 缺失的可选目录会跳过,不为了凑结构创建空目录。
  • AGENTS.md、agents_references、rules、skills、env、tools 都按同一份映射关系处理。
  • skills/.system/ 继续按本机运行态处理,只保留在工作区并被 .gitignore 忽略。

迁移成功后做几个检查:

test -f ~/.codex/skills/skill-creator/SKILL.md
git -C ~/code/codex-home ls-files | rg '(^|/)(auth|sessions|browser-profiles|cache|tmp|logs|worktrees|generated_images|.*\.sqlite)'

第一条用来确认 Skill 可读。第二条用来确认 Git 没有跟踪运行态或敏感文件;正常情况下应该没有输出。链接本身是否正确,脚本最后也会打印 verify 结果。

平台差异收进脚本里

命令入口保持一致,链接类型在脚本内部按平台选择。

macOS 和 Linux 上,文件、目录都可以走普通 symlink。Windows 上要更细一点:目录优先用 junction;文件优先用 symbolic link,如果当前权限不允许创建文件符号链接,再退到同盘 hard link。

原生 Windows 路线现在是可以成立的。Codex 官方文档里,Windows 桌面应用和 CLI 可以在 PowerShell 里配合 Windows sandbox 使用;不需要为了 Codex 本身强行套一层虚拟机。真正要考虑的是链接类型、权限和本机文件系统。

Git Bash 适合日常跑很多类 Unix 命令,但它没有改变底层文件系统。把 macOS 那段 ln -s 原样交给 Git Bash,最后生成什么仍然会受到 Windows 权限、MSYS/Git 配置和目标类型影响。迁移这种长期动作,交给 Node 脚本显式分支更稳。

Windows 上可以这样检查:

Get-Item "$HOME\.codex\AGENTS.md" | Format-List FullName,LinkType,Target
Test-Path "$HOME\.codex\skills\skill-creator\SKILL.md"
git -C $Repo ls-files | rg 'auth|session|sqlite|browser-profiles|cache|tmp|logs|worktrees|generated_images|node_modules|\.venv'

如果 AGENTS.md 最后是 hard link,LinkType 不一定像 symbolic link 那样直观;这时重点看两边内容是否同步、Git 是否只跟踪仓库里的那份文件。

那 WSL 合适吗

WSL2 更像一条 Linux 运行路线,适合工具链本来就在 Linux 的工作流。

如果你的项目、本地工具链、包管理器、测试脚本本来就更偏 Linux,或者原生 Windows sandbox 在当前公司设备策略下跑不顺,Codex 的 WSL 文档 也建议选择 WSL2。这个时候就不要把仓库放在 /mnt/c/... 里来回跨文件系统访问,直接放在 WSL 的 home 目录,比如:

mkdir -p ~/code
git clone <private-repo-url> ~/code/codex-home

WSL 里也有自己的 ~/.codex。如果 Windows 原生 Codex 和 WSL 里的 Codex 都要用同一套资产,我会让两边各自 clone 同一个私有仓库,再用 Git 同步,而不是让 Windows 的 ~/.codex 和 WSL 的 ~/.codex 互相指。这样边界更清楚:Windows 运行态留在 Windows,WSL 运行态留在 Linux,真正共享的是 Git 里的工作流资产。

在另一台机器 fork 或 clone

换设备时,只需要 clone 私有仓库并重新建立链接,不用搬旧机器的整个 ~/.codex。

新机器上先让 Codex 自己创建默认目录,或者手动准备空目录:

mkdir -p ~/.codex

然后 clone 私有仓库:

git clone <private-repo-url> ~/code/codex-home

再运行跨平台脚本:

cd ~/code/codex-home
node tools/setup-codex-home.mjs --repo "$PWD" --dry-run
node tools/setup-codex-home.mjs --repo "$PWD"

如果新机器已有自己写过的 Skill 或规则,不要直接删备份目录。先把确实要保留的内容合并进 ~/code/codex-home,再删除 .local-backup.<timestamp>。

链接完成后,再执行登录或打开桌面应用:

codex login

登录态和其他运行状态由新机器上的 Codex 初始化。仓库同步的是规则和工具,不会让新机器继承旧机器的登录状态。

为什么主入口改成 Node

Shell 示例很适合解释路径关系,但这套流程要长期在 macOS、Windows 和 WSL 之间复用,主入口就不应该绑定某个 shell。

这个脚本我选了 Node。fsPromises.symlink(target, path, type) 支持 Windows 上的 file、dir、junction 类型;按官方文档,junction 只能指向目录,目标路径会被规范成绝对路径。目录链接的 Windows 分支可以这样写:

import { symlink } from 'node:fs/promises';

const type = process.platform === 'win32' ? 'junction' : undefined;
await symlink(targetDir, linkPath, type);

Python 的 pathlib、os.symlink、os.link 能处理路径和部分链接操作;Windows junction 则需要额外调用 Windows 命令、PowerShell 或 Win32 API。Node 提供的 type: "junction" 正好覆盖这一步,脚本可以在同一套文件 API 里完成平台分支。

无论用哪种语言,脚本都应该按「可重复执行」设计:正确链接不动,错误链接先备份,缺失目录跳过或创建明确需要的父目录,任何凭证、session、sqlite、缓存都不搬。

这个选型本身也值得单独写一篇。更完整的判断,我放到了把 Codex Home 迁移做成跨平台 Node 脚本。

迁移后要扫掉旧机器绝对路径

还有一类问题和链接无关,但迁移到多设备后很容易暴露:Skill、规则或工具脚本里写死了旧机器路径。

我会在迁移后扫一遍:

rg -n '/Users/|/home/|C:\\Users\\' AGENTS.md global agents_references rules skills tools env

扫出来不代表一定要改。比如某篇文档里为了举例写了 /Users/alice/...,可以保留。但如果是全局规则、Skill 触发说明或工具脚本里的真实工作路径,就应该尽量换成环境变量或相对稳定的入口:

${CODEX_HOME:-$HOME/.codex}
${CODE_DIR:-$HOME/Desktop/code}
${SUGO_WEB_REPO}
${FRONTEND_AI_KNOWLEDGE_REPO}

这样仓库迁到 Windows、macOS 或 WSL 时,真正需要改的是本机 env,而不是到处翻 Skill 和脚本。

私有仓库也要检查边界

远端仓库是私有的,不代表可以把所有东西都推上去。私有仓库降低了公开泄露风险,但不能消除误提交凭证、登录态和大体积运行缓存的风险。

我会把仓库分成三类:

  • 可以提交:global/AGENTS.md、agents_references/、rules/、skills/、可复用工具源码、README、lockfile。
  • 私有仓库才可以提交:内部工具 env、只给自己使用的私有 Skill、带个人工作流偏好的全局规则。
  • 不要提交:auth.json、config.toml、session、浏览器 profile、sqlite、日志、缓存、插件缓存、依赖安装目录、构建产物。

提交前至少做两件事:

git status --short
git ls-files | rg 'auth|session|sqlite|browser-profiles|cache|tmp|logs|worktrees|generated_images|node_modules|\.venv'

第一条看本次提交会包含什么,第二条看 Git 已经跟踪了什么。第二条只要有可疑输出,就先停下来检查。

日常维护

迁移完成后,我直接在 codex-home 里改规则、Skill 和工具,用 Git 看差异、提交和同步。Codex 仍从 ~/.codex 读取链接,登录态和缓存继续由它自己管理。

换机器时复用同一个仓库和链接脚本;遇到规则改坏,也能从提交历史找回旧版本。这个分工比反复打包整个 home 目录更适合日常维护。