先建立坐标系:Charm 是谁,它为什么下场做 agent

charmbracelet(Charm)是终端圈最出名的 TUI 基础设施公司:Bubble Tea(Go 的 TUI 框架)、Lip Gloss(终端样式)、Glow(终端 Markdown)、Gum(shell 脚本里的 TUI 命令)全是它家的,README 自称「powering 25k+ applications」。crush 是它 2025 年 5 月下场做的 coding agent,口号是「Glamourous agentic coding for all 💘」——注意,这不是随便一个 vibe-coding 玩具:它是 Charm 认真押注的产品线,配套还养了一个自己的模型订阅服务 Hyper 和一个社区模型数据库 Catwalk。

跟工坊最近几篇的主角比,crush 的定位差异很明显:Gajae-Code 是「订阅 OAuth 外挂」,OpenClaude 是「Claude Code 改多后端」,MiMoCode 是「厂商闭环」——而 crush 是「老牌 TUI 厂把 agent 当成自家生态的旗舰应用来做」:模型自由(40+ provider)、配置即代码(crushrc)、LSP 一等公民、MCP 内置 OAuth。它不追求「某个模型调得最好」,追求「任何模型都能在终端里用得很顺」。血统纯正(Charm 出品)、迭代凶猛(nightly 日更、v0.90 → v0.91 三天一版)、但 669 个 open issues 也说明还在高速打磨期。

核心机制一:crushrc = 可执行 Bash——配置不是 JSON,是「带内置命令的 shell 脚本」

这是 crush 最反直觉也最 Charm 的设计:配置文件 crushrc 本质是 Bash,只是塞了一堆 Crush 内置命令(provider add / model add / mcp add / lsp add / permissions allow|deny / option)。因为 Crush 自带一个原生 Bash 解释器,同一份配置在 macOS / Linux / Windows 上行为完全一致。优先级从项目到全局:./.crushrc → ./crushrc → ~/.config/crush/crushrc(XDG)。

# crushrc 示例:加 Ollama、注册模型、放行工具、条件分支、加 MCP
provider add ollama --type ollama --base-url "http://localhost:11434/v1"
model add ollama/llama3.3 --name "Llama 3.3" --context-window 128000
permissions allow view edit            # 免审批放行只读工具
if [[ $HOSTNAME == "babysquid" ]]; then
    source ~/my-stuff/babysquid.sh    # 真·shell,条件分支随便写
fi
mcp add github --type http --url "https://api.githubcopilot.com/mcp/" \
  --header Authorization "Bearer $(op read 'op://my-secret-key')"

配置即代码的代价是安全面:README 自己用黑体警告——「crushrc 和 crush.json 都是 trusted code;crushrc 跑在完整 shell 里,crush.json 里任何 $(...) 都会在加载时执行」。也就是说,在没审过的目录里启动 crush,等于把 shell 执行权交给了那个目录的配置。别随便 clone 一个带 crushrc 的仓库就进去跑 agent。旧 JSON 格式(crush.json)仍支持但已标记 deprecated。

核心机制二:模型自由——40 家 provider、1,547 个模型、每天自动更新,外加自家订阅 Hyper

crush 的模型目录是「外置数据库」:启动时从 Catwalk(Charm 的社区模型仓库,789 Star)拉最新的 provider 和模型清单,自动写进本机配置。实测我第一次跑完,~/.local/share/crush/providers.json 里就有 40 家 provider、1,547 个模型——Anthropic / OpenAI / Gemini / DeepSeek / Groq / OpenRouter / Bedrock / Vertex / Kimi / GLM / MiniMax 全在,crush models 能直接列。想离线或固定版本:crush update-providers embedded 重置到内置清单,option provider-auto-update false 关自动更新。

两个值得记住的细节:

Charm 还养了自己的模型订阅 Hyper:免费层 $0/月送 100 Hypercredits(1 credit = 5¢),订阅 $20/月拿 250 credits 每日刷新,主打零数据留存(ZDR)+ GDPR。有意思的是实测落盘的 hyper.json:Hyper 的默认大模型是 qwen3.7-plus、小模型是 deepseek-v4-flash-0731——Charm 自己不做模型,订阅背后路由的是开源/三方模型,跟它「coding-optimized open source models」的定位一致。

