DEV Community

韩

Posted on

Crush 的 5 个隐藏用法:25K Star 的 Charm 终端 AI Agent 在配置卫生上完胜 Claude Code

你知道吗?Charm 团队在 Hacker News 上首发"终端里最迷人的 AI 编码代理"时,那条帖子一天就冲到 367 分、235 条评论。将近一年后,这个仓库已经积累到 25,233 个 GitHub Stars 和 1,805 个 Forks,最近一次提交是 2026 年 6 月 12 日。可是当大多数工程师第一次打开 Crush 的时候,用法跟 Claude Code 没什么两样——聊一聊、改一改、再聊一聊。README 又长又全,但真正好用的生产功能,全藏在配置文件、LSP 接线、MCP 配置和那一小撮不起眼的 flag 里。

charmbracelet/crush 是 Charm 生态(bubbletealipglossglow 都出自这个团队,他们的基础库支撑了大约 25,000 个下游 Go 应用)出品的代理化终端工具。它原生支持 OpenAI 和 Anthropic,自带三种 MCP 传输协议,同一份二进制在 macOS、Linux、Windows(PowerShell + WSL)、Android、FreeBSD、OpenBSD、NetBSD 都能跑。大多数用户看到的就是"又一个终端 AI"。其实它更像是一个可编程的代理运行时,有自己的小配置语言。

下面这五个隐藏用法,把 Crush 从"我的第二个编码 Agent"变成了我留在顶层的那个。

隐藏用法 #1:crush.json 里的 Shell 风格密钥展开

大多数人的用法: 直接把 API Key 粘贴到 crush.json 里(然后第一次提交进 git 就后悔了)。

隐藏技巧: Crush 自带一个兼容 bash 的展开引擎,会在 MCP、provider、LSP 配置的 commandargsenvheadersurl 字段上跑一遍。这意味着你可以用 $VAR${VAR:-default}$(command),甚至 ${VAR:?message}——最后一个是大多数人没注意到的杀手锏。必需的凭据一旦缺失就在加载时大声报错,绝不会悄悄变成空字符串。

