作为Claude Code的日常用户,最让人上火的画面就是命令发出去之后,终端里那个转圈图标一直转,转足十分钟,就是不吐一个字。我见过太多人在群里问“是不是死了”“要不要重开”,其实这事儿远没那么玄。Spinner状态标识、卡顿根源、排查方案,这三件事是连在一起的:只要能看懂转圈的状态在提示什么,再结合日志和上下文占用去定位,大部分卡顿都能在三五分钟内找到方向,而不是靠运气乱试。
这篇文章就把我自己的排查路子完整写出来。核心思路很简单:先看Spinner状态标识属于哪种“转”,再顺着工具调用、上下文膨胀、网络开销这几个常见根源去定位,最后给出一套可以直接照做的排查流程和优化配置。适合刚接触Claude Code没几天的新手,也适合已经在用但被“转圈卡住”折磨过几次的中度用户。
1. 动手之前,先看懂Spinner状态标识
很多人一看到转圈图标就慌,其实Spinner状态标识本身就能透露不少信息。Claude Code界面很简单,没有复杂的仪表盘,唯一的“运行状态灯”就是那个Spinner,以及旁边不断刷新的文本输出流。所以要排查卡顿,第一步不是查代码、不是改配置,而是学会读这个状态灯。
1.1 四种肉眼可辨的Spinner状态
我观察下来,Claude Code的Spinner状态大致可以分成四种。第一种是“快速空转”,就是转圈图标转得很快,但面板上没有多少新输出。这个状态通常出现在输入框等待、流式输出间歇、或者是短小的工具调用间隙,几秒到十几秒之内就会过去。如果你看到这个状态超过三十秒,那就不是正常间隙了,得往下查。
第二种是“匀速常转”,图标转得不算快,但在稳定输出文字、不断打印日志或工具调用信息。这种状态多半是模型正在一个较长的推理过程里,或者在做连续多次的工具调用。它确实在干活,只是慢,这种“慢”往往和上下文体积有关系。
第三种是“慢转卡顿”,转圈图标明显变慢甚至一顿一顿的,终端里半天蹦出一个字。这种状态常见于网络请求挂起、API长时间未返回、或者工具执行结果迟迟不回填。遇到这个状态,基本上可以锁定在网络层或命令执行层。
第四种最麻烦,叫“假死空转”,Spinner状态标识还在,转圈也在动,但终端完全没有任何输出,Ctrl+C要按好几下才有反应。这种通常是某个外部进程把命令行工具阻塞住了,比如插件等待确认、命令执行进入交互状态、或者是API请求连上了但数据流卡死。千万别在这种状态下傻等,直接查日志、中断重来更实在。
1.2 状态标识背后:一个完整的工作循环
要理解Spinner状态为什么会有这些差异,得先明白Claude Code运行时的完整循环。每次你输入一条指令,工具会做这么一件事:把当前会话的历史对话、已读文件的摘要、CLAUDE.md里的项目规则,全部打包成一个上下文窗口,发送给模型处理;模型返回的不是单纯的最终答案,而往往是一串结构化的“行为序列”,包含文本输出、工具调用请求(比如读文件、执行终端命令、改代码);CLI再把工具调用结果回填给模型,继续下一轮推理,直到模型给出终止标记、或者达到某个极限条件。
每一次“回话”,背后可能是好几轮“模型推理—工具执行—结果回填”的小循环。Spinner在转,说明至少有一个小循环正在跑。所以Spinner状态标识真正的价值是:它暗示着当前正处于哪一类循环里。快速空转,多半是流式响应间隙;匀速常转,一般在模型长推理或连续工具调用;慢转卡顿,常见于网络等待或工具挂起;假死空转,往往是阻塞性死锁。这个分类不是官方文档里的标准,而是我在实操中总结的经验,用它来当排查的第一层过滤器很管用。
1.3 从状态标识判断“该等还是该动手”
看见Spinner转起来,第一反应不应该是“完了”,而是“先看日志再决定”。我自己的判断标准是这样的:如果转圈的同时,日志文件里还有新的请求记录在增加,输出流里还有零星文字在蹦,那就说明链路是通的,只是慢,这时候耐心等一等,顺便去查上下文占用;如果Spinner转着但日志已经三分钟没新增记录了,那基本可以判断链路断了,这时候不要浪费生命在等待上,中断重开一次,或者先查网络。
这个判断姿势很重要,因为很多人一碰到卡顿就想重开会话,但如果你连卡在哪个环节都不知道,重开之后很可能再次踩进同一个坑。学会先用Spinner状态标识做初步分类,是后面所有排查方案的第一块基石。
2. 卡顿根源拆解:转圈到底在等什么
Spinner只是现象,真正的“卡顿根源”其实就藏在那几类循环里。我拆了这么多次,Claude Code的卡顿90%以上都逃不出下面四个大类:上下文膨胀、工具调用循环、网络层开销、以及模型推理本身。把这四个根源搞清楚,排查方案才有依据。
2.1 上下文膨胀:最大的隐形杀手
Claude Code的模型上下文是有限的,而且“读进上下文的文本量”和“每次推理的耗时”基本是正相关的。你让它读一个两千行的源码文件,表面上看它“读”完了,实际上那整个文件内容会被塞进上下文窗口里,后面的每一次工具调用,模型都要带着这一大坨历史来回处理。上下文体积从几千token涨到几万甚至十几万token之后,单次推理耗时会成倍上升,费用也跟着涨,但界面上唯一的变化就是Spinner转得更慢了。
我拿自己一个真实项目举例。当时让它重构一个旧模块,我图省事,直接让它读整个src目录,结果上下文瞬间被四五万token撑满。一开始还好,改到第三个文件时,每次让它改动一行代码,Spinner都要转一分多钟才响应。我用/status一看,上下文占用已经接近窗口上限。后来我把那个大仓库拆成多个独立任务,每次只让它读相关的几个文件,同样的改动几乎秒回。所以遇到“越用越慢”的卡顿,第一个怀疑对象就应该是上下文膨胀。
2.2 工具调用循环:反复尝试的“死循环”
Claude Code的一大卖点是能直接执行终端命令,但这同时也埋下一个坑:它会尝试自己排除命令行错误。比如你让它构建项目,它执行了一个npm命令,失败后返回了一个报错,它不会就此放弃,而是会基于报错再推理一次、再执行一次。如果报错信息很模糊,它可能就会陷入“执行—失败—再执行—再失败”的小循环里,表现就是Spinner一直转,日志里反复出现同一个命令调用。
这类情况我在用Claude Code做构建脚本、跑测试和做批量文件重命名时遇到过很多次。它在那边转圈并不代表“挂了”,而是真的在反复尝试,只是尝试方向可能不对。这时候最好的办法就是中断它,自己看一眼报错,在指令里把更明确的约束写进去,或者直接把容易出问题的命令改成手动执行完再让它接手后续。
2.3 网络层与API配置的隐性开销
模型推理最终是发生在远端服务器上的,CLI和API之间的网络请求质量直接决定了Spinner的节奏。如果你用的是默认的官方接口,正常网络情况下,每个请求的响应时间在几秒到一分钟之间都有可能;如果你用了第三方兼容API、自己搭了网关、或者机器上挂着各类代理环境变量,那请求链路又长了一层,任何一个环节抖动,都会表现为Spinner状态长时间的慢转或假死。
这边有一个我自己踩过的坑:用第三方API接入DeepSeek、Qwen这些模型时,如果API配置里没设好超时时间或请求并发限制,平台一旦限流,CLI就会一直挂在等待响应的状态里,终端既不报错也不输出。后来我养成了一个习惯,排查卡顿的时候第一件事就是用/status看当前连接的是哪个API端点,确认网络环境里没有多余代理干扰,再继续往下查。
2.4 模型推理本身:不是所有卡顿都是问题
最后要说的这个根源最容易被误判。复杂任务里,模型规划时间长一点、思考的链条长一点,从几秒钟到一两分钟都是非常正常的。你要它跨十几个文件做一个架构级重构,还带着一堆约束条件,它内部要先想明白整个方案,这个阶段Spinner状态标识就是匀速常转。我最早接触Claude Code时就犯过这个错,看它转圈转了一分钟,以为是卡死了直接Ctrl+C,结果重新执行之后它又花了同样的时间思考,来回折腾了三次才反应过来——人家是在认真思考,不是卡住。
怎么区分“认真思考”和“真卡死”?我的办法是看日志和输出流:如果日志里能频繁看到模型生成内容或工具调用的记录,它就还活着;如果日志完全静止,那才是真有问题。另外,同一个任务如果重开几回每次都花类似的时间思考和输出,那基本可以判定是模型推理的正常耗时,不是故障。
3. 排查方案:五步定位,从“玄学”到“科学”
前面把Spinner状态标识和卡顿根源讲清楚了,这节直接进入实操。我把自己的排查流程固定成了五步,每一步都有明确的动作和判断标准。按这个顺序走,一般不需要乱试就能锁住问题点。
3.1 第一步:观察现象,分清“慢”和“死”
观察现象不是傻等,而是带着问题去看。具体来说有这么几个观察点:Spinner状态标识转得快还是慢?终端有没有新输出?日志文件是否有新增记录?距离上一次输出已经过去多久?这三个问题问完,基本能得出第一步结论:如果还在持续输出,属于“慢”,往上下文膨胀和模型推理方向排查;如果完全静止,属于“死”,往网络挂起和工具阻塞方向排查。
这一步最大的价值是避免“无差别重开”。我自己最开始的排查习惯很差,一卡就Ctrl+C、重开、从零再来,结果每次都在同一个位置卡住。后来我学会先观察三分钟,确认是真死锁之后再干预,很多虚假的卡顿其实自己就恢复了。
3.2 第二步:打开日志,让Claude Code开口说话
Claude Code的日志是排查卡顿最直接的证据。操作上很简单:在以日志模式启动Claude Code之前,先设置一下环境变量,常见的方式是export CLAUDE_CODE_LOGGING=1,然后带日志模式运行,日志文件一般会写到~/.claude/logs目录下。如果你不想重新启动,也可以在运行的会话里直接开日志开关。
日志打开后再复现一次卡顿,然后去看最后几百行记录。你会看到每一次API请求是什么时候发出的、响应是什么时候收到的、工具调用是什么时候启动的、执行结果是什么时候返回的。如果你发现某次API请求发出之后,日志里再也没有后续记录,那问题就出在“请求发出后没收到响应”这个环节,直接去查网络和API配置。如果你发现日志里同一个命令反复出现,那问题就出在工具调用循环,和网络没关系。日志就是定位卡顿根源的裁判,没有它你只能瞎猜。
3.3 第三步:用/status和/context查看上下文账本
日志告诉你“卡在哪个环节”,/status和/context则帮你回答“为什么这个环节会卡”。在Claude Code会话里输入 /status,能看到当前会话用的模型标识、上下文占用百分比、API端点类型这些关键信息。再输入 /context 或相关命令,能列出当前上下文里占空间大户,大概率就是那几个被读进去的大文件,或者是积累了很久的历史对话。
这一步的排查逻辑很清晰:如果上下文占用已经在80%以上,那卡顿根源大概率是上下文膨胀,直接按第4章的“会话瘦身”方案处理;如果占用很低,说明问题不在上下文,继续往下走。每次做耗时较长的任务之前,我也会先看一眼 /status记录一个基线,等到卡顿的时候再对比一次,上下文涨了多少一目了然。
3.4 第四步:检查网络与API接入点
走到这一步,基本上锁定的是链路问题。先用 /status 确认当前会话连的是哪个API端点,再看系统环境变量或配置文件里有没有设置 ANTHROPIC_BASE_URL、ANTHROPIC_MODEL、ANTHROPIC_API_KEY 这些项。很多人用第三方API时改过这些配置,但改完可能根本没意识到旧配置还在生效,结果请求一直打到错误端点,Spinner自然一直转圈。
实操建议是,在排查期内尽量保持接入点干净:没特殊情况就走直连的官方API,或者单一明确的第三方接入点,不要在机器上同时留着多层转发配置。我见过一个案例,某台机器上同时配置了多个环境变量和代理链,结果Claude Code发出的API请求绕过了预期端点,走了个奇怪的链路,既不报错也不返回,最后把所有环境变量清掉、只保留一份API配置之后才恢复正常。
3.5 第五步:剔除工具循环与错误重试
最后一步专门对付工具调用循环。打开日志后,如果看到同一类命令被反复执行,而且每次都以失败收场,那就别再让它自己折腾了。直接中断,人工看一眼报错原因,然后在新的指令里给你自己人工修正后的做法。
我的习惯是把三件事同时做掉:在命令行里把出问题的命令手动执行一遍,确认能跑通;在指令里明确告诉Claude Code“不要再重试某类操作”;用系统参数限制单次会话可执行的最大操作数量。这一套下来,工具循环基本能被摁住。
4. 快速优化配置与第三方接口接入
排查完,下一步就是给环境做“提速优化”。这一节重点讲四件事:会话瘦身、控制工具调用、用cc switch接第三方模型、以及登录账号和纯API Key的区别。每一件都是我实测过有效的事。
4.1 会话瘦身:比想象中更有效的/compact和会话隔离
如果 /status 显示上下文占用很高,最直接的解法是见什么拆什么。我会优先用 /compact 命令压缩当前会话的上下文,它会用一段摘要替代之前的冗长对话,实测下来上下文占用能掉一大截,后续响应速度立竿见影。如果任务还能重来,我往往会用 /clear 直接清空当前会话,开一个全新的干净会话接着干,效果更彻底。
除了压缩,会话隔离也非常关键。Claude Code每个会话的上下文是各自独立的,如果你把“修A模块”和“改B模块”放进同一个会话里,改到后面整个上下文里塞满了A模块的代码,处理B模块时就全是干扰。我现在的习惯是同一个仓库、同一个任务目标就开一个新会话,绝不混用。最关键的一点是,不要随意让它读整个仓库目录,而是精确到一个文件或一个函数,上下文体积能控制得非常小。
4.2 控制工具调用:超时、输出上限与授权范围
Claude Code会自动执行一部分终端命令,但这不是没有限制的。为了不让它无限重试或一次干太多事,我建议手动做三个限制。第一个是设置输出token上限,通过环境变量(比如 CLAUDE_CODE_MAX_OUTPUT_TOKENS)限制单次输出的量,避免模型在长输出上耗时过久。第二个是给命令执行设一个超时心理线,如果一个命令执行超过几分钟还没完,就直接中断;虽然CLI没有特别直观的“全局超时”选项,但你可以在指令里写明“如果执行超过XX秒就停止”。第三个是缩小授权范围,在项目根目录的CLAUDE.md里明确告诉它哪些命令可以直接执行、哪些必须提前确认,能有效规避“它自己乱跑命令然后卡在奇怪环节”的场面。
安全方面还是得多说一句:让Claude Code执行终端命令时,默认保持先确认再执行的模式会更稳妥,特别是rm、git push、重命名这类有副作用的操作,出了事也不好撤销。
4.3 用cc switch接入DeepSeek、Qwen、GLM等第三方模型
“用Claude Code接入第三方模型”这件事,本质上不是修改Claude Code本身,而是换掉它背后的API接入点。Claude Code通过环境变量 ANTHROPIC_BASE_URL、ANTHROPIC_MODEL、ANTHROPIC_API_KEY 来决定“请求发到哪里、调用哪个模型”,第三方模型只要提供兼容的API端点,就能接进来。
在模型间切换最顺手的工具是 cc switch,这个工具专门用来管理Claude Code的多供应商配置。使用逻辑不复杂:安装之后先进行初始化,它会列出支持的供应商(DeepSeek、Qwen、GLM等),你选择目标供应商,填上对应的API Key,它自动帮你切换好 base url 和模型名。之后正常启动Claude Code,让/status看一眼确认当前连的供应商正确,就可以正常对话了。
实际用下来,DeepSeek V3/R1系列、Qwen系列、GLM系列都能在Claude Code里跑基本的对话、读文件和改代码。但要注意两点:第三方模型和官方模型在“工具调用格式遵循度”上会有差异,有些模型适合复杂工具链,有些不适合,得实际试;第三方API的响应速度、并发限制也各不相同,遇到Spinner状态慢转时优先怀疑供应商限流。
4.4 登录账号与仅用API Key的差异
关于登录和不登录的区别,我经常被人问到。不登录Claude Code账号,直接用API Key方式运行,是完全可以的,尤其当你接第三方模型时,走的就是这套模式。这种情况更像“裸用命令行工具”:基本对话、读写文件、执行命令都没问题,但一些依赖云端账号体系的功能(比如跨设备会话同步、用量仪表盘、官方订阅流量包等)用不上。
登录官方账号则走的是订阅体系,按套餐包含流量使用,AI能力上限和上下文设计也以官方模型为准。如果你有官方订阅,日常主力用官方模型、需要省钱或实验时用cc switch切第三方,是最舒服的组合。我自己就是这么配的:默认接官方模型写复杂架构,批量修小问题或跑实验时切到第三方模型,两边互补。
5. 高频问题与避坑实录
最后一部分,把我在实操中遇到的典型问题整理成一张速查表,再分享几条长期摸索出来的习惯。希望帮你少走一些弯路。
5.1 常见的卡顿问题速查表
| 现象 | 高概率根源 | 建议处理方式 |
|---|---|---|
| Spinner快速空转超过30秒 | 网络请求挂起或API未返回 | 看日志确认请求是否发出,检查API端点和网络配置,必要时中断重试 |
| 匀速常转但输出很慢 | 上下文膨胀或模型长推理 | 用/status查占用,用/compact压缩上下文,或拆分会话 |
| 日志里同一命令反复出现 | 工具调用循环 | 中断,人工执行命令看报错,并在指令里禁止盲目重试 |
| 任务中途完全无输出 | 工具执行卡死或假死空转 | Ctrl+C中断,重开后先开日志再复现 |
| 换第三方模型后频繁慢转 | 供应商限流或模型兼容性差 | 用cc switch换模型,或调整单次请求频率、改用轻量模型 |
| 越用越慢 | 上下文积累过多 | 用/clear开新会话,任务拆细再继续 |
这张表我反复用了好几个月,基本能覆盖九成以上的卡顿现象。每次遇到问题先对号入座,再动手,比漫无目的地重开会话高效太多。
5.2 实测下来最顺手的几个小习惯
第一个习惯:所有耗时任务都开日志模式跑。你可能觉得开日志会拖慢速度,实际上影响很小,但排查价值极大。卡住的时候直接看日志最后几行,三分钟定位问题,没有日志就只能瞎猜。
第二个习惯:大任务开工前,先看一眼 /status 的上下文占用和API端点,记个基线。任务跑到一半卡住时,再对比一次,立刻能判断是上下文膨胀还是接入点异常。整个过程不过几秒钟,但能省下半小时的排查时间。
第三个习惯:善用“新会话”而非“续旧会话”。很多人习惯在一个会话里把活全干完,但这种用法在Claude Code里非常吃亏。每个会话的上下文都是包袱,背着几十万token的包袱处理新任务,慢是必然的。我现在每切换一个子任务就开新会话,快得不是一点半点。
5.3 千万别踩的“重开主义”陷阱
最后想专门说一个心态问题:不要逢卡必重开。重开看似干脆,但你会丢掉当前会话里所有的中间状态和上下文,重新来过之后还是可能卡在同一个地方,而且更气人的是,你根本不知道为什么会卡。正确心态应该是:先用Spinner状态标识分类,再配合日志定位,最后针对根源处理。把“重开”当成所有方案都失败后的兜底措施,而不是默认操作。
我自己就做过一次特别蠢的事。一个大型重构任务进行到快收尾时,模型开始思考一个复杂约束,Spinner匀速转了好一会儿,我当时手贱按下Ctrl+C重开了,结果第二次跑又是同样的节奏,第三次我才反应过来这不是卡顿,是模型确实在规划。后来我学会了一件事:看到Spinner状态标识在转,先喝茶看日志,确认它真的死了再动手。慢一点点没关系,瞎折腾才最浪费时间。
如果你现在正被某个转圈图标折磨到心烦,不妨照着这条流程走一遍:观察状态、开日志、查上下文、查接入点、切除工具循环。大部分卡顿都能在这三步之内现出原形。剩下的那些疑难杂症,只要你手上有日志,去社区提问时也能给出别人看得懂的上下文,问题解决起来快得多。