核心机制三:26 个工具的武器库,8 个 LSP 工具是一等公民——扒包实测

我用自定义 provider 指向本地 mock 服务跑通全链路后,把 crush 真实发出的请求扒了出来,信息量很大。先看工具面——默认 26 个工具:

类别工具
LSP(8 个)lsp_definition · lsp_references · lsp_diagnostics · lsp_symbols · lsp_rename · lsp_replace_symbol · lsp_call_hierarchy · lsp_restart
文件/代码view · edit · multiedit · write · glob · grep · ls
执行bash · job_kill · job_output(后台任务)
检索fetch · agentic_fetch · download · sourcegraph(公网代码搜索)
编排agent(子代理)· todos(任务清单)· crush_info · crush_logs

8 个 lsp_* 工具是 crush 最跟别人不一样的地方——「agent 像你一样用 LSP 看代码」,定义/引用/诊断/重命名全走语言服务器而不是正则硬猜。搭配 sourcegraph 内置公网代码搜索和 agent 子代理,这是个「IDE 级上下文 + 子代理并行」的配置。

请求体还暴露了几个值得知道的事实:

核心机制四:MCP 内置 OAuth、Agent Skills 通吃各家目录、hooks 目前只有一个

MCP 支持 stdio / http / sse 三种传输,亮点是内置 OAuth 授权码流程:"oauth": true 就自动走 RFC 7591 动态客户端注册(Linear、Notion 这类直接可用),不支持动态注册的(GitHub、Slack)可以预注册 OAuth app 填 oauth_client_id/secret。实测项目里 mcp add 的 GitHub Copilot MCP 一行配置就带上了 Bearer $(op read ...) 的 shell 展开。

Agent Skills 走 agentskills.io 开放标准,发现目录覆盖得比谁都全:全局扫 ~/.config/agents/skills、~/.config/crush/skills、~/.agents/skills、~/.claude/skills(Windows 还有对应路径),项目里扫 .agents/skills、.crush/skills、.claude/skills、.cursor/skills——你给别的 agent 装的技能,crush 开机就能用。全局上下文文件也分两档:~/.config/crush/CRUSH.md(自家规则)+ ~/.config/AGENTS.md(跨工具通用规则)。

hooks 就寒酸了:目前只有 PreToolUse 一个事件(Claude Code 兼容格式,JSON 配置 + shell 脚本,可拦截/改写/注入/自动批准),README 明说「plans to support the full gamut」。想拿 hooks 做 git push 拦截之类的事,现在只能拦工具调用这一层。

上手:我在沙箱实测跑通的命令(含 mock 全链路验证)

Ubuntu 无头沙箱。全链路:下载 release 二进制 → 版本 → 命令面 → 无 key 裸跑 → 自定义 provider + 本地 mock(流式 SSE)→ 工具循环 → 坏 key → 会话管理,都走了一遍。

# 1) 安装(三选一;本文实测走 release 二进制)
brew install charmbracelet/tap/crush          # macOS
npm install -g @charmland/crush               # 跨平台
# 或下载 crush_0.91.0_Linux_x86_64.tar.gz(28.6MB → crush 单文件 94MB,sha256 校验通过)
crush --version                               # crush version v0.91.0

# 2) 无 key 裸跑(报错友好,exit 1)
crush run "say hi"
# ERROR: No providers configured - please run 'crush' to set up a provider interactively.

# 3) crushrc 配 DeepSeek(README 原样,openai-compat 类型)
provider add deepseek --type openai-compat \
  --base-url "https://api.deepseek.com/v1" --api-key "$DEEPSEEK_API_KEY"
model add deepseek/deepseek-chat --name "Deepseek V3" \
  --context-window 64000 --default-max-tokens 5000 \
  --price-input 0.27 --price-output 1.1

