版本 0.11.0 已发布:crates.io / GitHub Releases / Homebrew / npm 四平台同步。
几个月前我开始做一个 Rust 项目:在把日志、命令输出、diff、堆栈喂给 LLM 之前,把该留的留下,该删的删掉,而且一个字都不改。到 0.11.0 算是把设计、评测、发布全闭环了,写一篇把关键决策和数据摊开讲。
问题
排查问题时的经典场景:some-noisy-command > /tmp/out.log 2>&1,然后要么硬塞进上下文(贵、关键行被淹没),要么交给通用摘要(改写原文,不敢信),要么随机抽样(可能恰好丢掉根因),要么向量检索(不适合逐行保留原始证据)。
scx 的约束:先证据,后预算
核心是一条纪律:
只删整行,不改写原文;证据行及其最小邻域无条件保留,预算只能约束可选内容。
query + input
├─ 1. IDF 加权词面命中,确定证据行
├─ 2. 证据行及其 ±context 邻域无条件保留
├─ 3. 只在种子邻域内用剩余预算填充可选行
├─ 4. --max-tokens 硬上限:证据地板优先,超限如实报告
└─ 5. 输出原文行子集与统计,不重写、不截断
--query "database timeout connection pool" --ratio 0.35→ 命中的行保住,噪声裁掉,输出带原始行号--force "re:ERROR|FATAL"→ 强制保留,支持一个手写的有限正则子集(Thompson NFA,无回溯灾难)--max-tokens 2000→ 硬 token 上限,超限报overflow:evidence/overflow:fill,绝不静默丢证据
为什么零依赖
第三方 crate 数量是 0。不是偷懒,是把「确定性」当契约:
- JSON parser:手写,MCP server 和
--json统计共用 - TOML 子集:策略文件
--policy-file用 - SHA-256:可选语义打分的权重指纹校验
- 正则子集:
re:前缀进 Thompson NFA
--locked 离线可构建。压缩主链无网络请求、无随机源、无运行时依赖——同输入同查询同配置,输出逐字节一致。37 个 golden 用例对 stdout/stderr/退出码做逐字节差分,这是每次变更的硬红线。
数据
作者侧自测(Apple M5 Pro,非第三方评测,口径都写进了文档):
| 工作负载 | 结果 |
|---|---|
| 5 万行 / 233 万字符日志压缩 | 中位 11.7–12.0 ms |
| 187 万字符 / 5.2 万行 | 无损 ~50 ms,压 61.5%;--ratio 0.3 → 75.4%,0.2 → 77.9% |
| 证据保留(70 条证据行) | 70/70 = 100%(截断基线 0/70),默认档压减约 82% |
| Hard 层 MRR@10 vs 词面基线 | +0.0669(paired bootstrap 95% CI [0.0238, 0.1176],p=0.0020) |
代码规模:约 4.9 万行纯 Rust / 96 文件,554 个 #[test],注释占比约 7%。评测门禁 xtask ops check 全绿。
对 Agent 工作流的集成
同二进制内置 MCP stdio server(零依赖):
scx setup # 一键注册 Claude / Codex / Cursor(幂等 + 写前备份 + tools/list 自检)
scx mcp # 手动进入 stdio server 模式
npx -y @spapient/scx # npm 装,兼容千问办公的 MCP 接入
安装
# crates.io
cargo install scx
# macOS Homebrew
brew tap spapient/scx && brew install scx
# npm(含 MCP 入口)
npx -y @spapient/scx
边界(说清楚,不吹)
- 词面相关优先:查询零共享词时 fail-open 回退原文,不承诺 embedding 级语义检索
- 压缩率有地板:证据优先的语义决定了输出存在下限,
--ratio不是硬性字符上限 - 非幂等:对已压缩文本再压缩会继续裁减(级联退化)——累积场景必须对原始文本全量重压缩
- pre-1.0:CLI 和接口仍可能演进,生产集成建议固定 commit
有真实场景(排障、长代码问答、agent 上下文治理)的朋友欢迎试用、提 issue 或拍砖。