Context-Mode 深度拆解:AI 编程代理的上下文救星——98% 压缩比背后的技术革命
当 Playwright 快照吃掉 56 KB、GitHub Issues 吞掉 59 KB、一条访问日志就占满 45 KB,你的 AI Agent 还能剩下多少"脑容量"?Context-Mode 用 SQLite + FTS5 + 代码沙箱给出了一个令人震惊的答案:315 KB → 5.4 KB,98% 的上下文节省。
一、问题的本质:上下文窗口的四重危机
如果你用过 Claude Code、Cursor 或任何 AI 编程代理,一定遇到过这样的场景:
- 开了一个复杂项目,Agent 读了几十个文件后开始"胡言乱语"
- 修复 Bug 时 Agent 忘记了之前的修改,反复踩同一个坑
- 会话压缩后,Agent 完全"失忆",需要重新描述整个上下文
- 明明只问了简单问题,Agent 却输出了大量客套话和填充词
这不是模型不够聪明,而是上下文窗口的四重危机:
1.1 工具输出的数据洪流
现代 AI 编程代理通过 MCP(Model Context Protocol)连接各种工具,但每次工具调用都会往上下文窗口倾倒原始数据:
| 工具 | 输出大小 | 说明 |
|---|---|---|
| Playwright 快照 | 56 KB | 页面结构+交互树 |
| GitHub Issues(20条) | 59 KB | 标题+正文+标签 |
| Nginx 访问日志(500条) | 45 KB | 时间戳+路径+状态码 |
| React 文档(Context7) | 6 KB | API 文档+代码示例 |
| Git Log(150 commits) | 12 KB | 提交历史+消息 |
30 分钟后,40% 的上下文就没了。
这还不是最糟的——当上下文即将耗尽,Agent 会"压缩"对话,把历史信息丢弃。问题是:它丢掉的往往是最关键的信息——正在编辑的文件、进行中的任务、你刚交代的约束条件。
1.2 会话压缩后的"失忆症"
假设你正在让 Agent 重构一个模块:
你: 把 UserService 的认证逻辑抽成独立类
Agent: 好的,我创建了 AuthService,修改了 UserService...
你: 继续把数据库操作也抽出来
Agent: 我创建了 UserRepository... [上下文压缩]
你: 再把缓存逻辑也抽出来
Agent: 好的... 你说的是哪个 UserService?我没看到这个文件
这就是会话压缩后的"失忆症"——Agent 记得压缩点之后的内容,但压缩点之前的关键信息全丢了。
1.3 输出 Token 的隐形浪费
更隐蔽的是输出侧的浪费。很多 Agent 有这样的"礼貌病":
好的,我来帮你分析一下这个问题。首先,我需要了解一下当前的代码结构。
让我先看看 UserService 的实现... 嗯,这个类确实有点复杂。
我注意到它同时处理了认证、数据库操作和缓存逻辑,这违反了单一职责原则。
所以我建议我们...
明明一句话能说清的事,输出了一大堆填充词。这些 token 同样消耗上下文窗口。
1.4 核心矛盾:LLM 不是数据处理器
最根本的问题是:我们把 LLM 当成了数据处理器,而非代码生成器。
需要统计 50 个 TypeScript 文件的行数,传统做法是:
Agent: Read file1.ts (3 KB) → 上下文+3 KB
Agent: Read file2.ts (3 KB) → 上下文+3 KB
...
Agent: Read file50.ts (3 KB) → 上下文+150 KB
Agent: 计算总数... [上下文已满,开始压缩]
700 KB 的上下文消耗,只为了得到一个"总共 8421 行"的数字。
二、Context-Mode 的技术架构:四维度解决方案
Context-Mode 是一个 MCP Server,它从四个维度解决上述问题:
┌─────────────────────────────────────────────────────────────┐
│ Context-Mode 架构 │
├─────────────┬─────────────┬─────────────┬─────────────────────┤
│ Context │ Session │ Think in │ Output │
│ Saving │ Continuity │ Code │ Compression │
├─────────────┼─────────────┼─────────────┼─────────────────────┤
│ 沙箱工具 │ SQLite+FTS5 │ 代码执行 │ 智能压缩 │
│ 98% 压缩 │ BM25 检索 │ 100x 节省 │ 65-75% 减少 │
└─────────────┴─────────────┴─────────────┴─────────────────────┘
2.1 Context Saving:沙箱隔离原始数据
核心思想:工具输出的原始数据不进入上下文,只返回压缩后的摘要。
// 传统方式:直接读取 50 个 GitHub Issues
// 结果:59 KB 原始数据涌入上下文
// Context-Mode 方式:使用 ctx_execute_file
ctx_execute_file("github-issues.md", "summarize", {
limit: 500 // 最大输出 500 字节
})
// 结果:返回 "50 issues, 12 bugs, 8 features, 30 discussions"
// 上下文消耗:719 B
Benchmark 数据对比:
| 场景 | 原始大小 | 压缩后 | 节省率 |
|---|---|---|---|
| GitHub Issues(20条) | 58.9 KB | 1.1 KB | 98% |
| Playwright 快照 | 56.2 KB | 299 B | 99% |
| Nginx 访问日志(500条) | 45.1 KB | 155 B | 100% |
| Git Log(150 commits) | 11.6 KB | 107 B | 99% |
| 测试输出(30 suites) | 6.0 KB | 337 B | 95% |
2.2 Session Continuity:会话压缩后的记忆保持
这是 Context-Mode 最具创新性的设计:
┌─────────────────────────────────────────────────────────────┐
│ 会话生命周期 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户输入 → Agent 处理 → 工具调用 → 结果记录 │
│ ↓ │
│ SQLite 事件日志 │
│ ↓ │
│ FTS5 全文索引 │
│ ↓ │
│ [会话压缩] → BM25 检索 → 恢复关键上下文 │
│ │
└─────────────────────────────────────────────────────────────┘
关键设计:
- 事件追踪:每次文件编辑、Git 操作、任务创建、错误发生、用户决策都会被记录到 SQLite
- FTS5 索引:所有事件内容建立全文索引,支持 BM25 相关性检索
- 压缩恢复:会话压缩后,Agent 可以通过
ctx_search检索相关历史,而非重放全部日志
// 会话压缩后,Agent 想知道之前在做什么
ctx_search("UserService refactor authentication", { limit: 5 })
// 返回最近 5 条相关事件:
// - [2024-05-01 10:23] Edited: UserService.ts
// - [2024-05-01 10:25] Created: AuthService.ts
// - [2024-05-01 10:28] Error: Circular dependency detected
// - [2024-05-01 10:30] Fixed: Removed circular import
// - [2024-05-01 10:32] User: "继续把数据库操作也抽出来"
2.3 Think in Code:LLM 是代码生成器,不是数据处理器
这是范式级的转变:
// ❌ 错误范式:把 LLM 当数据处理器
// Agent 读取 50 个文件,在内存中分析
for (let i = 1; i <= 50; i++) {
agent.read(`file${i}.ts`) // 每次消耗 3 KB
}
agent.analyze() // 总消耗:150 KB
// ✅ 正确范式:LLM 写代码,代码处理数据
ctx_execute("javascript", `
const fs = require('fs');
const files = fs.readdirSync('src').filter(f => f.endsWith('.ts'));
const stats = files.map(f => ({
name: f,
lines: fs.readFileSync('src/' + f, 'utf8').split('\\n').length
}));
console.log('Total lines:', stats.reduce((sum, s) => sum + s.lines, 0));
console.log('Largest file:', stats.sort((a, b) => b.lines - a.lines)[0].name);
`);
// 输出:
// Total lines: 8421
// Largest file: UserService.ts
// 上下文消耗:3.6 KB(一个工具调用)
Benchmark 对比:
| 场景 | 传统方式 | Think in Code | 节省 |
|---|---|---|---|
| 统计 50 文件行数 | 47 × Read = 700 KB | 1 × ctx_execute = 3.6 KB | 99.5% |
| 分析 500 行日志 | Read + 正则 = 15 KB | ctx_execute 聚合 = 200 B | 98.7% |
| 提取 API 端点 | Grep + Read = 30 KB | ctx_execute 解析 = 500 B | 98.3% |
2.4 Output Compression:智能压缩输出
Context-Mode 内置了输出压缩器,遵循"穴居人原则":
原始输出:
"好的,我来帮你分析一下这个问题。首先,我需要了解一下当前的代码结构。
让我先看看 UserService 的实现... 嗯,这个类确实有点复杂。
我注意到它同时处理了认证、数据库操作和缓存逻辑,这违反了单一职责原则。
所以我建议我们..."
压缩后:
"UserService 违反 SRP。建议:认证 → AuthService,数据库 → UserRepository,
缓存 → CacheManager。先抽哪个?"
压缩规则:
- 删除填充词:just, really, basically, actually, 那个, 就是, 其实...
- 删除客套话:好的, 我来帮你, 请问, 感谢等待...
- 使用片段句:完整句子 → 核心谓语
- 保留技术细节:代码、错误信息、路径、命令不变
- 智能展开:安全警告、不可逆操作、用户困惑时恢复完整表达
实测效果:65-75% 的输出 Token 减少,技术准确性 100% 保持。
三、核心技术实现:MCP Server + Hook 机制
3.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ Context-Mode 组件 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ MCP Server │ │ Hook System │ │ ContentStore │ │
│ │ │ │ │ │ │ │
│ │ 6 Sandbox │ │ PreToolUse │ │ SQLite+FTS5 │ │
│ │ Tools │ │ PostToolUse │ │ BM25 Index │ │
│ │ │ │ PreCompact │ │ │ │
│ │ ctx_execute │ │ SessionStart │ │ Events Table │ │
│ │ ctx_index │ │ │ │ Chunks Table │ │
│ │ ctx_search │ │ Routing │ │ │ │
│ │ ... │ │ Enforcement │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Executor │ │ Compressor │ │ Analytics │ │
│ │ │ │ │ │ │ │
│ │ 10 Languages │ │ Head+Tail │ │ ctx_insight │ │
│ │ Sandboxes │ │ Truncation │ │ 90 Metrics │ │
│ │ │ │ │ │ 37 Patterns │ │
│ │ Node.js │ │ 60/40 Split │ │ 4 Scores │ │
│ │ Python │ │ │ │ │ │
│ │ Ruby... │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
3.2 六个沙箱工具
| 工具 | 功能 | 典型场景 |
|---|---|---|
ctx_execute | 执行代码片段,返回输出 | 数据分析、批量处理 |
ctx_execute_file | 压缩文件内容为摘要 | 日志、测试输出、构建结果 |
ctx_batch_execute | 批量执行多个任务 | 多文件分析 |
ctx_index | 索引内容到知识库 | 文档、API 参考、技能提示 |
ctx_search | BM25 检索索引内容 | 恢复会话上下文 |
ctx_fetch_and_index | 获取并索引远程内容 | 在线文档、GitHub 文件 |
3.3 Hook 系统:拦截与路由
Hook 是 Context-Mode 的核心,它在工具调用的关键节点注入逻辑:
// PreToolUse Hook:拦截大输出工具
// 检测到 Playwright snapshot → 自动路由到 ctx_execute_file
// 检测到 Read 50 files → 自动路由到 ctx_batch_execute
// PostToolUse Hook:记录事件
// 文件编辑 → SQLite INSERT
// Git 操作 → SQLite INSERT
// PreCompact Hook:保存会话状态
// 导出关键事件到 ContentStore
// 建立 FTS5 索引
// SessionStart Hook:注入路由规则
// 告诉 Agent:优先使用沙箱工具,而非原始工具
3.4 智能截断:Head + Tail 保留
传统截断只保留开头,丢失了关键的错误信息。Context-Mode 采用 60/40 分割:
原始日志(100 行):
┌─────────────────────────────┐
│ line 1: Server starting │ ← HEAD(60%)
│ line 2: Loading config │
│ line 3: Connecting to DB │
│ ... │
│ line 57: Connection OK │
├─────────────────────────────┤
│ [40 lines truncated] │ ← 中间省略
├─────────────────────────────┤
│ line 92: Connection timeout │ ← TAIL(40%)
│ line 93: Retry attempt 3 │
│ line 94: FATAL: DB unreachable│
│ line 95: Stack trace... │
│ line 96: exit code: 1 │
└─────────────────────────────┘
这样 Agent 同时看到了启动上下文和错误信息,能更准确地定位问题。
四、14 平台支持:从 Claude Code 到 JetBrains
Context-Mode 支持的 14 个平台分为三类:
4.1 完整 Hook 支持(自动路由)
| 平台 | Hook 能力 | 安装方式 |
|---|---|---|
| Claude Code | PreToolUse, PostToolUse, PreCompact, SessionStart | Plugin Marketplace |
| Gemini CLI | BeforeTool, AfterTool, PreCompress, SessionStart | settings.json |
| VS Code Copilot | PreToolUse, PostToolUse, SessionStart | mcp.json + hooks.json |
| JetBrains Copilot | PreToolUse, PostToolUse, SessionStart | IDE Settings |
| Cursor | preToolUse, postToolUse, stop | mcp.json + hooks.json |
| OpenCode | tool.execute.before, tool.execute.after | opencode.json |
| KiloCode | tool.execute.before, tool.execute.after | kilo.json |
4.2 Claude Code 一键安装
# 添加到插件市场
/plugin marketplace add mksglu/context-mode
# 安装
/plugin install context-mode@context-mode
# 验证
/context-mode:ctx-doctor
# 查看上下文节省统计
/context-mode:ctx-stats
4.3 Gemini CLI 配置
// ~/.gemini/settings.json
{
"mcpServers": {
"context-mode": {
"command": "context-mode"
}
},
"hooks": {
"BeforeTool": [
{
"matcher": "run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode",
"hooks": [{ "type": "command", "command": "context-mode hook gemini-cli beforetool" }]
}
],
"AfterTool": [
{ "hooks": [{ "type": "command", "command": "context-mode hook gemini-cli aftertool" }] }
],
"PreCompress": [
{ "hooks": [{ "type": "command", "command": "context-mode hook gemini-cli precompress" }] }
],
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "context-mode hook gemini-cli sessionstart" }] }
]
}
}
4.4 Cursor 配置
// .cursor/mcp.json
{
"mcpServers": {
"context-mode": {
"command": "context-mode"
}
}
}
// .cursor/hooks.json
{
"version": 1,
"hooks": {
"preToolUse": [
{
"command": "context-mode hook cursor pretooluse",
"matcher": "Shell|Read|Grep|WebFetch|Task|MCP:ctx_execute|MCP:ctx_execute_file|MCP:ctx_batch_execute"
}
],
"postToolUse": [
{ "command": "context-mode hook cursor posttooluse" }
],
"stop": [
{ "command": "context-mode hook cursor stop" }
]
}
}
五、实战案例:从理论到实践
5.1 案例一:重构遗留代码
场景:重构一个 3000 行的 God Class
传统方式:
1. Read UserService.ts (30 KB) → 上下文 +30 KB
2. Read UserService.spec.ts (10 KB) → 上下文 +10 KB
3. Read 相关的 10 个依赖文件 (50 KB) → 上下文 +50 KB
4. 开始分析... [上下文已用 90 KB,能力下降]
5. 提出重构方案... [可能遗漏关键依赖]
Context-Mode 方式:
1. ctx_execute("javascript", `
const code = fs.readFileSync('UserService.ts', 'utf8');
const methods = code.match(/(?:public|private)\s+\w+\([^)]*\)/g) || [];
console.log('Methods:', methods.length);
console.log('Lines:', code.split('\\n').length);
`) → 输出:Methods: 47, Lines: 3012
上下文消耗:100 B
2. ctx_execute_file("UserService.ts", "summarize", { limit: 300 })
→ 输出:"UserService handles auth, DB, cache, logging, validation..."
上下文消耗:300 B
3. ctx_search("dependency injection pattern", { limit: 3 })
→ 从知识库检索相关重构模式
上下文消耗:500 B
总上下文:< 1 KB,Agent 保持最佳状态
5.2 案例二:调试复杂 Bug
场景:测试偶发失败,日志分散在多个文件
传统方式:
1. Read test-output.log (20 KB)
2. Read error.log (15 KB)
3. Read access.log (45 KB)
4. Grep "ERROR" → 找到 500 条记录
5. 人工分析... [上下文 80 KB,信息过载]
Context-Mode 方式:
1. ctx_execute("bash", `
grep -c "ERROR" test-output.log error.log access.log
`) → 输出:test: 23, error: 156, access: 321
2. ctx_execute("python", `
import re
logs = open('test-output.log').read()
errors = re.findall(r'ERROR.*?at line (\d+)', logs)
from collections import Counter
print(Counter(errors).most_common(5))
`) → 输出:Top 5 错误行号
3. ctx_execute_file("error.log", "summarize", {
filter: "ERROR", limit: 200
}) → 只返回 ERROR 相关摘要
总上下文:< 2 KB
5.3 案例三:API 文档查阅
场景:查阅 React 文档实现特定功能
传统方式:
1. WebFetch React docs (60 KB)
2. Read 整个文档... [上下文 +60 KB]
3. 找到相关部分... [可能遗漏]
Context-Mode 方式:
1. ctx_index("React useEffect docs", reactDocContent)
2. ctx_search("useEffect cleanup pattern", { limit: 2 })
→ 返回精确的代码示例:
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData);
return () => controller.abort();
}, [url]);
上下文消耗:1.5 KB(包含完整代码示例)
六、性能 Benchmark:数据说话
6.1 综合测试结果
| 指标 | 数值 |
|---|---|
| 测试场景数 | 21 |
| 测试套件 | 125 tests |
| 原始数据量 | 376 KB |
| 压缩后上下文 | 16.5 KB |
| 总节省率 | 96% |
| 代码示例保留率 | 100%(精确,非摘要) |
| 处理时间 | 15-32ms/场景 |
6.2 单场景对比
| 场景 | 原始大小 | 压缩后 | 节省率 | 处理时间 |
|---|---|---|---|---|
| Playwright 快照(Hacker News) | 56.2 KB | 299 B | 99% | 16ms |
| GitHub Issues(facebook/react) | 58.9 KB | 1.1 KB | 98% | 16ms |
| Nginx 访问日志(500 requests) | 45.1 KB | 155 B | 100% | 17ms |
| Git Log(150+ commits) | 11.6 KB | 107 B | 99% | 16ms |
| 分析 CSV(500 rows) | 85.5 KB | 222 B | 100% | 32ms |
| React useEffect 文档 | 5.9 KB | 261 B | 96% | 18ms |
| MCP 工具列表(40 tools) | 17.0 KB | 742 B | 96% | 15ms |
| 测试输出(30 suites) | 6.0 KB | 337 B | 95% | 16ms |
6.3 真实会话模拟
场景:Claude 200K context window
工具调用序列:
- Context7 docs (3 queries): 16.4 KB → 5.6 KB
- Playwright snapshot: 56.2 KB → 299 B
- GitHub issues: 58.9 KB → 1.1 KB
- Test output: 6.0 KB → 337 B
- Build output: 6.4 KB → 405 B
- Skill prompt: 33.2 KB → 2.4 KB
┌──────────────────────────────────────────────────┐
│ 上下文使用对比 │
├─────────────────────┬────────────────────────────┤
│ 无 Context-Mode │ 有 Context-Mode │
├─────────────────────┼────────────────────────────┤
│ 177.1 KB │ 10.2 KB │
│ 45,300 tokens │ 2,600 tokens │
│ 22.7% context │ 1.3% context │
└─────────────────────┴────────────────────────────┘
结果:94% 更多上下文可用于实际问题解决
七、最佳实践:如何用好 Context-Mode
7.1 工具选择策略
| 数据类型 | 推荐工具 | 原因 |
|---|---|---|
| 文档、API 参考 | ctx_index + ctx_search | 需要精确代码示例,而非摘要 |
| 技能提示词 | ctx_index + ctx_search | 大提示词消耗上下文,按需检索 |
| MCP 工具签名 | ctx_index + ctx_search | 需要精确工具名和参数 |
| 日志文件 | ctx_execute_file | 需要聚合统计,而非原始行 |
| 测试输出 | ctx_execute_file | 需要失败统计,而非完整日志 |
| CSV 数据 | ctx_execute_file | 需要计算指标 |
| 构建输出 | ctx_execute_file | 需要错误计数 |
| 浏览器快照 | ctx_execute_file | 需要页面结构摘要 |
7.2 写好 ctx_execute 的技巧
// ❌ 不好:输出太多
ctx_execute("bash", `
cat package.json
`) // 输出整个文件,消耗大
// ✅ 好:只输出需要的
ctx_execute("bash", `
cat package.json | jq '.dependencies | keys | length'
`) // 输出:"23",最小消耗
// ❌ 不好:多次调用
ctx_execute("bash", "ls -la src")
ctx_execute("bash", "wc -l src/*.ts")
// ✅ 好:合并调用
ctx_execute("bash", `
echo "Files: $(ls src/*.ts | wc -l)"
echo "Lines: $(cat src/*.ts | wc -l)"
`)
7.3 知识库管理
// 索引常用文档
ctx_index("React Patterns", reactPatternsDoc)
ctx_index("API Reference", apiReferenceDoc)
ctx_index("Team Conventions", teamConventionsDoc)
// 会话中检索
ctx_search("error handling pattern", { limit: 3 })
ctx_search("API rate limit", { limit: 2 })
// 定期清理
ctx_purge() // 清空所有索引内容
八、局限性与未来方向
8.1 当前局限
- 非 Hook 平台需要手动路由:部分平台不支持 Hook,需要复制路由文件
- 知识库无持久化:默认 SQLite 在项目目录,跨项目无法共享
- 执行器隔离有限:当前在同一进程执行,安全性有限
- 压缩器语言支持:主要针对英文优化,中文压缩效果稍差
8.2 未来方向
- 云端知识库:支持跨设备、跨项目的知识库同步
- 更强的执行沙箱:基于 Deno 或 Bun 的安全执行环境
- 多语言压缩器:支持中日韩语言的智能压缩
- 可视化分析:ctx_insight 的 Web UI 更丰富
- 协作模式:团队共享的上下文管理策略
九、总结:AI 工程化的关键一步
Context-Mode 解决的不是"模型不够聪明"的问题,而是让聪明的模型更有效率的问题。
在 AI 编程代理的世界里,我们常说:
"Context is King"
但 Context-Mode 告诉我们:
"Context is a Budget — Spend Wisely"
它通过四个维度——沙箱隔离、会话连续性、代码思维、输出压缩——把上下文窗口变成一个可管理的资源,而非随时可能溢出的容器。
对于 AI 工程化来说,这是一个范式级的转变:
- 从 "给模型更多信息" 到 "给模型正确信息"
- 从 "让模型处理数据" 到 "让模型生成处理数据的代码"
- 从 "会话压缩 = 失忆" 到 "会话压缩 = 检索恢复"
如果你正在使用 AI 编程代理,Context-Mode 是一个值得尝试的工具。它不会让模型变聪明,但它能让模型在有限的上下文内发挥最大的价值。
附录:快速上手
安装(以 Claude Code 为例)
# 方式一:Plugin Marketplace(推荐)
/plugin marketplace add mksglu/context-mode
/plugin install context-mode@context-mode
# 方式二:MCP only(无 Hook)
claude mcp add context-mode -- npx -y context-mode
验证
/context-mode:ctx-doctor
# 应该看到所有检查项显示 [x]
查看效果
/context-mode:ctx-stats
# 输出:
# Tool Calls: 45
# Raw Output: 312 KB
# Context Used: 6.8 KB
# Savings: 97.8%
个人分析
/context-mode:ctx-insight
# 打开本地 Web UI,查看 90 个指标、37 个洞察模式
项目地址:https://github.com/mksglu/context-mode
NPM 包:https://www.npmjs.com/package/context-mode
Discord 社区:https://discord.gg/DCN9jUgN5v
Hacker News 讨论:https://news.ycombinator.com/item?id=47193064