CLAUDE.md 报 @include 循环引用?TaoToken 这样配 Claude Code 的 settings.json 多份CLAUDE.md之间用a.md、b.md互相引用Claude Code 加载记忆文件时就会抛Error loading memory files: circular reference detected或者干脆启动卡死、没有任何提示。这篇文章按排障顺序走先用 TaoToken官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 把 Claude Code 的模型通道配通——注册、创建 Key、把 Base URL 填成https://taotoken.net/api写进settings.json——再用这条通道让 Claude Code 去读项目里的几份CLAUDE.md、列出引用边、判断是否存在有向环最后对着排查清单逐条确认闭环是否已经被拆成单向结构。需要先说清楚边界TaoToken 在这里只负责给 Claude Code 提供 Key 和 Base URL它不参与CLAUDE.md的引用展开逻辑也不做循环检测更不替代grep和手画的引用关系图。很多人把两类问题混在一起排查才会觉得改了引用关系还是卡。一、报错现场卡死和 circular reference 往往是同一条根因先还原现象。项目里存在多份CLAUDE.md通过其他文件.md的形式互相补充内容。某次调整引用关系之后Claude Code 启动明显变慢严重时完全无响应把每个文件单独打开看语法都写得没错路径也没有明显笔误。这类现象的背后是一次递归展开Claude Code 读到行之后需要把被引用文件的内容取出来再递归处理被引用文件里的行最终拼接成完整的记忆内容。如果引用关系形成了环路——a.md引用b.mdb.md引用c.mdc.md又指回a.md——展开逻辑要么陷入无限递归要么需要处理的展开结果呈指数级膨胀。表现出来就是两种一种是版本内置了检测主动报出循环引用另一种是没触发明确检测资源消耗持续增长界面看起来只是卡住。这里有个容易被忽略的前提原文给出的排查手段用grep列出所有引用、改成单向层级、注释掉行做排除法都默认 Claude Code 本身是能启动、能响应、能返回内容的。如果settings.json里的模型通道没配通你面对的可能根本不是循环引用而是请求发不出去导致的启动异常两者的外部表现高度相似都卡、都慢、都没有有效日志。所以排障的第一步不是冲进CLAUDE.md里改引用而是先把通道和报错区分开。一个粗糙但有效的区分方式把项目里的CLAUDE.md暂时重命名或移出目录重新启动 Claude Code。如果依然卡死或反复重试问题在通道侧去看settings.json的ANTHROPIC_*配置如果启动恢复正常问题就在记忆文件的引用链上回到第一节描述的递归展开逻辑继续排查。二、TaoToken 前置Key 和 Base URL 只解决通道这一件事把通道补上只需要三件事注册账号、创建 Key、确认 Base URL 的写法。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成注册后进入 API Keys 页面创建一把 Key对应地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys 创建后先复制留存后面写进settings.json的就是这一串本文统一用YOUR_API_KEY代指。Base URL 固定写成https://taotoken.net/api三个注意点结尾不要补/v1不要拼任何查询参数也不要带 UTM 后缀。请求路径里的/v1/messages是接口自身的部分和 Base URL 是两码事两处叠加就会变成/api/v1/v1/messages。完整的接入写法在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc 里有说明配置前对照一遍比事后猜错要省事。要强调的是职责范围。TaoToken 提供的是模型调用的入口凭据和地址它不会读取你的CLAUDE.md不会做引用展开也不会告诉你哪两个文件构成了环。判断环路这件事仍然要靠grep列边、靠关系图或者一段判环脚本。把这条边界记住排查时就不会在错误的层面反复试错。三、可复制配置写进 Claude Code 的 settings.jsonClaude Code 的配置可以直接落在用户级~/.claude/settings.json也可以在项目里建.claude/settings.json做项目级覆盖。用户级适用于本机所有项目项目级适合团队各自拉取后开箱可用。把下面这段填进去{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: MODEL_ID } }几个细节决定了这段配置能不能一次跑通。ANTHROPIC_BASE_URL的值必须是裸地址不要写成https://taotoken.net/api/也不要写成https://taotoken.net/api/v1。ANTHROPIC_AUTH_TOKEN的位置放创建出来的 Key注意它是字符串要带引号。ANTHROPIC_MODEL填实际要用的模型标识这个值在模型对话页面确认不要凭记忆写。部分版本对键名更敏感同时存在ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN两种写法选当前版本认可的那一个不要两个键填不同的值否则行为会变得难以预测。还有一个高频坑shell 里如果之前export过ANTHROPIC_BASE_URL或ANTHROPIC_AUTH_TOKEN它会盖掉settings.json里的同名项。排查时先执行env | grep ANTHROPIC看一下当前 shell 的取值确认没有残留的旧地址。改完配置文件后要重新开一个 Claude Code 会话正在跑的进程不会自动重载。四、验证请求先打通一次调用再让 Claude Code 画引用链配置写完不要直接去啃CLAUDE.md先做一次最小验证确认通道本身是可用的。curl -sS https://taotoken.net/api/v1/messages \ -H x-api-key: YOUR_API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: MODEL_ID, max_tokens: 64, messages: [ { role: user, content: 只回复 ok } ] }成功的返回是一个 JSON 对象包含content数组和其中的文本字段stop_reason是一个正常结束值HTTP 状态码是 200。如果看到 401、403问题在 Key看到 404 或者路径相关的错误回头检查 Base URL 是否被写成了带/v1或带参数的形式如果长时间无响应先确认网络出口是否允许访问该地址再确认本地有没有代理把它拦下来。通道确认之后进入真正的排查环节。在 Claude Code 里发一条明确的分析指令让它在不修改任何文件的前提下做只读梳理扫描仓库内所有名为 CLAUDE.md 的文件找出每一行以 开头且指向 .md 文件的引用 输出 引用方文件 - 被引用文件 的边列表不要修改任何文件 然后基于这些边判断是否存在有向环如果存在把闭环节点按顺序列出来。拿到边列表之后自己再核对一遍。命令行上可以直接用grep做交叉验证grep -rn --includeCLAUDE.md -E ^\s* .这一步的作用是把引用方和被引用方两列对齐。注意把子目录一起扫进来只在仓库根目录看一份CLAUDE.md很容易漏掉藏在packages/或services/下的引用源。要判断有没有环手工画图在小项目上够用文件一多就建议上一个判环脚本思路是把刚才的边表读进来做一次深度优先遍历import re import pathlib import collections root pathlib.Path(.) graph collections.defaultdict(set) pattern re.compile(r^\s*([^\s]\.md)\s*$) for f in root.rglob(CLAUDE.md): rel str(f.relative_to(root)) for line in f.read_text(encodingutf-8).splitlines(): m pattern.match(line) if m: graph[rel].add(m.group(1).strip()) WHITE, GRAY, BLACK 0, 1, 2 color collections.defaultdict(int) stack [] def dfs(node): color[node] GRAY stack.append(node) for nxt in graph.get(node, ()): if color[nxt] GRAY: i stack.index(nxt) print(闭环:, - .join(stack[i:] [nxt])) return True if color[nxt] WHITE and dfs(nxt): return True stack.pop() color[node] BLACK return False for node in list(graph): if color[node] WHITE and dfs(node): break脚本只做只读分析不会改动CLAUDE.md。输出里出现闭环链条就说明第一节描述的递归展开问题确实存在。如果脚本报不出环但启动依然缓慢那属于下一节的第二类问题——引用链过深不是真闭环。五、本篇常见错排查通道侧和记忆文件侧分开看先把通道侧的错列出来它们制造的现象和循环引用很像混在一起排查最容易走弯路。第一Base URL 写成https://taotoken.net/api/v1。这是最高频的一种现象是请求路径重复、返回 404 或路径错误。处理方式是把值改回裸地址https://taotoken.net/api。第二Base URL 粘贴时把 UTM 参数一起带了进去。地址栏里复制出来的链接通常带着一长串查询串写进settings.json会让请求地址变形。UTM 只用于页面访问不进配置文件。第三Key 位置还留着YOUR_API_KEY占位符没换或者多复制了一个空格和换行。表现为稳定的 401。第四shell 里残留的ANTHROPIC_*环境变量覆盖了配置文件。用env | grep ANTHROPIC确认必要时在启动前清理。第五用户级和项目级settings.json同时存在同名键取值以谁为准取决于加载顺序容易造成改了没生效的错觉。排障期间先只保留一份。第六改完不重启会话。配置文件在被读取时生效运行中的进程不会热加载。再看记忆文件侧的错。第一只扫了一份CLAUDE.md就下结论说没有循环。这个项目里可能有三四份分布在子目录中引用关系是跨目录形成的。用-r递归扫并且把路径基准统一成仓库根目录否则同名文件容易混。第二行写在代码块里被当作真实引用展开。文档里为了举例写了一段common.md的说明加载时可能真的去展开它。展示用的引用示例建议用行内代码包裹或者加明显的转义标记。第三引用链过深但没有环。a引用bb引用cc引用d一路往下一层套一层加载时间会随深度明显上升虽然不是死循环体验上和卡住差别不大。处理思路是压缩层级把高频共用的核心约定直接合并进一份基础文件而不是拆成多层碎片。第四注释掉行做排除法之后忘了恢复。这是原文方案四的典型后遗症为了定位是哪一对文件构成了闭环临时注释几行观察加载是否恢复定位到之后必须把这批临时改动清理干净否则会留下引用关系看起来对、实际少了内容的隐性缺失。第五循环被打破的方式不对。发现a.md和b.md互引之后正确的改法是确定层级方向具体规则文件引用通用规则文件通用规则文件不反向引用具体规则文件。把a.md里的b.md删掉、同时又在b.md里加了a.md等于把环换了个方向继续存在。第六路径写法不统一。./common.md、common.md、docs/common.md混用会让grep的结果和实际展开的路径对不上关系图也就画不准。团队里最好统一成相对于仓库根目录的路径写法。把这两类错分开之后排查路径就清晰了先确认curl能拿到正常返回再确认settings.json里的ANTHROPIC_BASE_URL和 Key 生效且没有环境变量干扰最后才进入CLAUDE.md的引用图分析。顺序反了就会在引用关系上反复纠结而真正的问题一直在通道配置里。六、把这条排查链路固定下来如果只想快速复现这份流程按这个顺序走一遍在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys 创建 Key把 Base URL 写成https://taotoken.net/api落进~/.claude/settings.json或项目级.claude/settings.json具体键名和写法对照 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc 核对一遍模型标识在模型对话页面确认https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content模型对话 不在配置里猜测用curl打一次/v1/messages确认通道可用再让 Claude Code 扫描全部CLAUDE.md输出引用边配合判环脚本确认闭环是否已经拆成单向层级。排查清单可以按这个最小集合执行递归列出所有CLAUDE.md中的引用把引用关系整理成文件到文件的边表并检查是否有环发现环路后按具体引用通用的方向重建层级只做单向控制嵌套深度避免无谓碎片化引用关系复杂时用注释法缩小范围定位闭环点定位后立刻恢复把引用关系必须是无环有向图写进团队规范在评审新增行时顺手确认。如果 Claude Code 是团队日常编码和 Agent 任务的主要入口长期高频调用场景可以看 Coding Planhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan 先把通道稳定下来再让这套记忆文件规范长期跑在单向无环的结构上循环引用这类隐蔽问题就不会反复出现。