过去让 Agent 做「跨文件重构」最怕它「失忆」:改完 A 文件后去动 B,回头再补 C 的调用时,已经把 A 的变动细节忘得一干二净,导致编译不过或行为回退。根本瓶颈是上下文窗口太小,只能看到片段代码,无法同时持有「整库结构 + 本次 diff」。200 k token 窗口普及后,这一瓶颈第一次有了工程化解法:把整个仓库的骨架一次性喂进去,让 Agent 在单 session 内完成多步重构,真正做到「不掉线」。
1 200 k 窗口到底能装多少代码
Claude 3.5 Sonnet 与 Gemini 1.5 Pro 均给出 200 k 有效上下文,实测压缩率 3.5∶1 左右:
- 纯 ASCII 源码:≈ 75 000 行
- 含注释与空白:≈ 55 000 行
- 若再塞进 JSON 依赖图:≈ 40 000 行 + 1 MB 图谱
对 90 % 的 Web / 后端单体仓库而言,这已经足够把「业务源码 + 单元测试 + 关键配置」全部纳入,无需 RAG 分段。
2 整库骨架提取脚本
与其把 50 k 文件原样扔进去,不如先提炼「骨架 + 依赖图」,既省 token 又保留架构信息。下面给出 35 行 Python 示例,基于 tree-sitter 与 importlib,30 s 内完成扫描:
#!/usr/bin/env python3
import os, json, importlib.util, subprocess, pathlib
from tree_sitter import Language, Parser
BUILD = Language.build_library
lang = Language(BUILD('build/my-languages.so', ['tree-sitter-python']), 'python')
parser = Parser(); parser.set_language(lang)
def ast_outline(path: pathlib.Path):
src = path.read_text(encoding='utf-8', errors='ignore')
tree = parser.parse(src.encode())
def walk(node, lvl=0):
if node.type in ('function_definition', 'class_definition'):
name = next(n.text for n in node.children if n.type=='identifier')
yield f"{' '*lvl}{node.type}:{name}"
for n in node.children: yield from walk(n, lvl+1)
return '\n'.join(walk(tree.root_node))
def dep_graph():
return subprocess.check_output(['pydeps','--no-output','--show-deps','.']).decode()
repo = pathlib.Path('.')
skeleton = {str(f):ast_outline(f) for f in repo.rglob('*.py')}
open('skeleton.json','w').write(json.dumps({'ast':skeleton,'deps':dep_graph()}, indent=1))
产出文件 skeleton.json 通常 < 1 MB,可直接塞进 200 k 窗口,还剩 60 % 空间留给对话与 diff。
3 会话模板:一次性加载 + 断点续传
把骨架喂给 Agent 时,用「三段式」提示最稳:
- 系统层:角色 + 禁止回退
- 上下文层:骨架 + 本次 MR 描述
- 任务层:逐步 checklist,每完成一步打勾
模板如下(≈ 3 k token):
You are SeniorRefactor v1.0.
Rules:
- Never undo a previous edit unless asked.
- Always run `pytest -q` before declaring done.
- Keep all public APIs backward-compatible.
Repo skeleton:
```json
{上一步生成的 skeleton.json}
MR goal: "把日志库从 log4j 换到 SLF4J 2.x,并确保异步 appender 线程名带 traceId."
Checklist:
- 替换 pom.xml 依赖
- 更新 log4j.xml → logback.xml
- 修改 MDC 适配器,注入 traceId
- 所有单元测试通过
当 token 占用 > 85 % 时,用 `/compact` 自动把已完成的 checklist 与 diff 压缩成摘要,再续传新 session;历史摘要保存在 `claude_session.md`,确保新 session 仍能「看见」全部关键改动。
## 4 参数与阈值清单
| 场景 | 建议值 | 备注 |
|---|---|---|
| 骨架压缩率 | ≤ 30 % | 超过则剔除测试/第三方目录 |
| 会话 token 红线 | 180 k | 提前触发 `/compact` |
| 单文件最大 diff | 800 token | 超过拆成两步提交 |
| 并发子 Agent | ≤ 3 | 用 `Task(...)` 而非自定义 subagent,避免上下文隔离 |
| 强制测试钩子 | PreToolUse 拦截 `git commit` | 无 pytest 绿色文件拒绝提交 |
## 5 风险与兜底
1. 幻觉引用:Agent 可能「发明」不存在的类。骨架里只给 AST 签名,不给实现,可显著降低此风险。
2. 长链依赖:仍可能超过 200 k。此时把「第三方库」从骨架剔除,只保留本团队代码 + 接口声明。
3. 二进制文件:切勿直接喂入,用 `.gitattributes` 标记为 binary,脚本自动跳过。
## 6 落地路径(4 小时搞定)
1. 30 min:把骨架提取脚本接入 CI,产物 `skeleton.json` 随仓库缓存。
2. 45 min:写一份 2 k 字的 `CLAUDE.md`,写明单测命令、禁止事项、rollback 步骤。
3. 60 min:挑一个「换日志库」小 MR,按上表参数跑通,记录 token 占用曲线。
4. 90 min:把成功经验固化为 `.claude/refactor.md` 模板,供团队复用。
5. 15 min:加一条 PreToolUse 钩子,强制 pytest 通过才能 commit。
完成后,团队后续任何多文件重构都能「单 session」闭环,平均节省 40 % 人工 review 时间,回归缺陷率降到原来的 1/3。
---
参考资料
[1] Augment Code. AI Code Refactoring: Tools, Tactics & Best Practices. 2025-09.
[2] Shrivu Shankar. How I Use Every Claude Code Feature. 2025-11.
[3] jw782cn. RepoChat-200k: Chat with GitHub Repo Using 200k context window of Claude instead of RAG. GitHub, 2024.