
说实话那天下午我差点把 Codex 客户端卸载了。起因很简单我想让 Codex 帮忙梳理一下手头这个工程刚敲完启动命令整个终端卡在原地风扇直接起飞。打开任务管理器一看CPU 占用一路飙到 98% 以上Codex 相关进程占了大头。我第一反应是模型服务又抽风了可等了几分钟界面依旧没有反应CPU 还顶着满格这就完全不对劲了。折腾了一个下午重装客户端、清配置、换终端全都没用。最后顺着进程树一路扒下去发现罪魁祸首居然是一个躺在我用户目录下、连我自己都快忘了的 .git 文件夹。把它处理掉之后Codex 启动从卡到怀疑人生直接变成丝滑秒开。如果你也遇到 Codex 启动很卡、CPU 飙升的问题先别急着重装照着这篇文章排查一遍多半能直接定位到病根。1. Codex 启动卡顿先判断到底是卡在网络上还是本地在燃烧 CPU1.1 启动阶段 Codex 后台到底在忙什么很多朋友一遇到 Codex 启动慢第一反应就是网络问题。这个思路很自然因为 Codex 要连接模型服务、加载模型配置看起来确实像在等远程响应。但实际上Codex 这类 AI 编程工具的启动过程分两块一块是建立会话、加载模型配置这部分确实依赖网络另一块是初始化本地工作区、扫描项目文件、识别版本状态这部分完全是本地计算吃的是 CPU 和磁盘 IO。问题就出在第二块。Codex 作为一个要帮你改代码的代理它必须知道当前代码库长什么样有哪些文件、哪些文件被追踪、当前分支状态、工作区有没有未提交的改动。这些信息它不会去读空气而是直接调用本机的 git 命令来获取。只要工作区范围异常大这一步就可能变成灾难。1.2 三分钟自测离线启动 CPU 观察我通常用三步来判断问题属于哪一类第一步拔网线或者断开网络离线启动 Codex。如果断网之后 CPU 依然瞬间满格那几乎可以断定是本地在疯狂计算和网络无关。如果断网后 CPU 不高、只是卡在等待连接那才是网络问题。第二步启动 Codex 的同时打开任务管理器Windows、活动监视器macOS或 topLinux看 CPU 占用曲线。关键看两点占用率高不高以及高占用是不是集中在 Codex 相关进程上。第三步去 Codex 的日志目录翻一眼。Codex 会把运行日志写到用户目录下的.codex文件夹里有log之类的子目录。搜一下git看看有没有大量可疑的 git 调用记录。这一步在后续定位病根时非常有用。1.3 一个反直觉的判断规则这里有个经验之谈如果应用卡住但 CPU 占用很低大概率是在等网络响应这种卡是干等如果应用卡住的同时 CPU 冲到 100%那一定是本地有进程在空转或高负荷运转。Codex 启动卡的问题绝大多数属于后者。因为模型服务再慢也不会让你本机的 CPU 满载——等待网络的时候 CPU 是闲着的。一旦你观察到 CPU 顶着满格就别再怀疑网络了赶紧往本地进程方向查。我当时就是绕了这个弯路。先排查了半天网络配置又怀疑是客户端插件冲突重装了两遍 Codex浪费了不少时间。直到我开了任务管理器盯着看才意识到问题出在本机计算上。2. 从进程树里揪出git 风暴到底是谁在吃 CPU2.1 三平台定位高 CPU 占用进程的命令定位高占用进程是基本功但不同平台工具不一样我把三套命令都给你列出来总有一款用得上。Linux 下我习惯用top加排序或者直接用ps一条命令搞定top -o %CPU # 或者 ps aux --sort-%cpu | head -20macOS 下可以用htop如果装了的话没装就直接用活动监视器按 CPU 降序排列同样直观。终端里可以用ps aux -m | head -20Windows 下任务管理器默认只显示当前进程信息不够细。我建议用 Ctrl Shift Esc 打开任务管理器切到详细信息标签页点 CPU 列头按占用降序排列。如果要看得更细装一个 Process Explorer微软官方工具能直接看到进程树和每个进程的命令行参数。PowerShell 也有等效命令Get-Process | Sort-Object CPU -Descending | Select-Object -First 202.2 进程树里的见鬼现场我当时的观察结果是CPU 占用最高的确实是 Codex 相关进程这一点没跑。但诡异的是这个进程底下挂着一长串子进程每个子进程都不是在干什么复杂的计算而是在执行 git 命令。我用进程树工具展开一看当时就愣住了。Codex 进程下面挂着几十个git子进程有些还处于运行中有些在排队等待。命令行内容反复出现下面这几类git status --porcelain git ls-files git log -1 --format%H git diff --stat看到这一幕我第一反应是 Codex 是不是陷入了死循环。这些 git 命令一条接一条像是在无限重启。2.3 关键证据git 子进程的疯狂循环这里要说明一点Codex 作为 AI 编程代理在执行任务过程中调用 git 看状态、看差异、记录改动这是正常设计。我见过很多类似工具Aider、Cline 等都有这个行为因为 AI 需要知道文件有没有变化才能决定下一步怎么改。但正常调用和异常调用是有明显区别的。正常情况是你发一条指令它跑几条 git 命令拿到结果继续干活。异常情况是git 命令反复出现频率高到离谱而且每次执行时间都很长。你观察进程树的时候会发现同一批 git 命令在不停重启像是永远跑不完。我当时在进程树里数了一下Codex 主进程下面挂了 20 多个存活的 git 子进程几十秒内这些 git 进程的累计 CPU 时间涨了好几分钟。这已经不是调用 git 辅助工作了这分明是在跑一场 git 马拉松。2.4 排除幻觉真的是 git 在工作不是 V8 引擎在空转还有一个容易误判的点Codex 客户端本身基于 Node.js 环境V8 引擎跑 JavaScript 也吃 CPU。如果代码逻辑有 bug也完全可能出现 CPU 100% 的情况。怎么区分很简单看进程列表里到底是同一个进程在烧 CPU还是大量子进程在接力。如果是 Codex 主进程的 V8 引擎在空转你看到的是单个进程 CPU 占用极高不会有一群 git 子进程排队。我当时看到的是几十个 git 子进程此起彼伏这就锁定了方向——问题出在 Codex 和 git 的交互层而不是 JavaScript 逻辑本身。到这里问题的性质基本清楚了Codex 在不断触发 git 操作而 git 操作本身又慢到离谱于是 CPU 被拖死。3. 病根找到一个藏在上级目录里的巨型 .git 文件夹3.1 git 是怎么向上查仓库根的顺着 git 子进程这条线我第一反应是检查当前项目的 .git 文件夹。结果很意外当前项目的 .git 只有 12MB非常健康。那 Codex 里的 git 子进程为什么这么慢我调出 Codex 日志仔细看它初始化工作区时记录的路径发现它指向的根本不是我的项目目录而是我的用户主目录。这里的关键出在 git 的一个行为上git rev-parse --show-toplevel。当你在一个目录里执行 git 命令时git 会从这个目录开始逐级向上查找直到找到一个包含.git的目录然后把这个目录当成仓库根。git rev-parse --show-toplevel很多工具在初始化时不会问你的项目根在哪而是直接调用这个命令自动推断。Codex 也不例外。它从当前工作目录出发一路向上找仓库根结果找到了一个我完全没想到的地方——我的用户主目录。3.2 现场还原home 目录被误初始化成了 git 仓库我在现场排查时手动执行了一遍git rev-parse --show-toplevel输出结果赫然是/Users/用户名也就是我的用户目录。这个用户目录被初始化成 git 仓库我完全没印象。应该是某次手滑在~下执行过git init或者某个工具自动干的。反正结果就是用户目录下躺着一个.git文件夹这个文件夹把整个用户目录都纳入了版本管理包括桌面上的几百个项目、各种配置文件、下载目录、缓存文件全部被它追踪着。Codex 从我的项目目录向上查找仓库根第一个命中的就是这个用户目录级别的巨型仓库。于是它傻乎乎地以为当前项目其实就是整个用户目录开始对整个用户目录做全量扫描和差异分析CPU 不炸才怪。3.3 用三条命令坐实罪魁祸首如果你也怀疑自己遇到了同样的情况以下三条命令足够你完成定位第一条看当前目录的真实仓库根git rev-parse --show-toplevel如果输出结果不是你的项目目录而是某个上层目录那就要警惕了。第二条列出某个区域内的所有 .git 文件夹find ~ -maxdepth 4 -name .git -type d 2/dev/null这条命令会把你用户目录下四层以内所有 .git 列出来。注意加-maxdepth限制否则全盘扫描会很慢。第三条检查可疑 .git 的体积和内部对象数量du -sh .git git count-objects -vH我当时看到的结果是用户目录下的.git有 9.2GBloose objects 有几十万个提交历史几千次。这哪是一个正常的仓库这分明是把整台电脑都版本管理了。3.4 为什么巨型 .git 平时没感觉一遇 Codex 就爆炸这里有个很微妙的点用户目录被 git init 过不代表你平时能感觉到问题。如果你不用命令行操作或者只是偶尔在具体项目里跑 git那些命令从项目目录向上查也能命中这个巨型仓库但因为大部分项目改动不频繁单次 git 操作可能也就慢个几秒你根本不会注意。但 Codex 不一样。AI 编程工具的工作方式决定了它要频繁调用 git启动时枚举文件、任务执行中反复刷新状态、每次文件变化都要对比差异。这种高频、全量、重复的操作正好踩中了巨型仓库的软肋。它会在短时间内把几万次 git 调用的开销叠加起来CPU 直接被打满。所以你不是感觉不到是因为平时没有哪个工具会这么高频地压榨 git。4. 原理解读.git 为什么能拖垮 Codex以及所有 AI 编程工具4.1 AI 编码工具的工作区感知依赖什么我在 2.3 里提过Codex 这类 AI 编码代理在工作时要频繁调用 git。这里我把原理讲透一点。AI 编码工具要做的事本质上是一个循环读取代码库现状、规划改动、执行改动、验证效果。关键在第一步读取代码库现状它需要回答几个问题项目里有哪些文件最近改了什么当前分支和历史提交是什么样的这些问题的答案几乎全部藏在 git 元数据里。于是工具会做这些事用git ls-files枚举被追踪的文件清单用git status --porcelain判断哪些文件有变动用git diff生成当前工作区与 HEAD 的差异补丁用git log了解最近提交历史。这些操作对正常仓库来说都是毫秒级的但仓库一旦膨胀每个操作的成本都会成倍上升。4.2 从 git 数据结构看开销loose objects、索引与目录扫描要理解 .git 为什么会拖慢一切得稍微看一下 git 的内部结构。git 的对象存储分两种形态loose objects松散对象和 pack 文件打包文件。松散对象是零散存储在硬盘上的小文件一个对象一个文件pack 文件是把多个对象压缩打包成一个文件。正常维护的仓库会定期git gc把松散对象合并成 pack 文件这样访问效率高、占空间小。如果长期不维护松散对象越攒越多几十万个小文件散落在 .git/objects 里每次读取都是一次随机磁盘 IO慢得离谱。更致命的是文件树规模。当仓库根目录覆盖了整个用户目录时git status要拿索引里的文件清单和实际工作区做全量对比。几十万个文件挨个比对文件路径、修改时间、内容哈希这个开销在 CPU 和磁盘上都是灾难级。4.3 放大效应全量扫描加高频率刷新等于雪崩单个 git 操作慢本身还能忍。真正把问题放大的是频率。Codex 这类工具不是只跑一次 git 就完事它会在整个工作周期内反复检查工作区状态。文件一有变化它要刷新任务进度更新它要刷新你切换文件它还要刷新。每一次刷新都是从一个巨大的仓库根目录重新做全量扫描。打个比方一个保洁员来你家做深度保洁你以为她的服务范围是客厅结果她看到门牌上写着整栋楼于是她每一趟都从顶楼扫到底楼。文件越多她扫得越慢但她还是每十分钟完整扫一遍。别人问她为什么这么慢她说我在做深度保洁啊。4.4 正常仓库应该有多大给一个健康阈值参考根据我的经验可以给几个粗线条的参考值一个正常的项目仓库.git 体积通常在几十 MB 到几百 MB 之间。提交历史丰富的中大型项目.git 到 1GB 左右还在可接受范围。一旦 .git 超过几个 GB而且包含大量小文件对象不管什么工具来读都会明显变慢。关键是看git count-objects -vH输出的 count 值松散对象数量。如果松散对象数量超过几万个建议尽快跑一次git gc把松散对象打包成 pack 文件访问速度能提升一个量级。5. 处理方案移走、瘦身还是配置绕行5.1 方案 A直接重命名那一个 .git最快、回报最高如果你的巨型 .git 也是误建的比如用户目录被意外初始化或者某个根本不需要版本管理的文件夹被 init 过最简单暴力的方案就是把它移走或者重命名。以我的场景为例用户目录下的 .git 对我没有任何价值我执行mv ~/.git ~/.git.bak注意不要直接rm -rf先改名备份观察几天。确认 Codex 恢复正常、相关功能也没有异常之后再动备份。改完名字之后再启动 Codex你会看到立竿见影的效果。我当时把启动时间从 40 多秒降到了 2 秒左右CPU 峰值从 100% 降到 5%整个过程像换了台电脑。这正是标题里说的那个解法。所谓一个 .git 文件夹就解决了指的就是这个多余、误建、巨型化的 .git。5.2 方案 B历史不能丢用 filter-repo 给仓库瘦身如果你的巨型 .git 是某个真实项目只是历史里混进了大文件或大量无关目录那就不能简单删除了需要做历史改写。我推荐用git filter-repo它是目前最顺手的仓库历史清理工具。核心流程如下# 1. 备份整个仓库 cp -a .git .git.bak # 2. 从所有历史提交中去掉 node_modules 目录 git filter-repo --path node_modules --invert-paths # 3. 去掉历史中所有超过 10MB 的二进制文件 git filter-repo --strip-blobs-bigger-than 10M # 4. 清理过期引用和剩余对象强制 GC git reflog expire --expirenow --all git gc --prunenow --aggressive这里要提醒一句git filter-repo会改写提交哈希所有基于这个仓库的本地分支、远端同步都会受影响。如果这个仓库有协作者必须先商量好统一在清理后的新历史上重新同步。单人项目或者不太重要的仓库用完是真爽。5.3 方案 C配置级绕行让 Codex 别去碰那个巨库如果你的巨型仓库确实有保留价值或者你不想动历史那就从 Codex 这边入手把它的工作区边界限制在真正的项目目录内。具体做法有三点第一启动 Codex 时先cd到真正的项目根目录不要再用户目录、磁盘根目录这类上层位置启动。Codex 会从当前目录向上查找仓库根你把起点放对了它就不会误入歧途。第二在项目根目录维护好.gitignore把大型目录挡在代码库上下文之外。AI 编程工具在工作区扫描时通常都会参照 .gitignore 的规则来过滤不必要的文件。把node_modules、.venv、dist、build这类目录写进去既能加快工具启动也能减少模型上下文的浪费。第三如果 Codex 支持自定义工作区忽略规则就在配置里补充排除项和 .gitignore 双保险。5.4 三个方案怎么选一张表讲清楚方案操作难度对历史的影响恢复难度适用场景重命名/移走 .git极低仓库失效低改回来就行误建仓库、仓库无价值filter-repo 瘦身中高改写全部历史高需备份真实项目、历史需保留配置级绕行低无影响低巨库需保留、无法改写我的建议是先做方案 A 验证根因如果确认巨库无用直接清理如果巨库有用视情况在 B 和 C 之间选。一般个人场景A 就够用了。5.5 我的实际操作和效果复盘我当时选择的是方案 A因为用户目录下那个 .git 确实毫无价值。操作过程就是mv ~/.git ~/.git.bak然后在项目目录里重新跑了一遍git rev-parse --show-toplevel确认这次指向的是项目本身。重启 Codex 之后我又观察了一阵子进程树git 子进程依然会出现但都是零星几条执行完就退出CPU 占用恢复到正常水平。启动时间大幅缩短任务执行也不再卡顿。这个案例给我的经验是遇到工具性能问题不要只盯着工具本身要往前多走一步看看它依赖的底层设施是不是健康。Codex 依赖 gitgit 的健康状况就直接决定了 Codex 的表现。6. 修好以后防止巨型仓库再次偷袭你的工具链6.1 养成分仓库意识别在整盘或用户目录里 git init这次事件最核心的教训就一条git 仓库必须严格限定在项目目录内。我见过不少朋友为了给代码做个备份直接在用户目录、甚至整块硬盘上执行git init。这种操作短期看似乎没毛病反正平时也不怎么看得到 .git 文件夹。但它埋的雷是长期的一旦有工具需要自动识别仓库根就会把整个目录吞进去CPU、内存、磁盘全被拖垮。正确做法是一个项目对应一个 git 仓库仓库根目录只在项目的最上层。如果你想备份的是整个用户目录别用 git专业的备份工具多得是。6.2 定期体检 .git 体积的命令清单现在我每隔一段时间就会检查一下手头仓库的健康状态用的命令就这几条# 看 .git 占了多少空间 du -sh .git # 看对象数量和打包情况 git count-objects -vH # 列出仓库里体积最大的对象按大小排序 git rev-list --objects --all | git cat-file --batch-check%(objecttype) %(objectname) %(objectsize) %(rest) | sort -nr -k3 | head -20 # 找出某个目录下所有 .git 及体积 find /path/to/projects -maxdepth 3 -name .git -type d 2/dev/null | xargs du -sh一旦发现松散对象数量过多或者 .git 体积长得奇怪就及时处理。优先跑git gc其次检查是不是有大文件混进历史。6.3 Codex 这类工具的使用习惯干净的工作区加明确边界使用 Codex 这类 AI 编程工具我总结了两条铁律第一条给工具一个干净的工作区。启动前把无关的缓存目录、临时文件清理掉保持项目目录里只有代码和必要配置。第二条给工具一个明确的边界。在哪里启动它就会把哪里当成工作范围。你希望它处理的是当前项目就一定不要在项目上层目录启动。另外如果你的项目里确实有体积巨大的依赖目录比如 node_modules确保.gitignore里已经写上了不要寄希望于工具自动识别。6.4 同类元凶node_modules、.venv、build以及怎么用 .gitignore 挡住除了 .git 异常膨胀AI 编程工具启动卡顿还有一个常见元凶项目目录里躺着海量的非代码文件典型代表就是node_modules、.venv、build、dist这类依赖和构建产物目录。这些目录里可能塞下了几万个甚至几十万个文件工具扫描工作区时如果硬着头皮全读一遍CPU 一样会飙升。解决办法很朴素把这些目录写进.gitignore并且确保工具的工作区扫描逻辑参考了 ignore 规则node_modules/ .venv/ venv/ build/ dist/ .DS_Store .idea/ .vscode/这是一个很小但很关键的习惯。很多 AI 编码工具卡顿问题排查到最后你会发现模型推理没问题、网络没问题就是工作区里垃圾文件太多了。6.5 一个小技巧收尾最后分享一个我自己的排查习惯凡是遇到工具启动极慢、CPU 异常飙升这种问题我第一件事就是查三样东西——.git有没有异常膨胀、node_modules之类的依赖目录有没有被工具误扫、缓存目录有没有积压大量小文件。大多数情况下这三样里就能找到答案。遇到 Codex 启动卡的问题别再自己瞎猜了。顺着进程树往上查看它到底在调用什么底层命令然后一层层定位最终多半会落到某个看起来不起眼、实际已经膨胀到失控的目录上。知道病理对症下药就快了。