
1. 从 Spinner 转圈说起Claude Code 卡顿到底卡在哪一层用 Claude Code 的人大概率都遇到过这个画面终端里那个小小的 Spinner 一直在转转了几秒、十几秒甚至干脆停在那儿不动了。你盯着屏幕不确定它是在思考、在等网络、还是已经死掉了。这个体验非常折磨人因为 Claude Code 本质上是一个对话式编程代理它的工作模式是读代码 → 推理 → 调工具 → 再推理中间任何一个环节卡住前端表现都是同一个 Spinner 在转。所以排查卡顿的第一步不是急着去改配置而是先搞清楚 Spinner 这个状态标识到底在表达什么。Spinner 本身只是一个 UI 层的进行中指示器它不区分正在请求模型正在执行本地命令正在等待工具返回这些不同阶段。这就导致一个很现实的问题同样是转圈背后的原因可能天差地别而你如果只盯着它卡了这个表象排查方向会完全跑偏。我自己的经验是把 Claude Code 的运行链路拆成四层来看卡顿基本跑不出这四层输入层你的终端、Shell 环境、粘贴的大段代码、超长上下文。模型层请求发出去之后模型侧的排队、限流、响应生成。工具层Claude Code 调用本地命令读文件、跑测试、执行 git 等时的执行与等待。渲染层终端 UI 刷新、Spinner 动画、输出流式打印。这四层里真正卡死的概率其实不高绝大多数情况是某一层变慢了而 Spinner 没有把这个慢和死区分开。理解了这一点后面的排查才有章法。这篇文章就是把这四层逐一拆开告诉你每一层卡顿的典型症状、根因和对应的处理办法尽量做到你照着做就能定位问题。2. Spinner 状态标识的语义边界它告诉你什么又瞒了你什么2.1 Spinner 只代表进程还活着不代表任务在推进很多人对 Spinner 有个误解觉得它转就说明正在干活。严格来说Spinner 只能证明一件事主进程的事件循环还在跑。它转说明 UI 线程没被完全阻塞它不转说明连 UI 刷新都停了。但事件循环在跑和任务在推进是两码事。举个典型场景Claude Code 发起了一次模型请求然后进入等待。这个等待期间Spinner 会一直转因为事件循环在等 IO。但如果模型侧因为限流或者排队迟迟不返回Spinner 就会一直转下去看起来很努力实际上什么都没发生。这就是为什么你会觉得它转了半天也没输出。所以正确的读法是Spinner 转 进程没崩Spinner 转很久没输出 大概率卡在等待某个外部响应。把这两件事分开你的判断就准了。2.2 不同阶段的 Spinner 表现差异虽然 Spinner 本身不区分阶段但结合上下文你还是能看出一些端倪。我总结了几种常见表现和它们大概率对应的阶段Spinner 表现大概率所处阶段常见原因刚发消息就转很快出字模型层正常无转很久才出第一个字模型层排队/限流请求量大、账号限流出字中途突然停转工具层执行中本地命令卡住、等待输入转但完全无输出且时间极长网络层或模型层连接超时、响应丢失Spinner 动画本身卡顿、掉帧渲染层终端性能、输出量过大这张表不是绝对的但它能帮你快速缩小范围。比如出字中途突然停基本可以锁定是工具层——Claude Code 正在跑某个本地命令而那个命令卡住了比如等一个交互式输入或者跑了一个死循环的测试。2.3 为什么 Claude Code 特别容易让人误判卡顿Claude Code 和普通 CLI 工具不一样它是一个多轮工具调用的代理。一次用户输入背后可能是读 5 个文件 → 跑 1 次搜索 → 执行 1 条命令 → 再读 2 个文件 → 生成回答。这中间每一步都可能触发 Spinner而用户看到的只是一直在转。更麻烦的是工具调用是串行的大多数情况下前一个工具不返回后一个就不会开始。所以如果某个本地命令卡住整个链路就停在那儿Spinner 还在转但实际上是假活。这就是为什么排查 Claude Code 卡顿工具层往往是重灾区。3. 模型层卡顿请求发出去了但响应迟迟不来3.1 限流与排队最常见的转圈元凶模型层卡顿里排第一的永远是限流和排队。你发一个请求服务端可能因为当前负载高、你的账号触发了速率限制、或者单纯就是排队导致响应延迟。这种情况下 Spinner 会一直转直到超时或者最终返回。判断方法很简单看是不是所有请求都慢还是只有大请求慢。如果连你好这种一句话都要转很久那基本是账号或网络层面的限流如果只有长上下文、大文件分析的请求慢那可能是请求体太大导致的处理时间增加。应对上我一般这么做缩短单次上下文别一次性把整个仓库塞进去用精确引用文件。把大任务拆成小步骤让每一轮的工具调用和推理都轻量一些。如果怀疑是限流隔几分钟再试或者换个时间段。3.2 上下文膨胀请求体越大首字延迟越高Claude Code 的一个特点是它会自动把相关文件、历史对话、工具结果都塞进上下文。上下文越大模型处理首字的时间TTFT就越长。这不是 bug是物理规律——输入 token 越多prefill 阶段越慢。我实测过一个对比同样问一个函数的作用只引用单个文件时首字大概 1-2 秒如果把整个模块十几个文件都带上首字延迟能到 8-10 秒。这期间 Spinner 一直在转你会以为卡了其实是在 prefill。所以如果你发现越用越慢先检查上下文是不是膨胀了。Claude Code 一般有/clear之类的命令清理会话长会话该清就清别舍不得。3.3 网络链路被忽略的中间环节模型请求要经过网络网络抖动、DNS 解析慢、连接复用失效都会表现为转圈。这类问题的特征是偶发性有时候快有时候慢没有规律。排查网络层我习惯用最朴素的办法在另一个终端里持续 ping 或者用 curl 测一下到服务端的连通性和延迟。如果延迟忽高忽低那卡顿大概率是网络问题而不是 Claude Code 本身。这种情况你改配置没用得从网络环境入手。注意网络层排查时关注的是延迟稳定性和丢包而不是绝对速度。稳定的 200ms 比忽高忽低的 50ms 体验好得多。4. 工具层卡顿本地命令把整个链路拖死了4.1 交互式命令最隐蔽的假死工具层卡顿里最坑的是交互式命令。Claude Code 执行本地命令时如果那个命令需要用户输入比如git commit打开编辑器、某些脚本等待确认、npm init等待填写而 Claude Code 又没有正确处理 stdin命令就会一直挂着等输入。这时候 Spinner 在转但实际上是死等。我踩过这个坑让 Claude Code 帮我提交代码它跑了git commit没带-m结果打开了编辑器整个会话就卡在那儿了。解决办法是尽量让 Claude Code 执行非交互式命令比如git commit -m xxx、npm install --yes、带-y或--non-interactive参数的命令。如果你不确定某个命令会不会交互可以先在终端里手动跑一遍确认它是非交互的再让 Claude Code 去执行。4.2 长耗时命令测试、构建、安装第二类工具层卡顿是长耗时命令。跑全量测试、构建整个项目、安装依赖这些命令本身就要几分钟甚至更久。Claude Code 会等它跑完Spinner 一直转。这不算 bug但体验上就是卡。我的做法是让 Claude Code 跑针对性的命令比如只跑单个测试文件而不是全量测试。构建和安装这类重活自己在终端里跑跑完再让 Claude Code 看结果。如果必须让它跑长命令心里有个预期时间别误判成卡死。4.3 命令输出过大把终端刷爆还有一个容易被忽略的点命令输出过大。如果 Claude Code 执行了一个输出几万行的命令比如find /、cat一个大日志输出会疯狂刷屏终端渲染压力剧增Spinner 动画本身都会卡顿掉帧。这时候看起来是UI 卡了实际是渲染层被输出量压垮了。处理办法是给命令加过滤比如| head -100、| grep xxx只让 Claude Code 看到关键信息。既减轻渲染压力也减少上下文膨胀。4.4 工具层排查的实操清单把工具层的问题整理成一个可执行的排查清单确认命令是否交互式手动跑一遍看是否等待输入。确认命令耗时预估执行时间长命令单独跑。确认输出量加head/grep限制输出。确认工作目录命令是否在正确的目录执行避免在大目录里做全量扫描。确认权限某些命令需要权限卡在权限提示上也会假死。这五条基本能覆盖工具层 90% 的卡顿场景。5. 渲染层与终端环境Spinner 自己卡住了5.1 终端性能不是所有终端都扛得住流式输出Claude Code 是流式输出字是一个一个蹦出来的。这对终端渲染是个考验。一些老终端、配置了复杂主题的终端、或者开了大量插件的终端在流式输出时会出现明显的掉帧Spinner 动画一顿一顿的。我对比过几个终端同样的 Claude Code 会话在轻量终端里 Spinner 丝滑在重配置终端里就明显卡。如果你怀疑是渲染层问题可以换个干净的终端试试或者临时关掉终端的花哨主题和插件。5.2 系统资源CPU 和内存被吃满渲染卡顿的另一个原因是系统资源紧张。Claude Code 本身、它调用的工具、你的编辑器、浏览器全都在抢 CPU 和内存。如果内存吃紧开始 swap整个系统都会卡Spinner 自然也跟着卡。排查很简单卡的时候开个top或任务管理器看 CPU 和内存占用。如果某个进程吃满了资源先解决它。这类问题在配置较低的机器上尤其常见。5.3 终端复用与多会话别同时开太多有些人习惯开一堆终端窗口每个里面跑一个 Claude Code 会话。每个会话都在流式输出、都在调工具资源竞争会很激烈。我的建议是同一时间专注一个会话需要并行的时候再开用完就关。这能显著降低渲染层和系统层的压力。6. 一套可复现的卡顿排查链路6.1 第一步区分真卡和慢拿到卡顿现象先别动手改。观察 30 秒到 1 分钟如果 Spinner 在转且偶尔有输出那是慢不是卡。如果 Spinner 完全不转或者转但长时间零输出那可能是卡。这一步决定了你后面往哪个方向查。6.2 第二步按层定位用前面讲的四层模型逐层排除看是不是刚发消息就卡→ 模型层/网络层。看是不是出字中途卡→ 工具层。看是不是 Spinner 动画本身卡→ 渲染层/系统资源。看是不是特定操作才卡→ 大概率是那个操作触发的工具层问题。6.3 第三步针对性验证定位到某一层后做针对性验证模型层换个简单请求试试看是否同样慢。工具层手动跑那个命令看是否卡住。渲染层换终端、看资源占用。网络层测延迟和丢包。6.4 第四步修复与回归找到根因后修复然后重复触发那个场景确认不再卡。这一步很重要很多人修完就不管了结果换个场景又卡。回归验证能帮你确认修复是否彻底。7. 几个我踩过的坑和对应的经验7.1 别把上下文太长当成软件坏了我最开始用的时候一个会话聊了几十轮越到后面越慢我以为软件有问题。后来才明白是上下文膨胀。现在我的习惯是一个任务一个会话任务完成就清。这样既快又省。7.2 交互式命令是隐形杀手前面提过这里再强调一次。让 Claude Code 执行命令前先想一下这个命令会不会等输入。会等的要么加非交互参数要么自己手动跑。这个坑我踩过不止一次。7.3 终端配置越简单越稳花哨的终端主题、一堆插件平时看着爽流式输出时就露馅了。我现在用的终端配置非常朴素Spinner 从来没卡过。性能这东西简单就是快。7.4 长命令自己跑别全丢给 Claude Code构建、全量测试、装依赖这些我自己在终端跑跑完把结果贴给 Claude Code 分析。这样既避免了工具层卡顿也让 Claude Code 专注于它擅长的推理和分析。7.5 卡住时先别急着杀进程很多人一卡就 CtrlC 或者杀进程。但如果它只是在等一个慢响应杀了反而丢上下文。我的做法是先观察确认是真卡死再动手。判断标准就是前面说的——Spinner 转不转、有没有输出。8. 关于 Spinner 和卡顿最后再聊几句实在的Claude Code 的 Spinner 卡顿本质上是一个状态可见性问题。它用一个统一的转圈动画掩盖了背后四层完全不同的运行状态。你要做的不是去改 Spinner 本身而是学会透过它去判断真实状态。我现在的习惯是看到 Spinner 转先在心里过一遍它现在可能在干嘛——是在等模型、在跑命令、还是在渲染。这个判断一旦形成排查就变成了条件反射几秒钟就能定位方向。另外别追求永远不卡。任何依赖外部服务、依赖本地命令执行的工具都会有等待。关键是你能区分正常等待和异常卡死前者耐心等后者按链路排查。这个能力比记住任何一条具体命令都值钱。如果你也遇到过特别诡异的卡顿场景欢迎按这套四层模型去拆解大概率能找到根因。工具是死的排查思路是活的多拆几次你就成了那个一看 Spinner 就知道问题在哪的人。