context-mode 反模式避坑指南:execute / execute_file 的 8 大常见错误与正确姿势

发布时间:2026/9/13 11:38:37
context-mode 反模式避坑指南:execute / execute_file 的 8 大常见错误与正确姿势 context-mode 反模式避坑指南execute / execute_file 的 8 大常见错误与正确姿势【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode本指南以 context-mode 官方反模式文档 skills/context-mode/references/anti-patterns.md 为核心系统梳理在使用ctx_execute/ctx_execute_file时最常犯的 8 类错误并结合 src/executor.ts 的沙箱执行实现与 skills/context-mode/SKILL.md 的决策规则给出可直接照抄的正确写法。读完你将掌握何时该用 Bash、何时必须走 context-mode、如何保证脚本输出可被 LLM 正确摘要、如何设置合理的timeout_ms、以及如何用好summary_prompt与「捕获层 / 过滤层」分离的心智模型让大输出日志、构建产物、Playwright 快照对上下文的消耗从数十万 token 降到数百字节。反模式之前context-mode 的两层心智模型在进入反模式清单之前需要先建立 context-mode 的核心心智模型ctx_execute负责捕获capturectx_search负责过滤filter这是两个独立的分层永远不要合并它们。┌──────────────────────┐ ┌──────────────────────┐ │ ctx_execute │ ───▶ │ ctx_search │ │ (capture layer) │ │ (filter layer) │ │ │ │ │ │ produces full │ │ queries the │ │ output into index │ │ captured index │ └──────────────────────┘ └──────────────────────┘ ▲ ▲ │ │ Job: capture Job: narrow Do NOT narrow here. Do all narrowing here.ctx_execute的输出是一次性写入write-once索引的命令完整运行、完整入索引。所有后续的窄化narrowing都应该发生在下游的ctx_search调用中。这一分层之所以重要是因为索引是跨调用、跨会话存活的查询面——任何在进入索引之前就被丢弃的数据将永久地从当前会话的可查询范围内消失而保留在索引里的数据可以被不同的问题反复查询且零重新执行成本。这与 src/server.ts 中声明的「Think-in-Code」哲学一脉相承你的代码所处理的字节永远不会进入对话记忆只有你console.log()出来的内容才会。读取一份 700 KB 的日志意味着 700 KB 的推理容量被原始字节消耗在沙箱中运行代码处理这份日志并打印 3 KB 摘要则保留 697 KB 的容量用于真正的工作。反模式 1用 execute 处理小输出少于 20 行问题ctx_execute带有额外开销LLM 摘要调用。对于小输出Bash 更快更便宜。BAD — 浪费地使用 execute: Tool: execute code: echo $(node --version) language: shell GOOD — 直接用 Bash: Tool: Bash command: node --version规则如果输出能轻松装进你的上下文窗口约 20 行以内直接使用 Bash。把execute保留给那些会撑爆上下文、或需要智能摘要的输出。更多「直接用 Bash」的例子git status— 通常 5-10 行ls -la— 目录列表cat .env.example— 小配置文件pwd、whoami、which nodewc -l src/index.ts— 单行输出这一边界在 skills/context-mode/SKILL.md 中有更完整的落点Bash 白名单包括文件变更mkdir/mv/cp/rm/touch/chmod、Git 写操作git add/git commit/git push…、导航cd/pwd/which、进程控制kill/pkill、包管理npm install/pip install以及简单输出echo/printf。白名单之外的一切——任何读取、查询、抓取、列出、日志、测试、构建、diff、检查或调用外部服务的命令——都应走ctx_execute或ctx_execute_file包括 gh、aws、kubectl、docker、terraform、wrangler、fly、heroku、gcloud 等所有 CLI。反模式 2忘记打印输出问题ctx_execute捕获的是 stdout。如果你的代码什么都没打印摘要就会是空的或没有意义的。// BAD — 没有输出: const fs require(fs); const data JSON.parse(fs.readFileSync(package.json, utf8)); const deps Object.keys(data.dependencies); // 什么都没打印LLM 看到的 stdout 是空的。 // GOOD — 显式输出: const fs require(fs); const data JSON.parse(fs.readFileSync(package.json, utf8)); const deps Object.keys(data.dependencies); console.log(Dependencies (${deps.length}):); deps.forEach(d console.log( ${d}: ${data.dependencies[d]}));# BAD — 计算了但从不打印: with open(data.json) as f: data json.load(f) result [x for x in data if x[status] error] # result 丢失了 —— 从未打印 # GOOD — 总是打印结果: with open(data.json) as f: data json.load(f) result [x for x in data if x[status] error] print(fFound {len(result)} errors:) for r in result: print(f {r[id]}: {r[message]})规则每个execute脚本必须以 print/console.log 结束输出你想要被摘要的结果。这一规则在实现层面被反复强化。在 src/server.ts 的ctx_execute工具描述中明确写着执行代码时要用console.logJS/TS、printPython/Ruby/Perl/R、echoShell/PHP、fmt.PrintlnGo、IO.putsElixir或Console.WriteLineC#来把摘要输出到上下文。ctx_execute_file同样如此src/server.ts「代码用于处理 FILE_CONTENT。用 console.log/print/echo/IO.puts/Console.WriteLine 打印摘要。」stdout 是唯一进入上下文的东西——没有输出 浪费一次调用参见 SKILL.md 的 Critical Rules 第 1 条。反模式 3Bash 能做时却用 JS/Python或者反过来Bash 硬扛复杂处理问题复杂的数据处理在 Bash 里会迅速变得不可读、易出错。# BAD — 在 Bash 里解析 JSON 很脆弱: cat data.json | python3 -c import sys, json data json.load(sys.stdin) for item in data: if item[status] error: print(item[id], item[message]) # 如果你已经在内联 Python直接使用 language: python// GOOD — 为任务选择正确的语言: // language: javascript const data require(./data.json); data.filter(x x.status error) .forEach(x console.log(${x.id}: ${x.message}));规则如果你的 Bash 脚本里包含内联 Python/Node或复杂的jq/awk管道链改用language: python或language: javascript。你应该从 shell 切换的信号在 shell 脚本中使用python3 -c或node -e链式管道超过 3 个用jq做复杂的 JSON 变换Bash 中的嵌套循环超出简单cut/sed的字符串操作语言选择的标准来自 skills/context-mode/SKILL.md场景语言原因HTTP/API 调用、JSONjavascript原生 fetch、JSON.parse、async/await数据分析、CSV、统计pythoncsv、statistics、collections、re带管道的 shell 命令shellgrep、awk、jq、原生工具文件模式匹配shellfind、wc、sort、uniq从实现角度src/executor.ts 的PolyglotExecutor.execute()支持 12 种语言javascript/typescript/python/shell/ruby/go/rust/php/perl/r/elixir/csharp每种语言都会在系统临时目录中生成对应扩展名的脚本SCRIPT_EXT映射见 src/executor.ts并通过buildCommand调度运行时执行。Go 代码会自动补package main包装src/executor.tsPHP 自动补?php开头src/executor.tsElixir 在 Mix 项目内自动注入 BEAM 编译路径src/executor.ts——你只需关注业务代码本身。反模式 4把整个文件读进上下文再处理问题用Read工具读取 10,000 行的文件然后询问相关内容会耗尽整个上下文窗口。应该用execute处理文件并只返回摘要。BAD workflow: 1. Read tool: read server.log10,000 行进入上下文 2. Find all errors in this log → 为了一个只需 ~20 行输出答案的问题消耗了 10,000 行上下文 GOOD workflow: 1. execute with language: python code: | with open(server.log) as f: errors [l for l in f if ERROR in l] print(fTotal errors: {len(errors)}) for e in errors[-20:]: print(e.strip()) summary_prompt: Categorize errors and report frequency → 只有摘要进入上下文BAD workflow: 1. Read tool: read package-lock.json20,000 行 2. What version of lodash is installed? GOOD workflow: 1. execute with language: javascript code: | const lock require(./package-lock.json); const find (deps, name) { if (deps[name]) return deps[name].version; for (const [, dep] of Object.entries(deps)) { if (dep.dependencies) { const v find(dep.dependencies, name); if (v) return v; } } }; console.log(lodash: ${find(lock.dependencies, lodash) || not found}); summary_prompt: Report the installed version of lodash规则如果文件超过 200 行而你只需要其中特定数据用execute提取所需内容而不是把整个文件读进上下文。对于「只分析、不编辑」的文件读取场景context-mode 提供了更优的工具ctx_execute_file。它会在沙箱内预先加载文件内容到FILE_CONTENT变量src/executor.ts你的代码直接处理FILE_CONTENT并打印结论——文件字节从未进入上下文。以 Python 为例# FILE_CONTENT 由 ctx_execute_file 预加载 import json data json.loads(FILE_CONTENT) print(fRecords: {len(data)}) # ... 分析并打印结论SKILL.md 的决策树明确规定「读取文件用于分析/摘要非编辑」→ 使用ctx_execute_file文件加载进 FILE_CONTENT而不是上下文。需要编辑的文件才用常规 Read 工具Critical Rules 第 4 条。反模式 5结构化输出不序列化问题不序列化就打印对象JavaScript 会得到[object Object]。// BAD — 打印出 [object Object]: const pkg require(./package.json); console.log(pkg.dependencies); // Output: [object Object] // GOOD — 正确序列化: const pkg require(./package.json); console.log(JSON.stringify(pkg.dependencies, null, 2)); // Output: { react: ^18.2.0, next: ^14.0.0, ... }// BAD — 数组会丢失结构: const items [{name: a, value: 1}, {name: b, value: 2}]; console.log(items); // 可能打印得毫无帮助 // GOOD — 格式化为表格: const items [{name: a, value: 1}, {name: b, value: 2}]; console.log(Name | Value); console.log(------|------); items.forEach(i console.log(${i.name.padEnd(5)} | ${i.value})); // 或者使用 JSON.stringify: console.log(JSON.stringify(items, null, 2));规则JavaScript 中对象/数组始终使用JSON.stringify(data, null, 2)或格式化为可读表格。Python 中使用json.dumps(data, indent2)或pprint.pprint(data)。更进阶的做法是「写分析代码而不是数据倾倒」SKILL.md Critical Rules 第 2 条不要只console.log(JSON.stringify(data))先分析再打印结论。并做到输出具体Critical Rules 第 3 条打印带 ID、行号、精确值的 bug 细节而不仅是计数。例如分析 API 端点时const resp await fetch(http://localhost:3000/api/orders); const { orders } await resp.json(); const bugs []; const negQty orders.filter(o o.quantity 0); if (negQty.length) bugs.push(Negative qty: ${negQty.map(o o.id).join(, )}); const nullFields orders.filter(o !o.product || !o.customer); if (nullFields.length) bugs.push(Null fields: ${nullFields.map(o o.id).join(, )}); console.log(${orders.length} orders, ${bugs.length} bugs found:); bugs.forEach(b console.log(- ${b}));反模式 6网络操作的超时设置太短问题默认超时可能对 API 调用、构建或测试套件来说太短。BAD — 在 API 调用上会超时: Tool: execute code: | const resp await fetch(https://api.slow-service.com/data); console.log(await resp.json()); language: javascript timeout_ms: 5000 ← API 可能需要 10 秒以上 GOOD — 为网络操作给出宽裕超时: Tool: execute code: | const resp await fetch(https://api.slow-service.com/data); console.log(JSON.stringify(await resp.json(), null, 2)); language: javascript timeout_ms: 30000 ← 网络调用给 30 秒推荐超时设置操作timeout_ms文件读取/解析5000 - 10000本地计算10000单次 API 请求15000 - 30000分页 API 调用30000 - 60000npm install / 构建120000完整测试套件120000 - 300000规则始终考虑脚本在做什么并据此设置timeout_ms。网络调用和构建需要的时间远多于文件操作。关于超时的底层行为src/executor.ts有几处值得注意的实现细节超时触发时非后台进程会被killTree连同整个进程组一起杀掉Windows 用taskkill /F /TUnix 杀负 PID 进程组防止孤儿子进程残留src/executor.ts超时策略的归属权在 MCP 宿主/客户端Claude Code、VSCode、JetBrains 都执行自己的 RPC 超时executor 不会在调用方未传超时时擅自强加第二个策略否则会把 30 分钟的 Gradle/Maven/SBT 构建误杀成假阴性issue #406此外还存在一个流级硬上限stdoutstderr 合并超过 100MB#hardCapBytes默认 100 * 1024 * 1024 字节会直接杀掉进程并在 stderr 标注[output capped at 100MB — process killed]src/executor.ts防止yes或cat /dev/urandom | base64这类命令在超时前把内存撑爆。反模式 7没有有效使用 summary_prompt问题没有好的summary_promptLLM 摘要可能聚焦在无关细节上。BAD — 模糊或缺失的 summary_prompt: summary_prompt: Summarize this → 可能聚焦在错误的方向 GOOD — 具体且可执行: summary_prompt: Report the count of failing tests, list each failure with its file path and error message, and identify any patterns in the failures编写有效 summary_prompt 的技巧具体说明你需要哪些数据点要求计数和指标而不只是描述请求可执行的洞察suggest fixes、identify patterns说明想要的格式list as bullet points、group by category三个配套的参考文档 skills/context-mode/references/patterns-javascript.md、skills/context-mode/references/patterns-python.md、skills/context-mode/references/patterns-shell.md 中每个示例都附带了具体的summary_prompt与timeout_ms可直接套用。例如分页 API 收集后summary_prompt: Summarize issue distribution by label, highlight stale issues, suggest prioritiestimeout_ms: 30000Jest 测试摘要后summary_prompt: Report pass/fail ratio, list all failing test names with suite, note any slow teststimeout_ms: 120000。反模式 8ctx_execute捕获、ctx_search过滤——不要把两层合并ctx_execute和ctx_search是两个层不是一个。ctx_execute存在的意义是把完整输出捕获进索引ctx_search存在的意义是过滤已被捕获的内容。当你在ctx_execute内部、在 shell 层、在脚本逻辑里——任何捕获上游的位置——窄化输出时被丢弃的行永远不会到达索引。ctx_search无法恢复从未写入的内容。你花费了捕获预算却丢失了之后想查询的数据且没有获得任何上下文窗口收益大的 stdout 已经被自动索引不会内联返回。规则把ctx_execute的输出视为对索引的一次性写入。完整运行命令并让它入索引。所有窄化步骤都在下游通过ctx_search完成。如果你发现自己在ctx_execute内部裁剪输出那就是在捕获层做过滤层的活——停下来把窄化移到一次ctx_search调用中。为什么分层如此重要索引是跨调用、跨会话存活的东西。任何在进入索引前被丢弃的内容都会永久地从本会话的可查询面消失任何保留的内容都可以反复、以不同问题、零重执行成本地被查询。大输出自动索引与 intent 参数这条规则得以成立是因为 context-mode 对大输出有自动索引机制。在 src/server.ts 中ctx_execute支持传入intent字符串当输出超过约 5KB 阈值时自动索引进知识库只返回章节标题 预览之后可通过ctx_search按主题检索。底层还有一个更激进的硬阈值LARGE_OUTPUT_THRESHOLD 102_400100KBsrc/server.ts超过即自动索引为 FTS5 返回指针。ctx_batch_execute更进一步一次调用运行多个命令、全部输出自动索引、可同时传入queries在同一次往返中返回匹配章节src/server.ts。ctx_search 的查询姿势配合 skills/ctx-search/SKILL.md 的规则优先使用ctx_searchMCP 工具把所有相关问题批量放进一个queries数组——绝不要多次单独调用ctx_search()当用户指定项目或已索引标签时用source参数限定范围部分匹配有效source: Node可匹配Node.js v22 CHANGELOG使用 2-4 个具体技术术语的短查询BM25 是 OR 语义命中更多词的结果自动排名更高。ctx_search({ source: project:name, queries: [authentication middleware, token refresh], limit: 5 })MCP 不可用时回退到 CLIcontext-mode search authentication middleware --source project:name --limit 5。索引为空时先运行/context-mode:ctx-index或context-mode index path。反面案例不要把 Playwright 快照塞进上下文分层模型最典型的落点是 Playwright 集成。browser_snapshot返回 10K–135K token 的无障碍树数据不带filename调用会把全部内容倒进上下文再把输出传给ctx_index(content: ...)则会作为参数第二次进入上下文——两种都是错的。正确姿势是「Playwright → 文件 → 服务端读取 → 上下文」绝不允许「Playwright → 上下文 → ctx_index(content) → 再进上下文」Workflow A: 快照 → 文件 → 索引 → 多次搜索 Step 1: browser_snapshot(filename: /tmp/playwright-snapshot.md) → 保存到文件只返回 ~50B 确认而不是 135K token Step 2: ctx_index(path: /tmp/playwright-snapshot.md, source: Playwright snapshot) → 服务端读取文件索引进 FTS5返回 ~80B 确认 Step 3: ctx_search(queries: [login form email password], source: Playwright) → 只返回匹配的章节~300B 总上下文消耗约 430B而非 270K token真实约 99% 的节省 Workflow B: 快照 → 文件 → execute_file一次性提取 Step 1: browser_snapshot(filename: /tmp/playwright-snapshot.md) → ~50B Step 2: ctx_execute_file(path: /tmp/playwright-snapshot.md, language: javascript, code: const links [...FILE_CONTENT.matchAll(/- link \([^\])\/g)].map(m m[1]); const buttons [...FILE_CONTENT.matchAll(/- button \([^\])\/g)].map(m m[1]); const inputs [...FILE_CONTENT.matchAll(/- textbox|- checkbox|- radio/g)]; console.log(Links:, links.length, | Buttons:, buttons.length, | Inputs:, inputs.length); console.log(Navigation:, links.slice(0, 10).join(, )); ) → 沙箱内处理返回 ~200B 摘要 总上下文消耗约 250B而非 135K token方式上下文成本正确browser_snapshot()→ 原始输出进上下文135K token否browser_snapshot()→ctx_index(content: raw)270K token翻倍否browser_snapshot(filename)→ctx_index(path)→ctx_search约 430B是browser_snapshot(filename)→ctx_execute_file(path)约 250B是关键规则调用browser_snapshot、browser_console_messages、browser_network_requests时始终使用filename参数然后用ctx_index(path: ...)或ctx_execute_file(path: ...)处理——绝不用ctx_index(content: ...)content 参数会把数据当工具参数送进上下文只应留给你自己编写的小段内联文本。其他常见反模式速查结合 skills/context-mode/SKILL.md 的 Anti-Patterns 清单还有一批高频错误值得警惕用 Bash 跑curl http://api/endpoint→ 50KB 涌入上下文。改用ctx_execute fetch用 Bashcat large-file.json→ 整个文件进上下文。改用ctx_execute_file用 Bash 跑gh pr list→ 原始 JSON 进上下文。改用ctx_execute--jq过滤可参考 SKILL.md 示例gh pr list --json number,title,state,reviewDecision --jq .[] | \(.number) [\(.state)] \(.title) — \(.reviewDecision // no review)把 Bash 输出| head -20→ 丢失其余部分。用ctx_execute分析全部数据并打印摘要用 Bash 跑npm test→ 完整测试输出进上下文。用ctx_execute捕获并摘要调用 MCP 工具Context7query-docs、GitHub API 等后把响应传给ctx_index(content: response)→上下文用量翻倍。响应已在上下文中——直接使用或先存文件参见 SKILL.md 的「MCP 输出已在上下文」规则不要重复索引;忽略browser_navigate的自动快照 → 导航响应包含完整页面快照。检查页面时单独调用browser_snapshot(filename)期待ctx_stats重置或清空任何内容 →ctx_stats是只读的仅显示统计。用ctx_purge(confirm: true)永久删除全部已索引内容。使用 execute 前的最终检查清单每次使用execute之前逐项核对输出将超过 20 行否则用 Bash脚本把所有结果打印到 stdout对象已用 JSON.stringify / json.dumps 序列化超时与操作类型匹配语言与任务匹配JS 处理 JSON/APIPython 处理数据Shell 处理管道summary_prompt 具体且可执行没有把一个本可在 execute 内部处理的文件加载进上下文参考文件反模式主文档本文骨架来源context-mode 技能总则决策树、Bash 白名单、Critical Rules、Playwright 集成JavaScript/TypeScript 模式Python 模式Shell 模式ctx-search 技能查询语法与 CLI 回退多语言沙箱执行器实现超时、输出上限、环境变量净化、FILE_CONTENT 注入ctx_execute / ctx_execute_file / ctx_search 工具注册 与 服务端工具定义与自动索引【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考