面向终端密集型 Agent 工作流的确定性输出压缩工具,通过规则驱动的 Reducer 减少 LLM 上下文浪费。

概述

tokenjuice 是 Vincent Koc 开发的 CLI 工具,当前版本 v0.7.1(2026-05-17)。

核心思路:Agent 运行 git status、pnpm test、docker build、rg 等命令时会产生大量终端噪音输出,tokenjuice 在命令执行后观察输出,用规则驱动的 Reducer 返回压缩后的精简 payload,而不是把整面墙的终端文本塞回上下文。

关键设计原则:

  • 命令语义不变,只压缩输出
  • 规则是可检查的 JSON,不是 LLM 黑盒
  • 原始输出通过 --raw / --full 显式获取
  • Host 集成是薄包装,不是一次性适配器逻辑

安装

npm install -g tokenjuice
# 或
brew tap vincentkoc/tap && brew install tokenjuice

核心命令

tokenjuice reduce [file]          # 压缩已有文本
tokenjuice reduce-json [file]     # 机器协议(JSON in → JSON out)
tokenjuice wrap -- <command>      # 运行命令并压缩输出
tokenjuice wrap --raw -- <cmd>    # 运行命令但保留原始输出
tokenjuice wrap --store -- <cmd>  # 运行命令并存储 artifact
 
tokenjuice install claude-code    # 安装 Claude Code 集成
tokenjuice doctor hooks           # 检查所有已安装的 hook
tokenjuice stats                  # 查看压缩统计
tokenjuice ls                     # 列出存储的 artifacts

支持的 Host 集成(18 个)

正式支持:

Host安装方式Hook 文件
Claude Codetokenjuice install claude-code~/.claude/settings.json
OpenClawopenclaw config set plugins.entries.tokenjuice.enabled true~/.openclaw/openclaw.json
Cursortokenjuice install cursor~/.cursor/hooks.json
Codex CLItokenjuice install codex~/.codex/hooks.json
GitHub Copilot CLItokenjuice install copilot-cli~/.copilot/hooks/
VS Code Copilottokenjuice install vscode-copilot~/.copilot/hooks/
OpenCodetokenjuice install opencode~/.config/opencode/plugins/
CodeBuddytokenjuice install codebuddy~/.codebuddy/settings.json
Droid (Factory)tokenjuice install droid~/.factory/settings.json
pitokenjuice install pi~/.pi/agent/extensions/

Beta 支持:Aider、Avante.nvim、Cline、Continue、Gemini CLI、Junie、OpenHands、Zed

OpenClaw 集成内置在 OpenClaw 侧,需要 OpenClaw 2026.4.22+,不要运行 tokenjuice install openclaw。

规则引擎

规则是 JSON 文件,按三层优先级加载:

  1. src/rules/ — 内置规则(按命令类型分类)
  2. ~/.config/tokenjuice/rules/ — 用户全局覆盖
  3. .tokenjuice/rules/ — 项目级覆盖

内置规则覆盖 23 个类别:git、tests、package、lint、build、cloud、database、devops、filesystem、network、observability、search、system 等。

规则功能:分类命令输出、规范化行、保留/丢弃模式、统计事实、保留确定性的 head/tail 切片。

Adapter JSON 协议

reduce-json 是机器接口,stdin/stdout 均为 JSON:

{
  "toolName": "exec",
  "command": "pnpm test",
  "argv": ["pnpm", "test"],
  "combinedText": "RUN  v3.2.4 /repo\n...",
  "exitCode": 1
}

示例讲解

示例 1:git status 压缩(最典型场景)

规则文件:src/rules/git/status.json

{
  "id": "git/status",
  "family": "git-status",
  "match": {
    "argv0": ["git"],
    "argvIncludes": [["status"]]
  },
  "transforms": {
    "stripAnsi": true,
    "dedupeAdjacent": true,
    "trimEmptyEdges": true
  },
  "filters": {
    "skipPatterns": [
      "^On branch ",
      "^Your branch is ",
      "^\\(use \"git .+\" to .+\\)$",
      "^nothing to commit, working tree clean$"
    ]
  },
  "summarize": { "head": 10, "tail": 4 },
  "failure": { "preserveOnFailure": true, "head": 12, "tail": 12 },
  "counters": [
    { "name": "modified file", "pattern": "^(?:M:|\\s*modified:)" },
    { "name": "new file",      "pattern": "^(?:A:|\\s*new file:)" },
    { "name": "deleted file",  "pattern": "^(?:D:|\\s*deleted:)" },
    { "name": "untracked file","pattern": "^(?:\\?\\?:|\\?\\?\\s+)" }
  ]
}

压缩效果(来自 src/rules/fixtures/git/status.fixture.json):

原始输出:

On branch main
Changes not staged for commit:
  modified: src/index.ts

Untracked files:
  test/new.test.ts

压缩后(On branch main 被 skipPatterns 过滤掉,counters 统计文件数):

Changes not staged for commit:
  modified: src/index.ts

Untracked files:
  test/new.test.ts
[1 modified file, 1 untracked file]

示例 2:generic/fallback 兜底规则

规则文件:src/rules/generic/fallback.json

{
  "id": "generic/fallback",
  "family": "generic",
  "match": {},
  "transforms": { "stripAnsi": true, "dedupeAdjacent": true, "trimEmptyEdges": true },
  "summarize": { "head": 8, "tail": 8 },
  "failure": { "preserveOnFailure": true, "head": 12, "tail": 20 },
  "counters": [
    { "name": "error",   "pattern": "error",   "flags": "i" },
    { "name": "warning", "pattern": "warning", "flags": "i" }
  ]
}

match: {} 表示匹配所有命令,是最低优先级的兜底。成功时只保留前 8 行 + 后 8 行,失败时保留前 12 行 + 后 20 行(失败时保留更多上下文)。

fixture 示例(src/rules/fixtures/generic/fallback.fixture.json):

{
  "input": { "command": "custom-tool check", "combinedText": "custom line one\ncustom line two\n", "exitCode": 0 },
  "expect": { "matchedReducer": "generic/fallback", "contains": ["custom line one"] }
}

示例 3:测试输出压缩(多语言)

tokenjuice 对主流测试框架都有专用规则,失败时保留关键错误行。

Go 测试(src/rules/fixtures/tests/go-test.fixture.json):

{
  "input": {
    "command": "go test ./...",
    "combinedText": "ok  github.com/example/pkg 0.012s\nFAIL github.com/example/api 0.021s\n",
    "exitCode": 1
  },
  "expect": { "matchedReducer": "tests/go-test", "contains": ["FAIL github.com/example/api"] }
}

Cargo 测试(src/rules/fixtures/tests/cargo-test.fixture.json):

{
  "input": {
    "command": "cargo test",
    "combinedText": "running 2 tests\ntest a ... ok\ntest b ... FAILED\nfailures:\n    b\n",
    "exitCode": 101
  },
  "expect": { "matchedReducer": "tests/cargo-test", "contains": ["FAILED"] }
}

示例 4:reduce-json 机器协议(Host Adapter 接入方式)

Host Adapter 通过 reduce-json 与 tokenjuice 通信,stdin/stdout 均为 JSON:

# 将工具执行结果 JSON 传入,得到压缩后的 JSON
cat payload.json | tokenjuice reduce-json

输入 payload(ToolExecutionInput 格式):

{
  "toolName": "exec",
  "command": "git diff --stat",
  "argv": ["git", "diff", "--stat"],
  "combinedText": " src/index.ts | 4 ++--\n test/core/reduce.test.ts | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n",
  "exitCode": 0
}

匹配规则 git/diff-stat,输出保留 2 files changed, 3 insertions(+), 3 deletions(-) 摘要行。


示例 5:自定义规则覆盖

在项目根目录创建 .tokenjuice/rules/my-tool.json,覆盖或新增规则:

{
  "id": "my-tool/check",
  "family": "my-tool",
  "match": {
    "argv0": ["my-tool"],
    "argvIncludes": [["check"]]
  },
  "transforms": { "stripAnsi": true, "trimEmptyEdges": true },
  "filters": {
    "skipPatterns": ["^\\[INFO\\]", "^Scanning "]
  },
  "summarize": { "head": 5, "tail": 5 },
  "failure": { "preserveOnFailure": true, "head": 20, "tail": 20 }
}

规则优先级:项目级 > 用户级 > 内置,通过 id 字段覆盖。验证规则:

tokenjuice verify          # 检查 JSON 格式 + schema + 正则编译
tokenjuice verify --fixtures  # 同时跑 fixture 测试

示例 6:Claude Code 集成原理

安装后,tokenjuice 在 ~/.claude/settings.json 注入 PreToolUse hook:

tokenjuice install claude-code

Hook 工作方式:在 Claude Code 执行 Bash 命令前,将命令重写为 tokenjuice wrap -- <原命令>,这样命令输出在返回给 Claude 之前已经被压缩。使用 --raw 可绕过压缩:

tokenjuice wrap --raw -- cat src/index.ts   # 精确文件读取,不压缩
tokenjuice wrap -- pnpm test                # 测试输出,压缩后返回

安全策略

Host 适配器应用窄安全策略:

  • 精确文件内容读取 → 保持原始(不压缩)
  • 独立仓库清单命令 → 可压缩
  • 不安全的混合命令序列 → 保持原始

相关链接

关联页面