# 4) 自定义 provider + 本地 mock 全链路(流式 SSE 正常)
provider add mock --type openai-compat --base-url "http://127.0.0.1:9999/v1" --api-key "mock-key-123"
model add mock/mock-chat --name "Mock Chat" --context-window 128000 --default-max-tokens 2000
crush run -m mock/mock-chat "用一句话介绍你自己"    # → 你好,我是 mock。流式响应。exit 0

# 5) 工具循环实测:mock 让模型发 ls 工具调用,crush 真在本地执行
#    第二次请求里出现 roles=[system,user,user,assistant,tool],tool_result 是 /tmp/ws 真实目录树

# 6) 坏 key(mock 返回 401):报错清晰、exit 1,但失败后仍多发 2 次标题请求
crush run -m mockbad/mock-chat "hi"
# ERROR: Agent processing failed: ... unauthorized: Incorrect API key provided

# 7) 会话管理
crush session list --json        # 每条含 id/title/created/cost/prompt_tokens/completion_tokens
crush session show <id> --json    # 消息带 finish reason:end_turn / error / stop
crush run --continue "第二句"      # 续最近一次会话(注意:不看成败)
crush logs --follow               # ./.crush/logs/crush.log
crush stats                       # 生成 .crush/stats/index.html(headless 下打不开浏览器)

数据落盘结构也摸清了:全局在 ~/.local/share/crush/(providers.json 40 家 provider 全量、hyper.json、projects.json),每个项目一个 .crush/ 目录(SQLite crush.db + logs/crush.log + stats/index.html),会话、日志、统计全部按项目隔离。多客户端共享靠 crush server + 按 --cwd 归组 workspace,会话列表里 IsBusy / AttachedClients 两个信号能看出「这个会话另一个客户端正在看」。

对比:同赛道里的站位

维度CrushClaude CodeOpenCode
血统Charm(Bubble Tea 母公司)Anthropic 官方anomalyco(社区)
语言 / 体量Go 单二进制 94MB专有(npm/原生)TypeScript / npm
许可证⚠️ FSL-1.1-MIT(source-available,两年后转 MIT,期间禁止竞争性商用)❌ 专有✅ MIT
模型接入✅ 40 provider / 1,547 模型目录自动更新 + 本地自动发现⚠️ 订阅或 API⚠️ 多后端需自配
LSP✅ 8 个 lsp_* 工具一等公民⚠️ 弱(靠 grep)✅ 支持
MCP✅ stdio/http/sse + 内置 OAuth 授权码流程✅ 支持✅ 支持
配置crushrc(可执行 Bash + 内置命令)CLAUDE.md 指令JSON / TS 配置
非交互✅ crush run + stdin 管道 + --session✅ -p 打印模式✅ run 命令
遥测⚠️ PostHog 伪匿名,可关(CRUSH_DISABLE_METRICS / DO_NOT_TRACK)⚠️ 有✅ 默认无
Star(2026-08-26)27,677142,962201,287

一句话定位:Claude Code 是「官方模型 + 官方工具」,OpenCode 是「社区最开放的多后端」,crush 是「TUI 老厂把 agent 做成自家生态旗舰」——配置最 Geek(crushrc 可执行)、LSP 集成最深、模型目录最省心,但许可证最拧巴(FSL)。

实测与踩坑:6 个坑,前两个最要命

值不值得装:三个场景对号入座

最后说句公道话:27.7K Star 里没有 Star 通胀的味道(Charm 是十几年老厂,贡献者、release、文档都是真的),669 个 open issues 说明它还在高速打磨期——sql: database is closed 这种竞态就是例证。它跟工坊写过的 OpenClaude(Claude Code 改多后端)方向不同:OpenClaude 是「换引擎」,crush 是「自建整车 + 自家订阅 + 社区模型库」。FSL-1.1-MIT,仓库 github.com/charmbracelet/crush,安装 brew install charmbracelet/tap/crush 或 npm i -g @charmland/crush。「Glamourous agentic coding for all」——好看是真的,坑也是真的。