{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": {
        "Authorization": "Bearer ${GH_PAT:?请先在 shell 里设置 GH_PAT}"
      },
      "timeout": 120
    },
    "filesystem": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/mcp-server.js"],
      "env": {
        "NODE_ENV": "production",
        "TOKEN_FILE": "$(cat /run/secrets/mcp-token)"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

效果: 解析后值为空字符串的 header 会被 Crush 从请求里整个删掉,而不是发出 Authorization: Bearer 这种空值。这意味着类似 OpenAI-Organization 这种可选的、依赖环境变量的 header 在未设置时不会污染请求;必需的凭据则在 TUI 还没渲染之前就给出明确的报错。

数据来源: Crush 25,233 Stars / 1,805 Forks(GitHub REST API 验证,最近一次 push 2026-06-12)。HN 发布主帖 367 pts / 235 comments(objectID 44736176,2025-07-30)。

隐藏用法 #2:跨多个 TUI 客户端的共享工作区

大多数人的用法: 开一个 Crush 窗口,任务结束,关掉,会话也没了。

隐藏技巧: 运行 crush serve 暴露 HTTP 后端,再用 --cwd多个 TUI 客户端附加到同一个工作区。指向相同工作目录的两个客户端会加入同一个底层工作区——共享会话列表、消息历史、权限队列、LSP 服务池和 MCP 连接。会话选择器暴露两个信号:IsBusy(代理正在跑一轮)和 AttachedClients(当前有多少个终端在看着同一个会话)。

# 终端 A:启动一次长时间重构,然后挂后台
crush serve --cwd ~/code/monolith --yolo

# 终端 B:实时围观同一个工作区
crush --cwd ~/code/monolith

# 终端 C,笔记本 SSH 进来:还是同一个工作区
crush --cwd ~/code/monolith
Enter fullscreen mode Exit fullscreen mode

效果: AttachedClients 不为零就是"这个会话在另一个客户端上正在跑"的提示。最先创建工作区的那个客户端固定了进程级 flag——尤其是 --yolo--debug 遵循先到先得原则:后续客户端想用更宽松的设置是不被接受的。工作区的生命周期与任何一个客户端保持 SSE 流连接的时间一致;最后一个流断开时,工作区被销毁,但有一个短暂的宽限窗口,避免"刚创建还没来得及接入"的客户端被立刻回收。

数据来源: Crush README "Sharing a workspace across clients" 章节,宽限窗口与 first-wins flag 规则与官方文档一致。

隐藏用法 #3:带 user-invocabledisable-model-invocation 的 Agent Skills

大多数人的用法: 觉得 skill 文档读起来像插件市场,直接跳过。

隐藏技巧: Crush 支持开放的 Agent Skills 标准(agentskills.io),默认从七个全局路径三个项目相对路径自动发现 skill——这还没算上你自定义的 options.skills_paths。真正的好戏是两个 frontmatter 标记:

---
name: crush-config
description: "一个可以通过命令面板手动触发的 skill"
user-invocable: true
disable-model-invocation: true
---

# 引导用户完成 crush.json 的编辑流程
Enter fullscreen mode Exit fullscreen mode

设置 user-invocable: true 之后,skill 会在命令面板(Ctrl+P)里以 user:skill-nameproject:skill-name 的形式出现。再设上 disable-model-invocation: true,这个 skill 对模型完全隐身,但人可以随时手动调起来。Crush 自带的 crush-config skill 用的就是这个套路——模型永远不会自动触发它,但用户按 Ctrl+P 输入 "config" 就能让 Agent 引导自己完成配置。

# 用 anthropics/skills 当起点,把示例 skill 装到本地
mkdir -p ~/.config/crush/skills
cd ~/.config/crush/skills
git clone https://github.com/anthropics/skills.git _temp
mv _temp/skills/* . && rm -rf _temp
Enter fullscreen mode Exit fullscreen mode

效果: 干净地分离了人主动调用的工作流(部署、改配置、清理)和模型主动触发的 skill(调研、重构、代码检索)。模型不可能误触发危险 skill,但人随时可以召唤。

数据来源: Crush README "Agent Skills" 章节,七个全局路径 + 三个项目相对路径与源码一致。agentskills.io 开放标准在 README 中明确引用。

隐藏用法 #4:自定义 Anthropic 兼容 Provider 与每模型成本元数据

大多数人的用法: 用内置预设 Provider,从不动 providers 字段。

隐藏技巧: Crush 支持两种自定义 Provider 写法——openai-compat 给那些走 OpenAI 接口形态但不是 OpenAI 的服务(Deepseek、Groq、Together、Fireworks),anthropic 给 Anthropic 兼容端点(代理、内部集群、自定义 base URL)。真正没写在文档里的彩蛋是每模型的元数据字段——cost_per_1m_incost_per_1m_outcost_per_1m_in_cachedcost_per_1m_out_cachedcontext_windowdefault_max_tokenscan_reasonsupports_attachments。这些不只是装饰:TUI 用它们在每次请求时显示真实成本估算。

{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "deepseek": {
      "type": "openai-compat",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "$DEEPSEEK_API_KEY",
      "models": [
        {
          "id": "deepseek-chat",
          "name": "Deepseek V3",
          "cost_per_1m_in": 0.27,
          "cost_per_1m_out": 1.1,
          "cost_per_1m_in_cached": 0.07,
          "context_window": 64000,
          "default_max_tokens": 5000
        }
      ]
    },
    "custom-anthropic": {
      "type": "anthropic",
      "base_url": "https://api.your-proxy.internal/v1",
      "api_key": "$INTERNAL_ANTHROPIC_KEY",
      "extra_headers": {
        "anthropic-version": "2023-06-01",
        "X-Tenant-Id": "$TENANT_ID"
      },
      "models": [
        {
          "id": "claude-sonnet-4-20250514",
          "name": "Claude Sonnet 4",
          "cost_per_1m_in": 3,
          "cost_per_1m_out": 15,
          "context_window": 200000,
          "default_max_tokens": 50000,
          "can_reason": true,
          "supports_attachments": true
        }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

效果: extra_body不展开的 JSON 透传(用来塞静态字段),但 extra_headersapi_keybase_url 都会走 shell 展开引擎。这意味着你可以在团队里只分发一份 crush.json,每位工程师通过环境变量覆盖自己的凭据;TUI 能显示真实成本,因为元数据写在配置里、不是硬编码。

数据来源: Crush README "Custom Providers" 章节,Deepseek 示例配置与官方 README 一致。Provider 总数(25+,包括 OpenAI、Anthropic、Google、Groq、OpenRouter、Vercel、MiniMax、Z.ai、Cerebras、Hugging Face、AWS Bedrock、Azure OpenAI 等)通过 README 的环境变量表交叉验证。

隐藏用法 #5:分层工具与 Skill 隔离(.crushignore + disabled_tools + disabled_skills

大多数人的用法: 启动时加 --yolo 听天由命,或者每次权限弹窗都手动点。

隐藏技巧: Crush 给了你三层独立的隔离机制,可以叠加使用:

  1. .crushignore——gitignore 语法的文件,文件根本进不到 Crush 的上下文(不只是禁止编辑,连读都不读)。
  2. options.disabled_tools——对代理完全隐藏内置工具(比如 "bash""sourcegraph")。模型看不到的工具就没法选。
  3. options.disabled_skills——对代理隐藏 skill(内置和发现的都算)。再叠加 skill 自己的 frontmatter 里的 disable-model-invocation 可以做到单个 skill 级别的隐身。
  4. permissions.allowed_tools——反方向的白名单。只有列出来的工具能跑,其他都需要弹窗。
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disabled_tools": ["bash"],
    "disabled_skills": ["crush-config"],
    "skills_paths": [
      "~/.config/crush/skills",
      "./project-skills"
    ]
  },
  "permissions": {
    "allowed_tools": [
      "view",
      "ls",
      "grep",
      "edit",
      "mcp_context7_get-library-doc"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode
# .crushignore —— 凭据、构建产物、大数据文件
.env
.env.*
secrets/
*.pem
node_modules/
dist/
*.parquet
data/raw/
Enter fullscreen mode Exit fullscreen mode

效果: 你可以给团队部署一份"禁用 bash(所有 shell 操作强制走 MCP 工具)、隐藏某些 skill(模型重构时不会自作主张触发 crush-config)、只读工具白名单"的 Crush。.crushignore.gitignore 用一样的语法并叠加生效——已经提交进仓库但不想让代理碰的文件,git 留底、Crush 看不见。这是把 Crush 跑在面向客户的内部工具里时,团队实际在用的配置模式。

数据来源: Crush README 的 "Ignoring Files"、"Allowing Tools"、"Disabling Built-In Tools"、"Disabling Skills" 四个章节,四种机制均与官方文档行为一致。

总结:五个隐藏用法

  1. Shell 风格密钥展开${VAR:?msg}$(command),必需凭据零容忍。
  2. 共享工作区crush serve + --cwd 键值,多 TUI 客户端同步会话。
  3. Agent Skillsuser-invocabledisable-model-invocation 配合,分离"人触发"和"模型触发"两种工作流。
  4. 自定义 Anthropic/OpenAI Provider:每模型成本元数据 + extra_body 透传。
  5. 分层隔离.crushignore + disabled_tools + disabled_skills + allowed_tools 四重保险。

相关阅读

你那边呢——crush.json 里有没有哪个 flag 是你早该知道、早用早舒服的?评论区丢出来,Charm 团队在看,得票最高的几个建议大概率会进下个版本。

Top comments (0)