context-mode Shell 实战模式:构建、测试、日志与仓库分析的高效沙箱指南
【免费下载链接】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 项目中ctx_execute/ctx_execute_file的language: shell使用方式展开,系统梳理构建输出过滤、测试结果汇总、日志文件分析、目录结构与 Git 历史分析等高频场景的实战脚本模式。读者将掌握如何在沙箱内用tee+PIPESTATUS捕获命令真实退出码、用grep/awk/sort/uniq原生工具把海量输出浓缩为结构化摘要,并理解底层 PolyglotExecutor 执行 shell 脚本时的运行环境、安全约束与超时语义,让每次命令执行都只把"结论"带进上下文,而不是原始数据。
为什么 Shell 是 context-mode 的第四种一等语言
在 context-mode 的ctx_execute工具中,language支持javascript、python、shell等运行时。根据 SKILL.md 中的语言选择表,shell的定位非常明确:
| 场景 | 语言 | 理由 |
|---|---|---|
| HTTP/API 调用、JSON 处理 | javascript | 原生 fetch、JSON.parse、async/await |
| 数据分析、CSV、统计 | python | csv、statistics、collections、re |
| 带管道的 Shell 命令 | shell | grep、awk、jq、原生工具 |
| 文件模式匹配 | shell | find、wc、sort、uniq |
Shell 的价值在于:任何需要"先跑命令、再过滤、再统计"的任务,都可以用一条管道链在沙箱内完成。与 Bash 直连不同,ctx_execute的沙箱会把 stdout 完整捕获,再由summary_prompt引导 LLM 生成摘要——因此脚本的职责就是"分析并打印结论",而不是"把原始输出透传回来"。这正是下文所有模式的第一性原理:stdout 是唯一进入上下文的通道,脚本必须自己完成过滤与统计。
构建输出过滤(Build Output Filtering)
构建命令(npm run build、tsc、gradle、mvn)的输出动辄数千行,直接进入上下文会瞬间挤占窗口。正确姿势是:tee落盘 +PIPESTATUS捕获真实退出码 +grep分层提取错误/警告。
仅捕获构建错误
npm run build的输出被管道传给tee后,$?已经变成tee的退出码,必须用${PIPESTATUS[0]}取回管道第一个命令(npm)的退出码。随后按退出码分支,分别提取 Error 与 Warning 段落:
npm run build 2>&1 | tee /tmp/build-output.txt EXIT_CODE=${PIPESTATUS[0]} echo "=== Build Result ===" echo "Exit code: $EXIT_CODE" if [ "$EXIT_CODE" -ne 0 ]; then echo "" echo "=== Errors ===" grep -iE '(error|failed|FAIL)' /tmp/build-output.txt | head -50 echo "" echo "=== Warnings ===" grep -iE '(warning|warn)' /tmp/build-output.txt | head -20 else echo "Build succeeded." echo "" echo "=== Warnings (if any) ===" grep -iE '(warning|warn)' /tmp/build-output.txt | head -10 fi echo "" echo "=== Output Size ===" wc -l < /tmp/build-output.txt | xargs -I{} echo "{} total lines of output" rm -f /tmp/build-output.txtsummary_prompt: "Report build success/failure, list all errors with file paths, and count warnings" timeout_ms: 120000
要点:
2>&1把 stderr 并入 stdout,确保编译器的报错行不会漏进tee;- 构建类任务耗时较长,
timeout_ms: 120000(2 分钟)是合理下限; - 脚本结束时
rm -f清理临时文件——沙箱临时目录在进程结束后也会被回收(见下文执行器说明),但主动清理是良好习惯。
TypeScript 编译检查
npx tsc --noEmit的报错量在大型 monorepo 中同样惊人。该模式不仅统计错误总数,还用grep -oP 'error TS\d+'按错误码聚合、用cut -d'(' -f1按文件聚合,让 LLM 一眼看到"哪些错误码最多、哪个文件最受伤":
npx tsc --noEmit 2>&1 | tee /tmp/tsc-output.txt EXIT_CODE=${PIPESTATUS[0]} echo "=== TypeScript Check ===" echo "Exit code: $EXIT_CODE" TOTAL_ERRORS=$(grep -c 'error TS' /tmp/tsc-output.txt 2>/dev/null || echo 0) echo "Total errors: $TOTAL_ERRORS" if [ "$TOTAL_ERRORS" -gt 0 ]; then echo "" echo "=== Errors by Code ===" grep -oP 'error TS\d+' /tmp/tsc-output.txt | sort | uniq -c | sort -rn | head -20 echo "" echo "=== Errors by File ===" grep 'error TS' /tmp/tsc-output.txt | cut -d'(' -f1 | sort | uniq -c | sort -rn | head -20 echo "" echo "=== First 30 Errors ===" grep 'error TS' /tmp/tsc-output.txt | head -30 fi rm -f /tmp/tsc-output.txtsummary_prompt: "Report type error count, most common error codes, and most affected files" timeout_ms: 60000
grep -c ... || echo 0的写法值得注意:当没有任何匹配时grep -c返回非零退出码,|| echo 0保证TOTAL_ERRORS永远是数字而非空串。这里的summary_prompt明确要求报告"最常见的错误码"和"受影响最大的文件",与脚本输出的聚合维度一一对应。
测试结果汇总(Test Result Summarization)
测试套件是另一个输出大户。两条模式分别覆盖 Jest 与 Pytest,共同思路:抓取摘要行(Tests/Test Suites/Snapshots)、抓取失败详情、最后清理临时文件。
Jest 测试摘要
npx jest --verbose 2>&1 | tee /tmp/test-output.txt EXIT_CODE=${PIPESTATUS[0]} echo "" echo "=== Test Summary ===" echo "Exit code: $EXIT_CODE" # Extract summary line grep -E '(Tests:|Test Suites:|Snapshots:|Time:)' /tmp/test-output.txt echo "" echo "=== Failed Tests ===" grep -A 2 'FAIL ' /tmp/test-output.txt | head -40 echo "" echo "=== Slow Tests (if reported) ===" grep -i 'slow' /tmp/test-output.txt | head -10 rm -f /tmp/test-output.txtsummary_prompt: "Report pass/fail ratio, list all failing test names with suite, note any slow tests" timeout_ms: 120000
Pytest 摘要
python -m pytest --tb=short -q 2>&1 | tee /tmp/pytest-output.txt EXIT_CODE=${PIPESTATUS[0]} echo "" echo "=== Pytest Summary ===" echo "Exit code: $EXIT_CODE" # Last 20 lines usually contain the summary tail -20 /tmp/pytest-output.txt echo "" echo "=== Failures ===" grep -E '(FAILED|ERROR)' /tmp/pytest-output.txt | head -30 rm -f /tmp/pytest-output.txtsummary_prompt: "Report test results, list all failures with file and test name" timeout_ms: 120000
两个示例都使用了--tb=short/-q这类"预过滤"参数,先让被测工具本身少输出,再在脚本里做二次提取——这是分层降噪的典型做法。summary_prompt明确要求"列出失败测试所在文件与测试名",与grep -E '(FAILED|ERROR)'的输出格式匹配,保证 LLM 能直接引用具体失败点。
日志文件分析(Log File Analysis)
日志分析是ctx_execute的高频场景之一:日志文件往往数万行,而你需要的是级别分布、最近错误、时间线趋势这三类信息。
按严重级别过滤应用日志
LOG_FILE="${1:-/var/log/app.log}" echo "=== Log File: $LOG_FILE ===" echo "Total lines: $(wc -l < "$LOG_FILE")" echo "" echo "=== Level Distribution ===" grep -oE '\b(DEBUG|INFO|WARN|ERROR|FATAL)\b' "$LOG_FILE" | sort | uniq -c | sort -rn echo "" echo "=== Last 20 Errors ===" grep -i 'ERROR\|FATAL' "$LOG_FILE" | tail -20 echo "" echo "=== Error Timeline (hourly) ===" grep -i 'ERROR' "$LOG_FILE" | grep -oE '\d{4}-\d{2}-\d{2} \d{2}' | sort | uniq -c | tail -24summary_prompt: "Report error frequency, identify patterns, and note any error spikes"
三段的职责非常清晰:
grep -oE '\b(DEBUG|INFO|WARN|ERROR|FATAL)\b'+sort | uniq -c | sort -rn:得到级别频次直方图,\b词边界防止误匹配日志中的普通单词;tail -20拿最近错误(避免head取到最早的过时错误);- 时间线分析用
grep -oE '\d{4}-\d{2}-\d{2} \d{2}'抽出"日期 + 小时"前缀再聚合,直接看出错误是否在某小时集中爆发(错误尖峰)。
分析访问日志
访问日志(Nginx/Apache 等)是纯文本结构化数据的代表,用awk取字段最合适:
LOG_FILE="${1:-/var/log/access.log}" echo "=== Access Log Summary ===" echo "Total requests: $(wc -l < "$LOG_FILE")" echo "" echo "=== HTTP Status Codes ===" awk '{print $9}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10 echo "" echo "=== Top 20 Paths ===" awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -20 echo "" echo "=== Top 10 IPs ===" awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10 echo "" echo "=== 5xx Errors ===" awk '$9 ~ /^5/' "$LOG_FILE" | tail -20 echo "" echo "=== Requests per Hour ===" awk '{print $4}' "$LOG_FILE" | cut -d: -f1-2 | sort | uniq -c | tail -24summary_prompt: "Report traffic patterns, error rates, most hit endpoints, and suspicious IPs"
这里用$9(状态码)、$7(请求路径)、$1(客户端 IP)、$4(时间戳字段)直接按列切分,配合sort | uniq -c | sort -rn得到 Top N 排行。5xx 检测用awk '$9 ~ /^5/'正则匹配状态码首字符;summary_prompt中的 "suspicious IPs" 引导 LLM 进一步分析高请求 IP 是否有爬虫或攻击特征。
目录大小与结构分析(Directory Size and Structure Analysis)
仓库体积分析依赖find、du这类文件系统工具,是 shell 相比 JS/Python 的优势区——无需加载任何文件内容,只扫元数据。
项目结构总览
echo "=== Directory Structure ===" find . -maxdepth 3 -type d \ ! -path '*/node_modules/*' \ ! -path '*/.git/*' \ ! -path '*/dist/*' \ ! -path '*/.next/*' \ ! -path '*/__pycache__/*' \ | sort echo "" echo "=== File Type Distribution ===" find . -type f \ ! -path '*/node_modules/*' \ ! -path '*/.git/*' \ ! -path '*/dist/*' \ | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -20 echo "" echo "=== Largest Files (top 20) ===" find . -type f \ ! -path '*/node_modules/*' \ ! -path '*/.git/*' \ -exec ls -la {} \; | sort -k5 -rn | head -20 | awk '{print $5, $9}' echo "" echo "=== Directory Sizes ===" du -sh */ 2>/dev/null | sort -rh | head -15summary_prompt: "Describe the project structure, identify large files that may need attention, report file type distribution"
三段分析各回答一个问题:目录树长什么样(排除 node_modules/.git/dist/.next/pycache等噪音目录)、文件类型分布如何(sed 's/.*\.//'取扩展名)、哪些文件最大(sort -k5 -rn按ls -la第 5 列字节数降序)。
磁盘占用排查
echo "=== Top-Level Disk Usage ===" du -sh */ 2>/dev/null | sort -rh echo "" echo "=== node_modules Size ===" if [ -d "node_modules" ]; then du -sh node_modules echo "" echo "=== Largest node_modules packages ===" du -sh node_modules/*/ 2>/dev/null | sort -rh | head -20 else echo "No node_modules directory" fi echo "" echo "=== Build Artifacts ===" for dir in dist build .next out .cache; do if [ -d "$dir" ]; then echo " $dir: $(du -sh "$dir" | cut -f1)" fi done echo "" echo "=== Git Objects Size ===" if [ -d ".git" ]; then du -sh .git fisummary_prompt: "Report total project size, largest contributors, and recommend cleanup targets"
注意du -sh node_modules/*/ 2>/dev/null:node_modules下可能有无权限访问或损坏的目录,2>/dev/null静默丢弃 stderr,避免单条错误中断整段分析。这个模式还演示了for循环 + 存在性检查(if [ -d ... ]),把"可能不存在的构建产物目录"逐个探测——这是 shell 脚本健壮性的典型写法。
Git 分析(Git Analysis)
Git 历史分析对上下文消耗极其敏感:git log的原始输出可能成百上千行,而你要的只是提交数、作者排行、热点文件这几个数字。
提交活跃度分析
echo "=== Recent Commits (last 30 days) ===" git log --since="30 days ago" --oneline | wc -l | xargs -I{} echo "{} commits in last 30 days" echo "" echo "=== Commits by Author ===" git shortlog -sn --since="30 days ago" | head -15 echo "" echo "=== Most Changed Files (last 30 days) ===" git log --since="30 days ago" --pretty=format: --name-only | sort | uniq -c | sort -rn | head -20 echo "" echo "=== Branches ===" echo "Local: $(git branch | wc -l | xargs)" echo "Remote: $(git branch -r | wc -l | xargs)" echo "" echo "=== Stale Branches (merged, excluding main/master) ===" git branch --merged main 2>/dev/null | grep -v 'main\|master\|\*' | head -10summary_prompt: "Report development velocity, active contributors, hotspot files, and cleanup opportunities"
关键技巧:
git log --pretty=format: --name-only配合sort | uniq -c | sort -rn统计"最近 30 天改动最多的文件",即热点文件(hotspot files);xargs -I{} echo "{} commits ..."把wc -l的数字嵌入人类可读句子,而不是输出一个裸数字——LLM 摘要时语义更明确;git branch --merged main | grep -v 'main\|master\|\*'找出已合并进 main 的陈旧分支,为清理提供候选。
底层原理:Shell 脚本在沙箱中的真实运行方式
理解这些模式为何有效,需要看 executor.ts 中PolyglotExecutor的实现:
- 脚本落盘与执行:
ctx_execute会把code写入系统临时目录(mkdtempSync(join(OS_TMPDIR, ".ctx-mode-")))下的脚本文件,shell 语言使用.sh扩展名(Windows 上按 shell 类型可能写为无扩展名或.ps1/.cmd,见 buildScriptFilename);随后通过 buildCommand 构造bash /path/to/script.sh(Windows Git Bash 下使用bash -c "source '路径'"规避 MSYS2 路径改写,PowerShell 则追加-NoProfile -ExecutionPolicy Bypass -File)。 - 工作目录是项目根目录:所有语言统一在项目根目录运行(
cwd = cwdOverride ?? this.#projectRoot),因此脚本中的git、相对路径、package.json都能自然解析。 - 输出字节上限:stdout + stderr 合计超过 100MB(
hardCapBytes)时进程会被直接杀掉,防止yes、cat /dev/urandom | base64之类命令打爆内存——这也是为什么日志分析模式总是先grep过滤再输出。 - 超时语义:调用方未传
timeout时不设内部超时(超时策略属于 MCP 宿主,如 Claude Code、VSCode、JetBrains 各自有 RPC 超时);所以> timeout_ms: 120000这类元注释必须由调用者显式给出。 - 环境净化:执行前会剥离一批高危环境变量(
BASH_ENV、ENV、PS4、CDPATH、LD_PRELOAD、GIT_CONFIG_GLOBAL等,见 #buildSafeEnv),并强制NO_COLOR=1、LANG=en_US.UTF-8,保证输出是干净可解析的纯文本。同时把父进程PATH显式写回脚本(buildShellScriptContent),避免 shell 启动时的 PATH 漂移导致命令找不到。 - shell 运行时探测:
detectRuntimes()优先取SHELL环境变量(仅当 basename 匹配bash|sh|zsh|dash|pwsh|powershell|cmd白名单时,防注入),否则 POSIX 上回退bash→sh,Windows 上按 Git Bash → sh → pwsh → powershell → cmd.exe 顺序探测,详见 runtime.ts。 - Windows 特例:Git Bash 上会把裸
mvn重写为mvn.cmd以绕过 mingw 的路径转换缺陷(rewriteWindowsBuildTools);PowerShell 脚本会预置 UTF-8 BOM 防止 5.1 按 ANSI 码页解码乱码,tests/core/executor.test.ts 对此有专门测试。
语言选择与常见误区
虽然本文聚焦 shell,但 shell 并非万能。综合 SKILL.md 与 anti-patterns.md,判断标准如下:
- 超过 3 条管道、内嵌
python3 -c/node -e、复杂的jq转换、嵌套循环、复杂字符串处理——切换到language: python或language: javascript。Bash 里的内联 Python/Node 本身就是"用错语言"的信号。 - 输出小于约 20 行——直接用 Bash 白名单命令(
git status、ls -la、pwd等),ctx_execute的 LLM 摘要开销反而浪费;Bash 白名单只涵盖文件变更、git 写操作、导航、进程控制、包安装和echo,见 SKILL.md。 - 脚本必须打印结果:stdout 是唯一进入上下文的内容,只计算不 print 等于白跑一次调用(anti-patterns 第 2 条)。
- 不要把大文件读进上下文再分析:日志、lockfile、JSON 超过约 200 行且只需取特定数据时,一律在
ctx_execute内处理并只输出结论(anti-patterns 第 4 条)。 ctx_execute负责捕获、ctx_search负责过滤,两者是分层不是替代:不要在ctx_execute内部提前head截断——那会丢掉索引层本该看到的数据(anti-patterns 第 8 条)。上述所有模式里的head都是对"已打印分析结果"的行数限制,而非对捕获数据的截断。
最佳实践清单
把上述模式收敛为一份可复用的 checklist(对照 anti-patterns.md 的 Summary Checklist):
- 预估输出会超过约 20 行 → 用
ctx_execute(shell),否则用 Bash; - 命令输出经过管道时用
${PIPESTATUS[0]}取真实退出码,而不是$?; - 脚本必须以
echo/print输出结构化结论结尾,禁止只算不打印; - 对象、数组、结构化数据用可读表格或
JSON.stringify/json.dumps序列化; - 网络请求给 15s–60s、构建/测试套件给 120s–300s 的
timeout_ms,文件解析给 5s–10s; - 语言匹配任务:JS 管 JSON/API,Python 管数据分析,Shell 管管道/文件模式匹配;
summary_prompt具体化:要求计数、文件路径、错误码聚合、可行动建议;- 需要二次查询的数据先落盘再交给
ctx_index(path)索引,不要用ctx_index(content:)塞回上下文。
相关参考:
- Shell Patterns
- JavaScript/TypeScript Patterns
- Python Patterns
- Anti-Patterns & Common Mistakes
- 执行器实现:src/executor.ts、运行时探测:src/runtime.ts
【免费下载链接】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),仅供参考