Doramagic 项目包 · 项目说明书

crush 项目

生成时间:2026-05-31 04:01:54 UTC

项目概览

Crush 是由 Charm 开发的终端编程助手,能够将你的工具、代码和工作流无缝接入你选择的 LLM 模型。它支持多模型切换、内置多种开发工具、Hooks 机制、LSP 语言服务器集成以及 MCP(Model Context Protocol)协议扩展。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 多模型支持

继续阅读本节完整说明和来源证据。

章节 工具系统

继续阅读本节完整说明和来源证据。

章节 LSP 集成

继续阅读本节完整说明和来源证据。

简介

Crush 是由 Charm 开发的终端编程助手,能够将你的工具、代码和工作流无缝接入你选择的 LLM 模型。它支持多模型切换、内置多种开发工具、Hooks 机制、LSP 语言服务器集成以及 MCP(Model Context Protocol)协议扩展。

资料来源:README.md:1-8

核心功能

多模型支持

Crush 支持从广泛的 LLM 中选择使用,也可以通过 OpenAI 或 Anthropic 兼容 API 添加自定义提供商。

功能类别支持类型
云端 APIOpenAI、Anthropic、DeepSeek、Google Gemini 等
自托管通过 OpenAI-compatible 或 Anthropic-compatible 接口
订阅服务Synthetic、GLM Coding Plan、Kimi Code、MiniMax Coding Plan

资料来源:README.md:89-130

工具系统

Crush 提供丰富的内置工具集,包括:

  • Bash 工具:执行命令行操作
  • Glob 工具:文件模式匹配
  • Grep 工具:代码搜索
  • View 工具:文件查看
  • Edit 工具:文件编辑
  • Search 工具:网络搜索
  • Web Fetch 工具:网页内容获取
  • Task 工具:任务分解执行

资料来源:README.md:32-45

LSP 集成

Crush 可使用 Language Server Protocol (LSP) 来获取额外的上下文信息,辅助决策。支持手动配置 LSP:

{
  "lsp": {
    "go": {
      "command": "gopls",
      "env": { "GOTOOLCHAIN": "go1.24.5" }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}

资料来源:README.md:180-195

MCP 支持

Crush 支持通过三种传输类型连接 MCP 服务器:

传输类型用途
stdio命令行 MCP 服务器
httpHTTP 端点
sseServer-Sent Events

MCP 配置支持 shell 风格的环境变量展开($VAR${VAR:-default}$(command))。

资料来源:README.md:197-215

Hooks 机制

Hooks 使用内置 shell 解释器执行,默认使用系统 shell。这改善了跨平台支持。

资料来源:v0.67.0 发布说明

系统架构

客户端-服务端架构

Crush 采用客户端-服务端架构设计,可通过环境变量 CRUSH_CLIENT_SERVER=1 启用实验性功能。

graph TD
    A[CLI Client] -->|HTTP/WebSocket| B[Backend Server]
    B --> C[Workspace Manager]
    C --> D[Agent Processing]
    C --> E[LSP Manager]
    C --> F[MCP Integration]
    B --> G[Database]
    D --> H[Tool Executor]
    H --> I[Permission System]

资料来源:internal/backend/backend_test.go:10-25 资料来源:internal/server/events.go:1-50

工作空间管理

每个客户端连接到一个工作空间(Workspace),工作空间通过路径索引管理:

  • 绝对路径直接解析
  • 相对路径基于当前目录
  • 不存在的路径会创建新工作空间
type Workspace struct {
    ID           string
    Path         string
    resolvedPath string
    clients      map[string]*clientState
    shutdownFn   func()
}

资料来源:internal/backend/backend_test.go:13-20

事件系统

Crush 使用发布-订阅模式处理内部事件,主要事件类型包括:

type LSPEvent struct {
    Type            LSPEventType
    Name            string
    State           lsp.ServerState
    Error           error
    DiagnosticCount int
}
事件类型说明
LSPEventStateChangedLSP 服务器状态变更
LSPEventDiagnosticsChanged诊断信息变更
pubsub.Event[mcp.Event]MCP 相关事件
pubsub.Event[permission.PermissionRequest]权限请求

资料来源:internal/app/lsp_events.go:16-30 资料来源:internal/server/events.go:25-55

配置系统

配置文件优先级

Crush 配置文件按以下优先级加载:

  1. .crush.json(项目本地)
  2. crush.json(项目本地)
  3. $HOME/.config/crush/crush.json(全局)

配置文件使用 JSON 格式存储。

资料来源:README.md:139-155

环境变量覆盖

可通过以下环境变量覆盖默认配置路径:

环境变量说明
CRUSH_GLOBAL_CONFIG全局配置文件路径
CRUSH_GLOBAL_DATA全局数据目录路径
CRUSH_CLIENT_SERVER启用客户端-服务端模式

资料来源:README.md:156-165

API 密钥配置

Crush 支持多种提供商的 API 密钥配置:

环境变量提供商
ANTHROPIC_API_KEYAnthropic
OPENAI_API_KEYOpenAI
DEEPSEEK_API_KEYDeepSeek
OPENROUTER_API_KEYOpenRouter
VERTEXAI_*Google Cloud VertexAI
AWS_*Amazon Bedrock

资料来源:README.md:220-260

客户端 API

配置操作

客户端提供完整的配置管理接口:

// 设置紧凑模式
func (c *Client) SetCompactMode(ctx context.Context, id string, scope config.Scope, enabled bool) error

// 设置提供商 API 密钥
func (c *Client) SetProviderAPIKey(ctx context.Context, id string, scope config.Scope, providerID string, apiKey any) error

// 导入 Copilot Token
func (c *Client) ImportCopilot(ctx context.Context, id string) (*oauth.Token, bool, error)

// 刷新 OAuth Token
func (c *Client) RefreshOAuthToken(ctx context.Context, id string, scope config.Scope, providerID string) error

资料来源:internal/client/config.go:180-280

MCP 操作

客户端支持与 MCP 服务器交互:

// 读取 MCP 资源
func (c *Client) GetMCPResource(ctx context.Context, id, clientID, serverID, uri string) ([]MCPResourceContents, error)

// 获取 MCP Prompt
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error)

资料来源:internal/client/config.go:60-120

Agent 操作

// 列出消息
func (c *Client) ListMessages(ctx context.Context, id string, sessionID string) ([]proto.Message, error)

// 汇总会话
func (c *Client) SummarizeSession(ctx context.Context, id, sessionID string) error

// 初始化 Agent 处理
func (c *Client) InitiateAgentProcessing(ctx context.Context, id string) error

资料来源:internal/client/proto.go:80-120

生命周期管理

应用关闭

Crush 提供两种关闭机制:

  1. App.Shutdown:生产环境完整关闭路径,包含数据库释放、LSP 关闭、MCP 关闭
  2. App.ShutdownForTest:测试用关闭,仅执行清理函数
func (app *App) ShutdownForTest() {
    for _, cleanup := range app.cleanupFuncs {
        if cleanup != nil {
            _ = cleanup(context.Background())
        }
    }
    app.cleanupFuncs = nil
}

资料来源:internal/app/testing.go:1-15

工作空间持有机制

工作空间使用持有(Hold)机制防止意外关闭:

  • 注册客户端时获取持有
  • 客户端连接时增加引用计数
  • 最后一个持有释放时触发工作空间关闭
func TestHoldExpiry_TearsDown(t *testing.T) {
    b, srvShutdowns := newTestBackend(t)
    ws, wsShutdowns := insertTestWorkspace(t, b, "/tmp/a")
    cid := newClientID(t)
    b.registerClient(ws, cid)
    // 持有过期时触发关闭
}

资料来源:internal/backend/backend_test.go:80-95

社区相关问题

已知问题与功能请求

Issue说明状态
#2935多权限配置文件(Yolo/Safe/Custom)运行时切换功能请求
#928移除 bash 命令安全限制功能请求
#2898全局 LSP 配置不生效Bug 报告
#2903数据库持续损坏Bug 报告
#2928OpenRouter 模型授权失败Bug 报告

最新版本动态

v0.74.1 修复内容:

  • 修复 bash 工具在运行交互式命令(如 git rebase -i)时挂起的问题
  • 修复 OpenCode + Qwen 3.7 的兼容性
  • 客户端-服务端架构持续改进

技术栈

组件技术
语言Go
协议HTTP, WebSocket, SSE
配置JSON
扩展协议MCP (Model Context Protocol)
语言服务LSP (Language Server Protocol)
授权OAuth, API Key

相关资源

  • 官方文档:https://charm.land/crush
  • 社区 Slack:https://charm.land/slack
  • Discord:https://charm.land/discord
  • 模型列表:https://github.com/charmbracelet/catwalk

资料来源:README.md:1-8

安装与部署

Crush 是一个终端编程助手,支持在多种操作系统上运行。本文档详细介绍 Crush 的各种安装方式和部署配置选项,帮助用户快速上手并根据自身环境进行定制化部署。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 运行环境要求

继续阅读本节完整说明和来源证据。

章节 外部依赖

继续阅读本节完整说明和来源证据。

章节 通过包管理器安装

继续阅读本节完整说明和来源证据。

概述

Crush 是一个终端编程助手,支持在多种操作系统上运行。本文档详细介绍 Crush 的各种安装方式和部署配置选项,帮助用户快速上手并根据自身环境进行定制化部署。

Crush 采用 Go 语言开发,提供了跨平台支持,覆盖 macOS、Linux、Windows(包括 PowerShell 和 WSL)、Android、FreeBSD、OpenBSD 和 NetBSD 等主流操作系统。资料来源:README.md:1-15

系统要求

运行环境要求

组件最低要求推荐配置
操作系统macOS 10.15+ / Linux (glibc 2.31+) / Windows 10+最新稳定版
内存4GB8GB+
磁盘空间200MB500MB+
网络需要访问 LLM API稳定高速网络

外部依赖

部分功能需要安装外部工具:

  • Shell 工具:bash、zsh、PowerShell
  • Git:版本控制功能必需
  • LSP 服务器:根据编程语言需求(如 gopls、typescript-language-server)

资料来源:README.md:45-52

安装方式

通过包管理器安装

#### macOS (Homebrew)

brew install charmbracelet/tap/crush

#### NPM

npm install -g @charmland/crush

资料来源:README.md:59-65

#### Linux 包管理器

发行版安装命令
Arch Linuxyay -S crush-bin
FreeBSDpkg install crush
Nixnix run github:numtide/nix-ai-tools#crush

#### Windows

包管理器安装命令
Wingetwinget install charmbracelet.crush
Scoopscoop bucket add charm https://github.com/charmbracelet/scoop-bucket.git && scoop install crush

资料来源:README.md:66-80

Nix/NixOS 安装

#### 通过 NUR 安装

Crush 通过官方 Charm NUR 提供 Nix 支持,是 Nix 中获取最新版本的最优方式。

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nur.url = "github:nix-community/NUR";
    # 导入 nur.repos.charmbracelet.crush
  };
}

#### Nix Shell 快速试用

# 添加 NUR channel
nix-channel --add https://github.com/nix-community/NUR/archive/main.tar.gz nur
nix-channel --update

# 在 Nix shell 中运行 Crush
nix-shell -p '(import <nur> { pkgs = import <nixpkgs> {}; }).repos.charmbracelet.crush'

#### NixOS / Home Manager 模块

Crush 提供 NixOS 和 Home Manager 模块,可直接通过 NUR 导入到 flake 配置中:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nur.url = "github:nix-community/NUR";
  };

  outputs = { self, nixpkgs, nur }: {
    # 支持自动检测 home-manager 或 nixos 上下文
    homeModules.example = import (nur + "/repos/charmbracelet/modules/crush") { pkgs = nixpkgs.legacyPackages.x86_64-linux; };
  };
}

资料来源:flake.nix:1-25

从源码编译安装

#### 环境准备

  1. 安装 Go 1.21+
  2. 克隆仓库
git clone https://github.com/charmbracelet/crush.git
cd crush

#### 编译

# 编译可执行文件
go build -o crush ./cmd/crush

# 或使用 Taskfile(需要安装 Task)
task build

#### Taskfile 构建任务

任务说明
task build编译 Crush 可执行文件
task test运行测试套件
task lint运行代码检查
task release创建发布版本
# 查看所有可用任务
task --list

资料来源:Taskfile.yaml:1-50

配置管理

配置文件位置

Crush 支持多级配置文件,按以下优先级加载:

graph TD
    A[配置文件加载顺序] --> B[.crush.json]
    B --> C[crush.json]
    C --> D[$HOME/.config/crush/crush.json]
    
    E[临时数据位置] --> F[Unix: $HOME/.local/share/crush/crush.json]
    E --> G[Windows: %LOCALAPPDATA%\crush\crush.json]

配置文件优先级(高 → 低):

  1. .crush.json(项目本地)
  2. crush.json(项目根目录)
  3. $HOME/.config/crush/crush.json(全局)

资料来源:README.md:30-50

环境变量配置覆盖

可通过环境变量覆盖默认配置路径:

环境变量用途
CRUSH_GLOBAL_CONFIG全局配置文件路径
CRUSH_GLOBAL_DATA全局数据目录路径
CRUSH_SKILLS_DIR自定义技能目录
CRUSH_CLIENT_SERVER启用客户端-服务器架构(实验性)

资料来源:README.md:48-52

基本配置示例

{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disabled_skills": ["crush-config"]
  },
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "go1.24.5"
      }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}

LSP 配置

Crush 支持 Language Server Protocol,可为不同编程语言配置 LSP 服务器:

{
  "lsp": {
    "<语言>": {
      "command": "<命令>",
      "args": ["参数列表"],
      "env": {"环境变量": "值"},
      "root_markers": ["标记文件"],
      "filetypes": ["文件类型"]
    }
  }
}

常见 LSP 配置示例:

语言命令参数
Gogopls-
TypeScripttypescript-language-server--stdio
Nixnil-
注意:全局 LSP 配置需确保配置文件位于正确路径(~/.config/crush/crush.json),部分用户报告过全局 LSP 配置不生效的问题。资料来源:README.md:54-68

MCP 服务器配置

Crush 支持 Model Context Protocol (MCP),支持三种传输类型:

传输类型说明
stdio命令行服务器
httpHTTP 端点
sseServer-Sent Events
{
  "mcp": {
    "servers": {
      "example": {
        "transport": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"]
      }
    }
  }
}

环境变量扩展支持:

  • $VAR - 基本变量替换
  • ${VAR:-default} - 带默认值的变量
  • $(command) - 命令替换
  • 文件引用如 "$(cat /path/to/secret/token)"

资料来源:README.md:70-90

技能(Skills)配置

#### 技能搜索路径

Crush 按以下顺序搜索技能目录:

graph LR
    A[技能搜索路径] --> B[全局目录]
    A --> C[项目目录]
    
    B --> B1[$CRUSH_SKILLS_DIR]
    B --> B2[$XDG_CONFIG_HOME/agents/skills]
    B --> B3[$XDG_CONFIG_HOME/crush/skills]
    B --> B4[~/.agents/skills]
    B --> B5[~/.claude/skills]
    
    C --> C1[.agents/skills]
    C --> C2[.crush/skills]
    C --> C3[.claude/skills]
    C --> C4[.cursor/skills]

#### 自定义技能路径

{
  "options": {
    "skills_paths": [
      "~/.config/crush/skills",
      "./project-skills"
    ]
  }
}

资料来源:README.md:105-135

权限模式配置

Crush 提供三种权限模式控制工具调用行为:

模式说明配置项
Yolo完全自动批准所有工具调用permissions.yolo: true
Safe每次工具调用前询问确认permissions.yolo: false(默认)
Custom自定义权限规则使用 permissions.rules
社区反馈:当前版本权限模式一旦设置将应用于整个会话,无法在运行时切换。资料来源:社区讨论 #2935

提交信息配置

{
  "git": {
    "trailer_style": "assisted-by",
    "generated_with": true
  }
}
配置项可选值说明
trailer_styleassisted-by(默认)、co-authored-bynone提交信息归属风格
generated_withtrue(默认)、false是否添加 "💘 Generated with Crush"

资料来源:README.md:145-165

环境变量

API 密钥配置

Crush 支持多种 LLM 提供商,通过环境变量配置 API 密钥:

环境变量支持的提供商
ANTHROPIC_API_KEYAnthropic
OPENAI_API_KEYOpenAI
VERCEL_API_KEYVercel AI Gateway
GEMINI_API_KEYGoogle Gemini
SYNTHETIC_API_KEYSynthetic
ZAI_API_KEYZ.ai
MINIMAX_API_KEYMiniMax
HF_TOKENHugging Face Inference
CEREBRAS_API_KEYCerebras
OPENROUTER_API_KEYOpenRouter
OPENCODE_API_KEYOpenCode Zen & Go
GROQ_API_KEYGroq
IONET_API_KEYio.net
ALIBABA_SINGAPORE_API_KEYAlibaba (Singapore)
AVIAN_API_KEYAvian

AWS / Azure 配置

环境变量用途
AWS_ACCESS_KEY_IDAmazon Bedrock (Claude)
AWS_SECRET_ACCESS_KEYAmazon Bedrock (Claude)
AWS_REGIONAmazon Bedrock (Claude)
AWS_PROFILEAmazon Bedrock (自定义 Profile)
AWS_BEARER_TOKEN_BEDROCKAmazon Bedrock
AZURE_OPENAI_API_ENDPOINTAzure OpenAI
AZURE_OPENAI_API_KEYAzure OpenAI
AZURE_OPENAI_API_VERSIONAzure OpenAI
VERTEXAI_PROJECTGoogle Cloud VertexAI
VERTEXAI_LOCATIONGoogle Cloud VertexAI

资料来源:README.md:170-195

客户端-服务器模式

架构概述

Crush 支持实验性的客户端-服务器架构,将前端界面与后端服务分离:

graph TD
    A[Crush 客户端] <--> B[Crush 服务器]
    B --> C[数据库]
    B --> D[LSP 服务]
    B --> E[MCP 服务]
    B --> F[LLM API]

启用方式

export CRUSH_CLIENT_SERVER=1
crush

工作空间管理

服务器模式下支持多工作空间管理:

功能说明
多工作空间每个项目独立的上下文
会话持久化跨会话保持对话历史
并行连接支持多个客户端同时连接

资料来源:internal/app/app.go:1-45

桌面通知

Crush 支持桌面通知,当工具调用需要权限或代理完成时会发送通知:

{
  "options": {
    "disable_notifications": false  // 默认值
  }
}

通知发送条件:

  • 工具调用需要权限确认
  • 代理完成当前回合
注意:macOS 平台的通知目前缺少图标(平台限制)。

资料来源:README.md:138-155

订阅服务

除 API 密钥方式外,Crush 也支持订阅制服务:

服务说明
Synthetic订阅计费
GLM Coding Plan智谱 AI 代码计划
Kimi Code月之暗面代码助手
MiniMax Coding PlanMiniMax 代码计划

资料来源:README.md:197-205

验证安装

基本验证

# 检查版本
crush --version

# 检查配置
crush doctor

配置测试

# 测试 API 连接
crush config test

# 测试 LSP 连接
crush lsp check

常见问题排查

问题解决方案
数据库损坏清除 ~/.local/share/crush/crush.json 并重启
OpenRouter 连接失败确认 OPENROUTER_API_KEY 正确设置
LSP 配置不生效检查配置文件路径和权限
Bash 工具挂起避免运行交互式命令(如 git rebase -i
社区反馈:部分用户报告数据库在 VM 环境中定期损坏,可能是文件系统问题导致。资料来源:社区讨论 #2903

更新升级

自动更新检查

Crush 启动时会自动检查更新,提示用户有新版本可用。

手动更新

# 使用包管理器
brew upgrade crush  # macOS
npm update -g @charmland/crush  # NPM

# 或重新安装
brew reinstall charmbracelet/tap/crush

版本信息

当前稳定版本:v0.74.1

最新版本信息请参阅 GitHub Releases

资料来源:README.md:210-220

卸载

平台卸载命令
Homebrew (macOS)brew uninstall crush
NPMnpm uninstall -g @charmland/crush
Winget (Windows)winget uninstall charmbracelet.crush
Scoop (Windows)scoop uninstall crush

卸载后建议清理配置文件:

# 配置文件
rm -rf ~/.config/crush

# 数据文件
rm -rf ~/.local/share/crush

# Windows
rd /s /q %LOCALAPPDATA%\crush

资料来源:README.md:45-52

快速入门

Crush 是一款终端内的智能编程助手,它将你的工具、代码和工作流与大型语言模型(LLM)无缝集成。无论你是处理日常开发任务还是复杂的多步骤项目,Crush 都能提供强大的辅助能力。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 系统要求

继续阅读本节完整说明和来源证据。

章节 安装方式

继续阅读本节完整说明和来源证据。

章节 验证安装

继续阅读本节完整说明和来源证据。

安装 Crush

系统要求

Crush 支持 macOS、Linux 和 Windows 系统。推荐使用最新版本的操作系统以获得最佳体验。

安装方式

#### macOS

brew install charm-cli/tap/crush

#### Linux

curl -fsSL https://get.crush.sh | bash

#### Windows

使用 winget 安装:

winget install Charm.Crush

验证安装

安装完成后,在终端中运行以下命令验证安装:

crush --version

资料来源:README.md:1-20

首次启动与登录

默认启动

直接运行 crush 命令即可启动程序:

crush

首次启动时,Crush 会引导你完成初始配置流程,包括选择默认语言模型和配置 API 密钥。

配置 API 密钥

Crush 支持多种模型提供商,你需要配置相应的 API 密钥才能使用对应的模型。

#### 环境变量方式

提供商环境变量说明
AnthropicANTHROPIC_API_KEY用于 Claude 系列模型
OpenAIOPENAI_API_KEY用于 GPT 系列模型
Google GeminiGEMINI_API_KEY用于 Gemini 模型
OpenRouterOPENROUTER_API_KEY用于访问多种模型
DeepSeekDEEPSEEK_API_KEY用于 DeepSeek 模型

资料来源:README.md:1-100

#### 配置文件方式

你也可以在 crush.json 中直接配置 API 密钥:

{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "deepseek": {
      "type": "openai-compat",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "$DEEPSEEK_API_KEY"
    }
  }
}

资料来源:README.md:100-150

基本配置

配置文件位置

Crush 按以下优先级查找配置文件:

优先级位置说明
1.crush.json项目本地配置
2crush.json项目本地配置
3~/.config/crush/crush.json用户全局配置

配置结构

Crush 的配置文件采用 JSON 格式,主要包含以下部分:

{
  "$schema": "https://charm.land/crush.json",
  "providers": {},
  "lsp": {},
  "mcp": {},
  "options": {}
}

资料来源:README.md:150-200

核心功能入门

1. 对话交互

启动 Crush 后,你可以直接通过自然语言与它交流。Crush 能够理解你的编程需求并执行相应的操作。

示例对话:

你:帮我创建一个新的 Go 项目
Crush:好的,我将为你创建一个标准的 Go 项目结构...

2. 文件操作

Crush 提供了多种文件操作工具:

工具名称功能常用场景
view查看文件内容代码审查、快速定位
write写入或创建文件生成代码、修改配置
read读取文件获取文件内容进行处理
edit编辑文件修改代码、行级调整
glob文件搜索查找项目中的文件

3. Bash 命令执行

Crush 可以执行 bash 命令来完成各种任务:

# 运行 git 命令
crush> git status

# 运行构建命令
crush> go build ./...

# 搜索文件内容
crush> grep -r "function" .
[!NOTE]
某些敏感命令(如 curlwgetsshsudo)可能受到安全限制。社区中有用户反馈希望移除这些限制以获得不受限制的终端访问能力。相关讨论可参考 GitHub Issue #928

4. LSP 集成

Crush 支持 Language Server Protocol (LSP),可以为编程决策提供更丰富的上下文信息。

#### 配置示例

{
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "go1.24.5"
      }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}

资料来源:README.md:200-250

#### LSP 事件类型

事件类型说明
state_changedLSP 服务器状态变更
diagnostics_changed诊断信息变更

资料来源:internal/app/lsp_events.go:1-50

5. MCP 服务器支持

Crush 支持 Model Context Protocol (MCP) 服务器,提供三种传输类型:

传输类型说明配置方式
stdio命令行服务器命令行参数
httpHTTP 端点URL 和 Headers
sseServer-Sent EventsURL 配置

#### 配置示例

{
  "mcp": {
    "my-server": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"]
    }
  }
}

#### Shell 变量展开

MCP 配置支持 Shell 风格的变量展开:

语法说明
$VAR展开环境变量
${VAR:-default}展开带默认值的变量
$(command)执行命令并展开结果

资料来源:README.md:250-300

工作流程图

基本交互流程

graph TD
    A[用户启动 Crush] --> B[加载配置文件]
    B --> C{检查 API 密钥}
    C -->|有有效密钥| D[连接到 LLM]
    C -->|无密钥| E[引导用户配置]
    E --> C
    D --> F[用户发送请求]
    F --> G[解析请求意图]
    G --> H[调用相应工具]
    H --> I[执行操作]
    I --> J[返回结果给用户]
    J --> F

工具调用流程

graph LR
    A[用户请求] --> B[LLM 决策]
    B --> C{需要权限?}
    C -->|是| D[请求权限]
    D --> E{用户批准?}
    E -->|是| F[执行工具]
    E -->|否| G[跳过/取消]
    C -->|否| F
    F --> H[返回结果]
    G --> H

Agent Skills

Crush 支持 Agent Skills 开放标准,可以通过可重用的技能包扩展功能。

技能搜索路径

优先级路径
1$CRUSH_SKILLS_DIR
2~/.config/agents/skills/
3~/.config/crush/skills/
4~/.agents/skills/
5~/.claude/skills/

项目本地技能路径

  • .agents/skills
  • .crush/skills
  • .claude/skills
  • .cursor/skills

资料来源:README.md:300-350

权限与安全

权限模式

Crush 提供了两种权限模式:

模式说明配置项
Yolo自动批准所有工具调用permissions.yolo: true
Safe执行前询问每个工具permissions.yolo: false
[!TIP]
社区中有功能请求,希望支持在运行时切换权限配置文件(如 Yolo、Safe、Custom),而无需重启 Crush。相关讨论可参考 GitHub Issue #2935

提交信息配置

{
  "git": {
    "trailer_style": "assisted-by",
    "generated_with": true
  }
}

支持的提交风格:

风格说明
assisted-by添加 Assisted-by: Crush:[ModelID]
co-authored-by添加 Co-Authored-By: Crush <[email protected]>
none不添加任何标识

资料来源:README.md:50-100

常见问题与故障排除

数据库问题

[!WARNING]
有用户报告在虚拟机环境中运行 Crush 时遇到数据库损坏问题。若遇到 ERROR: failed to get session message 错误,可能需要检查文件系统完整性。相关讨论可参考 GitHub Issue #2903

LSP 配置问题

[!NOTE]
全局 LSP 配置可能不生效。若 LSP 功能无法正常使用,可以尝试使用项目本地的 .crush.json 配置文件。相关讨论可参考 GitHub Issue #2898

模型提供商问题

如果在使用 OpenRouter 等第三方模型时遇到认证错误,请确保:

  1. API 密钥已正确设置在环境变量中
  2. API 密钥具有访问所需模型的权限
  3. 配置文件中的模型名称拼写正确

相关讨论可参考 GitHub Issue #2928

下一步

资源说明
配置文件参考完整的配置选项文档
工具参考所有可用工具的详细说明
LSP 集成LSP 配置高级指南
MCP 集成MCP 服务器配置指南
技能开发创建自定义 Agent Skills

获取帮助

资料来源:README.md:1-20

系统架构

Crush 是一个基于终端的 AI 编程助手,采用客户端-服务器(Client-Server)架构设计。该架构允许终端界面与核心处理逻辑分离,支持多工作区管理和实时事件流传输。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 1. App 模块

继续阅读本节完整说明和来源证据。

章节 2. Backend 模块

继续阅读本节完整说明和来源证据。

章节 3. Server 模块

继续阅读本节完整说明和来源证据。

整体架构概览

Crush 的系统架构由以下几个核心模块组成:

graph TD
    subgraph "客户端层 (Client)"
        TUI[终端用户界面]
        SDK[Client SDK]
    end
    
    subgraph "服务端层 (Server)"
        HTTP[HTTP Server]
        WS[WebSocket Handler]
        API[REST API Controllers]
    end
    
    subgraph "业务逻辑层 (Backend)"
        BE[Backend 核心]
        WS_Manager[Workspace Manager]
        Agent[Agent 处理]
    end
    
    subgraph "集成层 (Integrations)"
        LSP[LSP 集成]
        MCP[MCP 集成]
        Permission[权限系统]
    end
    
    TUI <--> SDK
    SDK <--> HTTP
    SDK <--> WS
    HTTP --> API
    API --> BE
    BE --> WS_Manager
    BE --> Agent
    BE --> LSP
    BE --> MCP
    BE --> Permission
    
    LSP <--> LSP_Server[Language Server]
    MCP <--> MCP_Server[MCP Server]

核心组件

1. App 模块

App 模块是 Crush 应用程序的主入口,负责全局生命周期管理和清理函数注册。

组件文件职责
Appinternal/app/app.go全局应用状态管理
testinginternal/app/testing.go测试环境支持
lsp_eventsinternal/app/lsp_events.goLSP 事件订阅与分发

关键特性:

  • 清理函数注册:通过 cleanupFuncs 切片管理资源释放回调
  • 测试支持ShutdownForTest() 方法提供测试专用的清理路径
  • LSP 事件系统:基于 pubsub.Broker 的发布订阅机制
// internal/app/testing.go:7-11
func (app *App) ShutdownForTest() {
    for _, cleanup := range app.cleanupFuncs {
        if cleanup != nil {
            _ = cleanup(context.Background())
        }
    }
    app.cleanupFuncs = nil
}

资料来源:internal/app/testing.go:7-11

2. Backend 模块

Backend 是 Crush 的核心业务逻辑层,负责工作区管理和客户端状态追踪。

组件文件职责
backend.gointernal/backend/backend.go核心业务逻辑
backend_test.gointernal/backend/backend_test.go单元测试

关键数据结构:

type Workspace struct {
    ID           string
    Path         string
    resolvedPath string
    clients      map[string]*clientState
    shutdownFn   func()
}

资料来源:internal/backend/backend_test.go:22-29

工作区生命周期管理:

  • 创建:通过 NewWorkspace 创建独立工作区
  • 注册客户端:使用 registerClient 追踪活跃连接
  • 持有机制releaseHold 控制工作区何时被销毁
sequenceDiagram
    participant C as Client
    participant B as Backend
    participant W as Workspace
    
    C->>B: registerClient(ws, clientID)
    C->>B: AttachClient(ws.ID, clientID)
    C->>B: releaseHold(ws.ID, clientID)
    
    alt 有活跃流
        B->>W: 保持 Workspace
    else 无活跃流
        B->>W: 调用 shutdownFn
        W->>B: 清理资源
    end

3. Server 模块

Server 模块实现 HTTP API 接口,支持 REST 和 SSE(Server-Sent Events)两种通信模式。

组件文件职责
server.gointernal/server/server.goHTTP 服务器启动与路由
events.gointernal/server/events.go事件类型转换
proto.gointernal/server/proto.goAPI 控制器实现

事件类型转换链:

// internal/server/events.go:1-25
// 支持的事件类型:
// - LSPEvent: 语言服务器协议事件
// - MCPEvent: 模型上下文协议事件  
// - PermissionRequest: 权限请求事件
// - PermissionNotification: 权限通知事件

主要 API 端点:

端点方法功能
/workspacesGET列出所有工作区
/workspaces/:idGET获取工作区详情
/workspaces/:id/configGET/PUT配置管理
/workspaces/:id/agent/sessions/:sid/summarizePOST会话摘要
/workspaces/:id/agent/initPOST初始化 Agent
/controlPOST服务器控制命令

资料来源:internal/server/proto.go:1-20

4. Client 模块

Client 模块提供 SDK 供外部应用集成 Crush 功能。

组件文件职责
client.gointernal/client/client.goHTTP 客户端基类
config.gointernal/client/config.go配置与 MCP 交互
proto.gointernal/client/proto.go协议消息处理

MCP 资源访问:

// internal/client/config.go:1-20
type MCPResourceContents struct {
    Type     string `json:"type"`
    Text     string `json:"text,omitempty"`
    URI      string `json:"uri,omitempty"`
    MimeType string `json:"mimeType,omitempty"`
}

API Key 管理:

Client 支持多种凭证类型的安全传输:

// internal/client/config.go - SetProviderAPIKey
// 支持的 API Key 类型:
// - Anthropic
// - OpenAI
// - Google Gemini
// - 其他自定义提供商

资料来源:internal/client/config.go:1-20

5. LSP 集成

LSP(Language Server Protocol)集成提供项目级代码上下文感知能力。

文件职责
internal/app/lsp_events.goLSP 事件定义与分发

LSP 事件类型:

const (
    LSPEventStateChanged       LSPEventType = "state_changed"
    LSPEventDiagnosticsChanged LSPEventType = "diagnostics_changed"
)

LSP 状态管理:

// internal/app/lsp_events.go:28-35
type LSPClientInfo struct {
    Name            string
    State           lsp.ServerState
    Error           error
    Client          *lsp.Client
    DiagnosticCount int
    ConnectedAt     time.Time
}

使用 csync.NewMap 实现线程安全的并发访问:

var lspStates = csync.NewMap[string, LSPClientInfo]()
var lspBroker = pubsub.NewBroker[LSPEvent]()

资料来源:internal/app/lsp_events.go:1-35

客户端-服务器通信架构

实验性架构

Crush 正在推进客户端-服务器架构的重构,可通过环境变量 CRUSH_CLIENT_SERVER=1 启用实验性功能。

资料来源:社区讨论 - v0.68.0

事件流处理

graph LR
    subgraph "服务端"
        E[Event Source]
        T[Type Conversion]
        W[Wire Format]
    end
    
    subgraph "传输层"
        S[JSON over HTTP/SSE]
    end
    
    subgraph "客户端"
        P[Parse]
        R[Application]
    end
    
    E --> T
    T --> W
    W --> S
    S --> P
    P --> R

事件序列化示例:

// internal/server/events.go - skillsEventToProto
func skillsEventToProto(e skills.Event) proto.SkillsEvent {
    out := proto.SkillsEvent{States: make([]proto.SkillState, len(e.States))}
    for i, s := range e.States {
        entry := proto.SkillState{
            Name:  s.Name,
            Path:  s.Path,
            State: proto.SkillDiscoveryState(s.State),
        }
        if s.Err != nil {
            entry.Error = s.Err.Error()
        }
        out.States[i] = entry
    }
    return out
}

工作区管理

Workspace 结构

type Workspace struct {
    ID           string              // 唯一标识符 (UUID)
    Path         string              // 用户指定路径
    resolvedPath string              // 解析后的绝对路径
    clients      map[string]*clientState  // 活跃客户端映射
    shutdownFn   func()              // 清理回调
}

资料来源:internal/backend/backend_test.go:22-29

路径解析与符号链接

Backend 模块实现了智能路径解析:

  • 解析符号链接到真实路径
  • 对不存在的路径自动创建
  • 支持工作区路径索引映射
// internal/backend/backend_test.go - 测试用例
func TestResolveWorkspaceKey_AbsoluteAndSymlink(t *testing.T) {
    tmp := t.TempDir()
    real, err := filepath.EvalSymlinks(tmp)
    got, err := resolveWorkspaceKey(tmp)
    require.Equal(t, real, got)
}

资料来源:internal/backend/backend_test.go:37-46

权限系统

Crush 实现细粒度的权限控制机制,支持运行时权限请求和审批流程。

事件类型说明
PermissionRequest工具调用前的权限请求
PermissionNotification权限状态变更通知

权限请求结构:

// internal/server/events.go
type PermissionRequest struct {
    ID          string
    SessionID   string
    ToolCallID  string
    ToolName    string
    Description string
    Action      string
    Path        string
    Params      map[string]any
}

配置系统

配置优先级

  1. .crush.json (项目本地)
  2. crush.json (项目根目录)
  3. $HOME/.config/crush/crush.json (用户全局)

环境变量覆盖

变量说明
CRUSH_GLOBAL_CONFIG覆盖配置文件路径
CRUSH_GLOBAL_DATA覆盖数据目录路径
CRUSH_CLIENT_SERVER启用实验性客户端-服务器模式

常见问题与社区反馈

架构相关问题

Issue问题状态
#2935多权限模式切换(Yolo/Safe/Custom)功能请求
#928Bash 命令安全限制用户反馈
#2898全局 LSP 配置不生效问题报告
#2903数据库损坏问题问题报告

稳定性改进

v0.68.0 版本对客户端-服务器架构进行了大量修复,显著提升了稳定性。

资料来源:社区讨论 - v0.68.0

扩展机制

LSP 支持

配置示例:

{
  "lsp": {
    "go": {
      "command": "gopls",
      "env": { "GOTOOLCHAIN": "go1.24.5" }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}

MCP 支持

支持三种传输类型:

  • stdio:命令行服务器
  • http:HTTP 端点
  • sse:Server-Sent Events

总结

Crush 的系统架构采用分层设计:

  1. App 层:应用生命周期管理
  2. Backend 层:核心业务逻辑与工作区管理
  3. Server 层:HTTP API 与事件分发
  4. Client 层:SDK 与外部集成
  5. 集成层:LSP、MCP、权限系统

该架构支持实验性的客户端-服务器模式,允许更灵活的前端实现和更好的资源隔离。

资料来源:internal/app/testing.go:7-11

数据流与数据库

Crush 的数据流与数据库系统承担着整个应用的状态管理、事件分发和持久化存储的核心职责。该系统采用模块化架构,将客户端与服务器分离,通过事件驱动的方式实现各组件间的解耦通信。数据库层负责存储会话、消息历史和配置信息,而事件系统则负责在运行时协调 LSP、MCP、权限等子系统的状态变化。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 事件类型与转换

继续阅读本节完整说明和来源证据。

章节 事件类型映射表

继续阅读本节完整说明和来源证据。

章节 Proto 转换机制

继续阅读本节完整说明和来源证据。

概述

Crush 的数据流与数据库系统承担着整个应用的状态管理、事件分发和持久化存储的核心职责。该系统采用模块化架构,将客户端与服务器分离,通过事件驱动的方式实现各组件间的解耦通信。数据库层负责存储会话、消息历史和配置信息,而事件系统则负责在运行时协调 LSP、MCP、权限等子系统的状态变化。

核心架构

Crush 采用客户端-服务器架构,数据在各组件间通过统一的事件总线流转。客户端负责用户交互和 API 调用,服务器端处理实际的业务逻辑和数据库操作。

graph TD
    Client[客户端] -->|HTTP/WebSocket| Server[服务器]
    Server -->|事件分发| EventBus[事件总线]
    EventBus -->|LSP事件| LSPSub[LSP子系统]
    EventBus -->|MCP事件| MCPSub[MCP子系统]
    EventBus -->|权限事件| PermSub[权限子系统]
    Server -->|持久化| DB[数据库]
    Session[会话管理] --> DB
    Workspace[工作空间] --> Session

事件系统

事件类型与转换

事件系统是 Crush 数据流的核心枢纽。系统定义了多种事件类型,每种事件在客户端与服务器之间通过 Protocol Buffer 进行序列化传输。

// 资料来源:internal/app/lsp_events.go:11-14
const (
    LSPEventStateChanged       LSPEventType = "state_changed"
    LSPEventDiagnosticsChanged LSPEventType = "diagnostics_changed"
)

事件类型映射表

事件类型来源文件说明
LSPEventlsp_events.go语言服务器状态变化
MCPEventevents.goMCP 服务器事件
PermissionRequestevents.go工具调用权限请求
PermissionNotificationevents.go权限通知
SkillsEventevents.go技能状态变化

Proto 转换机制

事件在跨网络传输前需要转换为 Protocol Buffer 格式。转换逻辑集中在 internal/server/events.go 中:

// 资料来源:internal/server/events.go
func skillsEventToProto(e skills.Event) proto.SkillsEvent {
    if len(e.States) == 0 {
        return proto.SkillsEvent{}
    }
    out := proto.SkillsEvent{States: make([]proto.SkillState, len(e.States))}
    for i, s := range e.States {
        entry := proto.SkillState{
            Name:  s.Name,
            Path:  s.Path,
            State: proto.SkillDiscoveryState(s.State),
        }
        if s.Err != nil {
            entry.Error = s.Err.Error()
        }
        out.States[i] = entry
    }
    return out
}

事件消息转换

消息内容的转换同样遵循统一的 proto 格式:

// 资料来源:internal/server/events.go
func messagesToProto(msgs []message.Message) []proto.Message {
    out := make([]proto.Message, len(msgs))
    for i, m := range msgs {
        out[i] = messageToProto(m)
    }
    return out
}

会话管理

会话生命周期

会话是 Crush 数据持久化的核心单位。每个工作空间可以包含多个会话,会话存储消息历史、工具调用记录和上下文状态。

graph LR
    Create[创建会话] --> Active[活跃状态]
    Active -->|上下文满| Summarize[摘要压缩]
    Active -->|用户退出| Close[关闭会话]
    Active -->|Token刷新| Refresh[刷新认证]
    Summarize --> Active

客户端注册与注销

// 资料来源:internal/backend/backend_test.go:21-32
func insertTestWorkspace(t *testing.T, b *Backend, key string) (*Workspace, *atomic.Int32) {
    var shutdowns atomic.Int32
    ws := &Workspace{
        ID:           uuid.New().String(),
        Path:         key,
        resolvedPath: key,
        clients:      make(map[string]*clientState),
        shutdownFn:   func() { shutdowns.Add(1) },
    }
    b.mu.Lock()
    b.workspaces.Set(ws.ID, ws)
    b.pathIndex[key] = ws.ID
    b.mu.Unlock()
    return ws, &shutdowns
}

Hold 机制

为防止最后一个客户端断开时工作空间被意外销毁,Crush 实现了引用计数机制(Hold)。

// 资料来源:internal/backend/backend_test.go:60-75
func TestHoldExpiry_TearsDown(t *testing.T) {
    b, srvShutdowns := newTestBackend(t)
    ws, wsShutdowns := insertTestWorkspace(t, b, "/tmp/a")
    
    cid := newClientID(t)
    b.registerClient(ws, cid)
    
    require.Eventually(t, func() bool {
        return wsShutdowns.Load() == 1 && srvShutdowns.Load() == 1
    }, 1*time.Second, 5*time.Millisecond)
}

客户端 API

消息列表获取

// 资料来源:internal/client/proto.go
func (c *Client) ListMessages(ctx context.Context, id string, sessionID string) ([]proto.Message, error) {
    rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/messages", id, sessionID), nil, nil)
    if err != nil {
        return nil, fmt.Errorf("failed to get messages: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("failed to get messages: status code %d", rsp.StatusCode)
    }
    var msgs []proto.Message
    // ...
}

会话摘要

// 资料来源:internal/client/proto.go
func (c *Client) SummarizeSession(ctx context.Context, id string, sessionID string) error {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/sessions/%s/summarize", id, sessionID), nil, nil, nil)
    if err != nil {
        return fmt.Errorf("failed to summarize session: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to summarize session: status code %d", rsp.StatusCode)
    }
    return nil
}

OAuth 令牌刷新

// 资料来源:internal/client/config.go
func (c *Client) RefreshOAuthToken(ctx context.Context, id string, scope config.Scope, providerID string) error {
    // 实现刷新逻辑
}

LSP 事件处理

事件订阅机制

// 资料来源:internal/app/lsp_events.go:40-41
var (
    lspStates = csync.NewMap[string, LSPClientInfo]()
    lspBroker = pubsub.NewBroker[LSPEvent]()
)

状态查询接口

// 资料来源:internal/app/lsp_events.go:53-58
func GetLSPStates() map[string]LSPClientInfo {
    return lspStates.Copy()
}

func GetLSPState(name string) (LSPClientInfo, bool) {
    return lspStates.Get(name)
}

MCP 资源与提示

资源获取

// 资料来源:internal/client/config.go
func (c *Client) GetMCPResource(ctx context.Context, id, clientID, serverID, uri string) ([]MCPResourceContents, error) {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/read-resource", id), nil, jsonBody(struct {
        ClientID string `json:"client_id"`
        URI      string `json:"uri"`
    }{Name: name, URI: uri}), http.Header{"Content-Type": []string{"application/json"}})
    // ...
}

提示获取

// 资料来源:internal/client/config.go
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error) {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/get-prompt", id), nil, jsonBody(struct {
        ClientID string            `json:"client_id"`
        PromptID string            `json:"prompt_id"`
        Args     map[string]string `json:"args"`
    }{ClientID: clientID, PromptID: promptID, Args: args}), http.Header{"Content-Type": []string{"application/json"}})
    // ...
}

权限事件

权限相关事件通过专用的 Payload 类型分发:

// 资料来源:internal/server/events.go
case pubsub.Event[permission.PermissionRequest]:
    return envelope(pubsub.PayloadTypePermissionRequest, pubsub.Event[proto.PermissionRequest]{
        Type: e.Type,
        Payload: proto.PermissionRequest{
            ID:          e.Payload.ID,
            SessionID:   e.Payload.SessionID,
            ToolCallID:  e.Payload.ToolCallID,
            ToolName:    e.Payload.ToolName,
            Description: e.Payload.Description,
            Action:      e.Payload.Action,
            Path:        e.Payload.Path,
            Params:      e.Payload.Params,
        },
    })

清理与关闭

清理函数注册

应用在启动时注册多个清理函数,确保资源正确释放:

// 资料来源:internal/app/testing.go
func (app *App) ShutdownForTest() {
    for _, cleanup := range app.cleanupFuncs {
        if cleanup != nil {
            _ = cleanup(context.Background())
        }
    }
    app.cleanupFuncs = nil
}

清理流程覆盖:

  • 数据库连接释放
  • LSP 服务器关闭
  • MCP 连接断开

已知问题

社区反馈表明数据库损坏是用户遇到的常见问题之一:

用户在 VM 环境中运行 Crush 时,数据库每隔一到两小时就会损坏,出现 "failed to get session message" 错误。

相关社区议题:数据库损坏问题 #2903

配置与持久化路径

Crush 的配置和数据存储位置可通过环境变量覆盖:

环境变量说明
CRUSH_GLOBAL_CONFIG覆盖全局配置文件路径
CRUSH_GLOBAL_DATA覆盖全局数据目录路径
graph TD
    Config[配置文件] --> Priority{配置优先级}
    Priority -->|1| Local1[.crush.json]
    Priority -->|2| Local2[crush.json]
    Priority -->|3| Global[~/.config/crush/crush.json]
    
    Data[数据存储] --> Platform{平台}
    Platform -->|Unix| UnixPath[$HOME/.local/share/crush/]
    Platform -->|Windows| WinPath[%LOCALAPPDATA%\crush\]

测试覆盖

事件系统的测试确保数据在序列化和反序列化过程中不丢失:

// 资料来源:internal/server/events_test.go
func TestSkillsEventToProto_RoundTrip(t *testing.T) {
    src := pubsub.Event[skills.Event]{
        Type: pubsub.UpdatedEvent,
        Payload: skills.Event{
            States: []*skills.SkillState{
                {Name: "ok", Path: "/p/ok", State: skills.StateNormal},
                {Name: "broken", Path: "/p/broken", State: skills.StateError, Err: errors.New("bad frontmatter")},
            },
        },
    }
    env := wrapEvent(src)
    // 验证往返转换正确性
}

总结

Crush 的数据流与数据库系统通过事件驱动的架构实现了组件间的高效解耦。Protocol Buffer 格式确保了跨网络通信的类型安全,Hold 机制防止了工作空间的意外销毁,而清理函数则保证了资源的正确释放。开发者若需扩展新的事件类型,应遵循 events.go 中定义的转换模式,并在 proto.go 中添加对应的消息类型。

来源:https://github.com/charmbracelet/crush / 项目说明书

Agent 系统

Crush 的 Agent 系统是整个应用的核心组件,负责协调 AI 模型与工作区之间的交互。该系统处理 Agent 消息、会话管理、事件分发等核心功能,支持多客户端同时连接和工作区隔离。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 Server Controller

继续阅读本节完整说明和来源证据。

章节 事件类型

继续阅读本节完整说明和来源证据。

章节 Agent 事件类型

继续阅读本节完整说明和来源证据。

概述

Crush 的 Agent 系统是整个应用的核心组件,负责协调 AI 模型与工作区之间的交互。该系统处理 Agent 消息、会话管理、事件分发等核心功能,支持多客户端同时连接和工作区隔离。

Agent 系统采用客户端-服务器架构,通过 HTTP API 和 Server-Sent Events (SSE) 实现与前端的通信。

架构概览

graph TD
    A[Client] -->|HTTP/WebSocket| B[Server Controller]
    B --> C[Backend]
    C --> D[Agent]
    C --> E[Workspace Manager]
    C --> F[Event Broker]
    
    F -->|SSE Events| A
    
    D -->|Tool Calls| G[Permission System]
    G -->|Approved| H[Tool Executor]
    H -->|Results| D
    
    D -->|Messages| I[LLM Provider]
    I -->|Responses| D

核心组件

Server Controller

internal/server/proto.go 中的 Controller 负责处理 Agent 相关的 HTTP 请求。主要端点包括:

端点方法功能
/workspaces/{id}/agentPOST发送 Agent 消息
/workspaces/{id}/agent/initPOST初始化 Agent 处理
/workspaces/{id}/agent/sessionsGET列出所有会话
/workspaces/{id}/agent/sessions/{sessionID}/summarizePOST汇总会话

#### 消息处理流程

// handlePostWorkspaceAgent 处理 Agent 消息
// 资料来源:internal/server/proto.go:XX
func (c *controllerV1) handlePostWorkspaceAgent(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")

    var msg proto.AgentMessage
    if err := json.NewDecoder(r.Body).Decode(&msg); err != nil {
        c.server.logError(r, "Failed to decode request", "error", err)
        jsonError(w, http.StatusBadRequest, "failed to decode request")
        return
    }

    // 使用 WithoutCancel 分离请求生命周期
    ctx := context.WithoutCancel(r.Context())
    if err := c.backend.SendMessage(ctx, id, msg); err != nil {
        c.handleError(w, r, err)
        return
    }
    w.WriteHeader(http.StatusOK)
}

关键设计点:

  • 使用 context.WithoutCancel() 分离运行生命周期,避免客户端断连导致正在进行的操作被取消
  • 只有显式的取消端点才能终止运行

事件系统

事件类型

internal/server/events.go 定义了 Agent 系统支持的事件类型:

case pubsub.Event[proto.AgentEvent]:
    return envelope(pubsub.PayloadTypeAgentEvent, pubsub.Event[proto.AgentEvent]{
        Type: e.Type,
        Payload: proto.AgentEvent{
            SessionID:    e.Payload.SessionID,
            SessionTitle: e.Payload.SessionTitle,
            Type:         proto.AgentEventType(e.Payload.Type),
        },
    })

Agent 事件类型

事件类型说明
AgentEventTypeResponseAgent 响应事件
AgentEventTypeErrorAgent 错误事件
AgentEventTypeCompleteAgent 完成事件

事件封装机制

所有事件通过统一的 envelope 函数进行 JSON 序列化:

// envelope marshals the inner event and wraps it in a pubsub.Payload
// 资料来源:internal/server/events.go:XX
func envelope(payloadType pubsub.PayloadType, inner any) *pubsub.Payload {
    raw, err := json.Marshal(inner)
    if err != nil {
        slog.Error("Failed to marshal event payload", "error", err)
        return nil
    }
    return &pubsub.Payload{
        Type:    payloadType,
        Payload: raw,
    }
}

客户端 API

Agent 操作

internal/client/proto.go 提供了完整的 Agent 客户端接口:

#### 发送消息

// SendMessage sends a message to the agent
// 资料来源:internal/client/proto.go:XX
func (c *Client) SendMessage(ctx context.Context, id string, msg proto.AgentMessage) error {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent", id), nil, jsonBody(msg), http.Header{"Content-Type": []string{"application/json"}})
    if err != nil {
        return fmt.Errorf("failed to send message: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to send message: status code %d", rsp.StatusCode)
    }
    return nil
}

#### 初始化 Agent 处理

// InitiateAgentProcessing triggers agent initialization on the server
// 资料来源:internal/client/proto.go:XX
func (c *Client) InitiateAgentProcessing(ctx context.Context, id string) error {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/init", id), nil, nil, nil)
    if err != nil {
        return fmt.Errorf("failed to initiate session agent processing: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to initiate session agent processing: status code %d", rsp.StatusCode)
    }
    return nil
}

#### 会话汇总

// Summarize generates a summary of the conversation
// 资料来源:internal/client/proto.go:XX
func (c *Client) Summarize(ctx context.Context, id, sessionID string) error {
    rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/sessions/%s/summarize", id, sessionID), nil, nil, nil)
    if err != nil {
        return fmt.Errorf("failed to summarize session: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to summarize session: status code %d", rsp.StatusCode)
    }
    return nil
}

配置管理

Agent 配置 API

internal/client/config.go 提供了 Agent 配置相关的 API:

#### 设置默认模型

// SetDefaultAgentModel sets the default agent model
// 资料来源:internal/client/config.go:XX
func (c *Client) SetDefaultAgentModel(ctx context.Context, id string, modelID, providerID string) error {
    _, err := c.patch(ctx, fmt.Sprintf("/workspaces/%s/agent/default-model", id),
        url.Values{"model_id": []string{modelID}, "provider_id": []string{providerID}}, nil, nil)
    if err != nil {
        return fmt.Errorf("failed to set default agent model: %w", err)
    }
    return nil
}

#### 设置默认小型模型

// SetDefaultSmallModel sets the default small model for quick operations
// 资料来源:internal/client/config.go:XX
func (c *Client) SetDefaultSmallModel(ctx context.Context, id, modelID, providerID string) error {
    _, err := c.patch(ctx, fmt.Sprintf("/workspaces/%s/agent/default-small-model", id),
        url.Values{"model_id": []string{modelID}, "provider_id": []string{providerID}}, nil, nil)
    if err != nil {
        return fmt.Errorf("failed to set default small model: %w", err)
    }
    return nil
}

#### 获取默认模型

// GetDefaultSmallModel returns the default small model for the workspace
// 资料来源:internal/client/config.go:XX
func (c *Client) GetDefaultSmallModel(ctx context.Context, id, providerID string) (*config.SelectedModel, error) {
    rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/agent/default-small-model", id), url.Values{"provider_id": []string{providerID}}, nil)
    if err != nil {
        return nil, fmt.Errorf("failed to get default small model: %w", err)
    }
    defer rsp.Body.Close()
    if rsp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("failed to get default small model: status code %d", rsp.StatusCode)
    }
    var model config.SelectedModel
    if err := json.NewDecoder(rsp.Body).Decode(&model); err != nil {
        return nil, fmt.Errorf("failed to decode default small model: %w", err)
    }
    return &model, nil
}

事件订阅与分发

LSP 事件集成

虽然 LSP 系统是独立的,但 Agent 系统通过事件总线与其交互:

// LSPEvent represents an event in the LSP system
// 资料来源:internal/app/lsp_events.go:XX
type LSPEvent struct {
    Type            LSPEventType
    Name            string
    State           lsp.ServerState
    Error           error
    DiagnosticCount int
}

事件订阅机制:

// SubscribeLSPEvents returns a channel for LSP events
// 资料来源:internal/app/lsp_events.go:XX
func SubscribeLSPEvents(ctx context.Context) <-chan pubsub.Event[LSPEvent] {
    return lspBroker.Subscribe(ctx)
}

消息协议

Agent 消息结构

Agent 消息通过 proto.AgentMessage 类型传输,包含:

字段类型说明
SessionIDstring会话标识符
TypeAgentMessageType消息类型
Contentstring消息内容
Metadatamap元数据

事件有效载荷类型

类型说明资料来源
PayloadTypeAgentEventAgent 事件internal/server/events.go
PayloadTypeRunComplete运行完成internal/server/events.go
PayloadTypePermissionRequest权限请求internal/server/events.go
PayloadTypePermissionNotification权限通知internal/server/events.go

工作流程

sequenceDiagram
    participant C as Client
    participant S as Server
    participant B as Backend
    participant A as Agent
    participant E as Event Broker
    
    C->>S: POST /agent (AgentMessage)
    S->>B: SendMessage(ctx, msg)
    B->>A: Process Message
    A->>A: LLM Inference
    A->>A: Tool Execution
    A-->>E: AgentEvent
    E-->>C: SSE Stream
    A-->>B: Response
    B-->>S: Result
    S-->>C: HTTP 200 OK

测试覆盖

事件系统具有完整的测试覆盖:

// TestSkillsEventToProto_RoundTrip verifies that a pubsub.Event[skills.Event]
// can be wrapped, marshaled, and unmarshaled back through the SSE
// envelope without losing state values or error messages
// 资料来源:internal/server/events_test.go:XX
func TestSkillsEventToProto_RoundTrip(t *testing.T) {
    t.Parallel()
    // 测试事件序列化与反序列化
}

配置选项

Agent 系统支持通过 crush.json 进行配置:

{
  "agent": {
    "default_model": "claude-sonnet-4-20250514",
    "default_small_model": "claude-haiku-4-20250514"
  }
}

相关社区讨论

  • #990: 支持 Agent Client Protocol 以与 IDE 集成
  • #431: 子代理功能请求 - 支持配置子代理及其各自模型
  • #372: Claude Code SDK 支持请求

扩展阅读

来源:https://github.com/charmbracelet/crush / 项目说明书

工具系统

Crush 的工具系统是 Agent 与外部环境交互的核心模块,负责执行文件操作、Shell 命令、代码编辑等任务。该系统支持多种工具类型,并通过权限控制机制确保操作安全性。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 权限请求类型

继续阅读本节完整说明和来源证据。

章节 权限请求数据结构

继续阅读本节完整说明和来源证据。

章节 权限事件序列化

继续阅读本节完整说明和来源证据。

系统架构

Crush 采用客户端-服务端架构,工具系统在服务端执行,操作结果通过事件机制通知客户端。

graph TD
    A[Agent] -->|工具调用请求| B[服务端工具调度器]
    B -->|权限检查| C[权限系统]
    C -->|批准/拒绝| D{权限决策}
    D -->|批准| E[工具执行器]
    D -->|拒绝| F[返回权限拒绝]
    E --> G[bash工具]
    E --> H[文件编辑工具]
    E --> I[写入工具]
    E --> J[grep工具]
    G -->|事件| K[事件总线]
    H --> K
    I --> K
    J --> K
    K -->|SSE推送| L[客户端]

权限系统

权限系统是工具安全执行的核心,负责在工具执行前进行授权检查。

权限请求类型

权限系统定义了两种主要的事件类型,用于跟踪工具调用状态:

事件类型说明
PermissionRequest工具执行前的授权请求
PermissionNotification工具执行完成的通知

权限请求数据结构

权限请求包含以下关键字段,用于识别和控制工具操作:

type PermissionRequest struct {
    ID          string            // 唯一请求标识符
    SessionID   string            // 会话标识符
    ToolCallID  string            // 工具调用标识符
    ToolName    string            // 工具名称
    Description string            // 操作描述
    Action      string            // 请求的操作类型
    Path        string            // 目标路径(如适用)
    Params      map[string]any    // 操作参数
}

资料来源:internal/server/events.go:24-35

权限事件序列化

权限事件通过 protobuf 定义进行序列化,支持在客户端-服务端之间传输:

return envelope(pubsub.PayloadTypePermissionRequest, pubsub.Event[proto.PermissionRequest]{
    Type: e.Type,
    Payload: proto.PermissionRequest{
        ID:          e.Payload.ID,
        SessionID:   e.Payload.SessionID,
        ToolCallID:  e.Payload.ToolCallID,
        ToolName:    e.Payload.ToolName,
        Description: e.Payload.Description,
        Action:      e.Payload.Action,
        Path:        e.Payload.Path,
        Params:      e.Payload.Params,
    },
})

资料来源:internal/server/events.go:34-47

内置工具类型

Bash 工具

Bash 工具允许 Agent 执行 Shell 命令,是与系统交互的主要方式。

社区关注点: 用户反馈当前对 bash 命令存在安全限制,阻止了 curlwgetsshsudo 等命令的执行,这影响了开发测试工作流。

参考:Issue #928 - Remove bash command security limits for unrestricted terminal access

已知问题: 在 v0.74.1 版本中修复了交互式命令(如 git rebase -i)导致的 bash 工具挂起问题。

文件编辑工具

支持对文件内容进行编辑操作,包括行级修改和内容替换。

文件写入工具

提供完整的文件写入能力,用于创建新文件或覆盖现有文件内容。

Grep 工具

实现代码搜索功能,支持在项目中查找指定模式的内容。

Safe 模式工具

提供额外的安全检查层,在执行敏感操作前进行额外验证。

工具配置

权限模式配置

crush.json 中通过 permissions.yolo 开关控制权限模式:

{
  "$schema": "https://charm.land/crush.json",
  "permissions": {
    "yolo": false
  }
}
模式说明
yolo: true启用全自动化批准,所有工具调用无需确认
yolo: false启用安全模式,每项操作需用户确认

社区需求: Issue #2935 请求支持在运行时动态切换权限配置文件(Yolo、Safe、Custom),而无需重启会话。

参考:Issue #2935 - Feature: Multiple permission profiles/modes switchable at runtime

MCP 工具集成

Crush 支持通过 Model Context Protocol (MCP) 扩展工具集。MCP 服务器通过三种传输类型连接:

传输类型说明
stdio命令行服务器模式
httpHTTP 端点模式
sseServer-Sent Events 模式

MCP 工具调用通过客户端 API 执行:

// 获取 MCP 资源
func (c *Client) GetMCPResource(ctx context.Context, id, clientID, resourceID string) ([]MCPResourceContents, error)

// 获取 MCP 提示
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error)

资料来源:internal/client/config.go:85-110

事件驱动通信

工具执行状态通过发布-订阅模式在系统内传播,客户端通过 SSE 连接接收实时更新。

sequenceDiagram
    participant A as Agent
    participant E as 事件总线
    participant S as SSE服务端
    participant C as 客户端

    A->>E: 发布工具事件
    E->>S: 事件推送
    S->>C: SSE Stream
    C-->>A: 用户反馈

工具计数事件

MCP 工具事件携带工具计数信息:

case pubsub.Event[mcp.Event]:
    return envelope(pubsub.PayloadTypeMCPEvent, pubsub.Event[proto.MCPEvent]{
        Type: e.Type,
        Payload: proto.MCPEvent{
            Type:      mcpEventTypeToProto(e.Payload.Type),
            Name:      e.Payload.Name,
            State:     proto.MCPState(e.Payload.State),
            Error:     e.Payload.Error,
            ToolCount: e.Payload.Counts.Tools,
        },
    })

资料来源:internal/server/events.go:21-33

API 密钥管理

工具系统中的外部服务调用需要相应的 API 密钥支持:

环境变量提供商
OPENAI_API_KEYOpenAI
ANTHROPIC_API_KEYAnthropic
OPENROUTER_API_KEYOpenRouter
OPENCODE_API_KEYOpenCode
DEEPSEEK_API_KEYDeepSeek

客户端提供设置提供商 API 密钥的方法:

func (c *Client) SetProviderAPIKey(ctx context.Context, id string, scope config.Scope, providerID string, apiKey any) error

资料来源:internal/client/config.go:145-170

错误处理与状态管理

工具执行可能遇到多种错误情况,系统通过事件机制传播错误状态:

type LSPEvent struct {
    Type            LSPEventType
    Name            string
    State           lsp.ServerState
    Error           error
    DiagnosticCount int
}

资料来源:internal/app/lsp_events.go:24-30

最佳实践

  1. 安全优先:在公共或共享环境中使用 yolo: false 模式,防止未经授权的操作
  2. 渐进式配置:从安全模式开始,逐步添加可信工具到白名单
  3. 会话隔离:每个工作区维护独立的权限上下文
  4. 错误监控:通过事件订阅机制实时监控工具执行状态

资料来源:internal/server/events.go:24-35

技能系统

Crush 的技能系统(Skills System)是一个扩展代理能力的框架,基于 Agent Skills 开放标准实现。技能系统允许用户通过可复用的技能包来扩展 Crush 的功能,这些技能包以包含 SKILL.md 说明文件的文件夹形式存在,Crush 可以按需发现和激活这些技能。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 技能搜索路径

继续阅读本节完整说明和来源证据。

章节 技能包结构

继续阅读本节完整说明和来源证据。

章节 状态数据结构

继续阅读本节完整说明和来源证据。

概述

Crush 的技能系统(Skills System)是一个扩展代理能力的框架,基于 Agent Skills 开放标准实现。技能系统允许用户通过可复用的技能包来扩展 Crush 的功能,这些技能包以包含 SKILL.md 说明文件的文件夹形式存在,Crush 可以按需发现和激活这些技能。

技能系统的核心设计目标是:

  • 模块化扩展:通过独立技能包扩展代理能力
  • 按需激活:技能在需要时被发现和加载,而非全部预加载
  • 多路径支持:支持全局技能路径和项目本地路径
  • 跨平台兼容:支持 Unix、Windows 等多平台文件系统布局

技能发现机制

技能搜索路径

Crush 在多个位置搜索技能包,按照优先级和作用域分类。

#### 全局技能路径

环境变量/路径描述
$CRUSH_SKILLS_DIR用户指定的技能目录
$XDG_CONFIG_HOME/agents/skillsAgent Skills 标准目录
$XDG_CONFIG_HOME/crush/skillsCrush 专用技能目录
~/.agents/skills/Claude 兼容路径
~/.claude/skills/Claude 兼容路径
Windows: %LOCALAPPDATA%\agents\skills\Windows 全局路径
Windows: %LOCALAPPDATA%\crush\skills\Windows Crush 专用
配置来源:README.md

#### 项目本地技能路径

相对路径描述
.agents/skills标准 agent 技能目录
.crush/skillsCrush 项目目录
.claude/skillsClaude 兼容目录
.cursor/skillsCursor IDE 兼容目录

项目本地技能路径支持项目级别的技能共享,无需全局安装。

#### 自定义技能路径

可通过配置文件指定额外的技能搜索路径:

{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "skills_paths": [
      "~/.config/crush/skills",
      "./project-skills"
    ]
  }
}

技能包结构

技能包是一个文件夹,包含至少一个 SKILL.md 文件:

skill-name/
└── SKILL.md    # 必需:技能说明文件

SKILL.md 文件包含技能的指令说明,Crush 会读取并使用这些内容来理解和执行技能任务。

技能状态管理

状态数据结构

技能状态通过 skills.Eventskills.SkillState 类型管理:

type SkillState struct {
    Name  string                     // 技能名称
    Path  string                     // 技能路径
    State SkillDiscoveryState        // 发现状态
    Err   error                      // 错误信息(如果有)
}

技能发现状态

状态值描述
StateNormal技能正常加载
StateError技能加载失败,包含错误信息
配置来源:internal/server/events.go:71-72

事件通知机制

技能系统通过事件发布订阅机制通知状态变更:

type SkillsEvent struct {
    States []SkillState  // 所有技能的状态列表
}

当技能发现过程完成或发生变化时,系统发布 SkillsEvent,客户端可以订阅这些事件以更新 UI。

配置来源:internal/server/events.go:64-76

技能事件序列化

技能事件在客户端-服务器通信中需要进行序列化。以下函数负责将内部事件转换为协议缓冲区格式:

func skillsEventToProto(e skills.Event) proto.SkillsEvent {
    if len(e.States) == 0 {
        return proto.SkillsEvent{}
    }
    out := proto.SkillsEvent{States: make([]proto.SkillState, len(e.States))}
    for i, s := range e.States {
        entry := proto.SkillState{
            Name:  s.Name,
            Path:  s.Path,
            State: proto.SkillDiscoveryState(s.State),
        }
        if s.Err != nil {
            entry.Error = s.Err.Error()
        }
        out.States[i] = entry
    }
    return out
}
配置来源:internal/server/events.go:95-111

往返序列化测试

技能事件支持完整的往返序列化:

func TestSkillsEventToProto_RoundTrip(t *testing.T) {
    src := pubsub.Event[skills.Event]{
        Type: pubsub.UpdatedEvent,
        Payload: skills.Event{
            States: []*skills.SkillState{
                {Name: "ok", Path: "/p/ok", State: skills.StateNormal},
                {Name: "broken", Path: "/p/broken", State: skills.StateError, Err: errors.New("bad frontmatter")},
            },
        },
    }
    // 测试事件包装、序列化、反序列化过程
}
配置来源:internal/server/events_test.go:89-106

内置技能

Crush 附带了一些内置技能:

技能名称功能描述
crush-config配置 Crush 本身

禁用内置技能

可以通过配置禁用内置技能:

{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disabled_skills": ["crush-config"]
  }
}
配置来源:README.md

技能管理器架构

graph TD
    A[技能管理器] --> B[技能目录 Catalog]
    A --> C[技能发现器 Discoverer]
    A --> D[技能加载器 Loader]
    A --> E[事件发布器 Broker]
    
    B --> F[全局路径]
    B --> G[项目路径]
    B --> H[自定义路径]
    
    E --> I[Server-Sent Events]
    E --> J[WebSocket]
    
    C --> K[文件系统扫描]
    C --> L[SKILL.md 解析]

配置选项汇总

配置项类型默认值描述
skills_paths[]string[]额外的技能搜索路径
disabled_skills[]string[]禁用的内置技能列表

常见问题

技能路径环境变量

可以通过设置 CRUSH_SKILLS_DIR 环境变量指定额外的技能目录:

export CRUSH_SKILLS_DIR=/path/to/my/skills

Windows 路径兼容性

Windows 平台使用 %LOCALAPPDATA% 变量,配置文件示例:

{
  "options": {
    "skills_paths": [
      "%LOCALAPPDATA%\\crush\\skills"
    ]
  }
}
配置来源:README.md

技能加载失败处理

当技能 SKILL.md 文件格式错误或路径不可访问时,该技能会标记为 StateError 状态,错误信息通过 Err 字段传递。单个技能加载失败不会影响其他技能。

来源:https://github.com/charmbracelet/crush / 项目说明书

配置系统

Crush 的配置系统负责管理应用程序的全局设置、用户偏好、模型提供者和运行时选项。该系统采用分层配置架构,支持本地项目和全局配置的优先级覆盖,同时提供灵活的环境变量扩展机制。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 配置层级

继续阅读本节完整说明和来源证据。

章节 数据存储位置

继续阅读本节完整说明和来源证据。

章节 加载流程图

继续阅读本节完整说明和来源证据。

配置架构概述

Crush 的配置系统采用三层架构设计,各层之间按优先级从高到低覆盖,形成统一配置视图。

配置层级

层级配置文件位置优先级作用域
本地项目配置.crush.json最高当前项目目录
工作目录配置crush.json执行命令的工作目录
全局用户配置~/.config/crush/crush.json最低当前用户所有项目

配置加载时会按上述顺序搜索配置文件,相同键值在高优先级配置中出现时将覆盖低优先级配置。资料来源:README.md

数据存储位置

除了 JSON 配置文件外,Crush 还使用以下数据存储路径:

操作系统用户数据目录全局配置覆盖变量
Unix/Linux$HOME/.local/share/crush/crush.jsonCRUSH_GLOBAL_DATA
Windows%LOCALAPPDATA%\crush\crush.jsonCRUSH_GLOBAL_DATA
Unix/Linux$HOME/.config/crush/crush.jsonCRUSH_GLOBAL_CONFIG
Windows%APPDATA%\crush\crush.jsonCRUSH_GLOBAL_CONFIG

环境变量 CRUSH_GLOBAL_CONFIGCRUSH_GLOBAL_DATA 可分别覆盖全局配置和用户数据存储路径。资料来源:README.md

配置加载流程

配置加载由 internal/config/load.go 模块处理,采用懒加载和缓存机制确保性能。

加载流程图

graph TD
    A[启动 Crush] --> B{检查缓存}
    B -->|缓存未命中| C[查找配置文件]
    C --> D[搜索 .crush.json]
    C --> E[搜索 crush.json]
    C --> F[搜索 ~/.config/crush/crush.json]
    D --> G{找到配置文件?}
    E --> G
    F --> G
    G -->|是| H[合并配置层级]
    G -->|否| I[使用空配置]
    H --> J[展开环境变量]
    J --> K[缓存配置对象]
    I --> K
    K --> L[返回 Config 结构]

配置加载器会递归合并各层级的配置对象,使用 JSON Schema 验证配置格式。资料来源:internal/config/load.go

配置结构

核心配置项

Crush 的配置文件采用 JSON 格式,支持以下顶层配置块:

{
  "$schema": "https://charm.land/crush.json",
  "providers": {},
  "lsp": {},
  "mcp": {},
  "options": {},
  "permissions": {},
  "hooks": {}
}
配置块类型说明
providersobjectAI 模型提供者配置
lspobject语言服务器协议配置
mcpobjectModel Context Protocol 配置
optionsobject全局运行选项
permissionsobject权限控制配置
hooksobject钩子脚本配置

资料来源:schema.json

提供者配置

提供者(Provider)是 Crush 与各种 AI 模型服务交互的核心组件。

内置提供者支持

Crush 支持以下内置 AI 模型提供者,通过相应的环境变量配置 API 密钥:

环境变量提供者
ANTHROPIC_API_KEYAnthropic (Claude)
OPENAI_API_KEYOpenAI
DEEPSEEK_API_KEYDeepseek
OPENROUTER_API_KEYOpenRouter
GOOGLE_API_KEY / GEMINI_API_KEYGoogle Gemini
VERTEXAI_PROJECT / VERTEXAI_LOCATIONGoogle VertexAI
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYAmazon Bedrock (Claude)
AZURE_OPENAI_API_ENDPOINTAzure OpenAI
GROQ_API_KEYGroq
HF_TOKENHugging Face Inference
CEREBRAS_API_KEYCerebras
OPENCODE_API_KEYOpenCode Zen & Go
HYPER_API_KEYHyper (Charm)

资料来源:README.md

自定义提供者

Crush 支持通过配置文件定义自定义提供者,分为 OpenAI 兼容和 Anthropic 兼容两种类型:

#### OpenAI 兼容 API

{
  "providers": {
    "deepseek": {
      "type": "openai-compat",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "$DEEPSEEK_API_KEY"
    }
  }
}
注意:选择正确的类型非常重要。使用 openai 类型用于通过 OpenAI 代理或路由的请求,使用 openai-compat 类型用于非 OpenAI 但提供 OpenAI 兼容 API 的提供商。资料来源:README.md

#### Anthropic 兼容 API

{
  "providers": {
    "custom-anthropic": {
      "type": "anthropic-compat",
      "base_url": "https://your-custom-endpoint.com/v1",
      "api_key": "$CUSTOM_ANTHROPIC_KEY"
    }
  }
}

LSP 配置

语言服务器协议(LSP)配置使 Crush 能够获取额外的上下文信息来辅助决策。

LSP 配置示例

{
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "go1.24.5"
      }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    },
    "nix": {
      "command": "nil"
    }
  }
}

每个 LSP 服务器配置包含以下字段:

字段类型说明
commandstringLSP 服务器可执行命令
argsarray命令行参数
envobject环境变量
root_markersarray工作目录标记文件
filetypesarray支持的文件类型
已知问题:社区反馈全局 LSP 配置有时不生效,需要确保配置文件位于正确路径 ~/.config/crush/crush.json。资料来源:README.md

MCP 配置

Model Context Protocol (MCP) 配置支持三种传输类型:

传输类型说明使用场景
stdio标准输入输出命令行 MCP 服务器
httpHTTP 请求REST API 端点
sseServer-Sent Events实时事件流

Shell 变量扩展

MCP 配置支持完整的 Shell 风格变量扩展:

{
  "mcp": {
    "github": {
      "command": "uvx",
      "args": ["mcp-github", "--token", "$GITHUB_TOKEN"]
    }
  }
}

支持的扩展语法包括:

  • $VAR - 基本变量引用
  • ${VAR:-default} - 带默认值的变量
  • $(command) - 命令替换
  • 嵌套引用和转义
变量扩展通过 Crush 内置的 Shell 解释器执行,确保在 Windows 和 Unix 系统上行为一致。资料来源:README.md

选项配置

options 配置块控制 Crush 的运行时行为。

可用选项

选项类型默认值说明
compactbooleanfalse紧凑模式,减少输出
no_env_expansionbooleanfalse禁用环境变量扩展
no_outputbooleanfalse禁用所有输出
verbosebooleanfalse详细输出模式
hooks_pathstring-自定义钩子脚本路径
skills_pathsarray-技能目录路径列表
disabled_skillsarray-禁用的技能列表
trailer_stylestring"assisted-by"提交消息归属风格
generated_withbooleantrue添加生成标记

提交消息归属风格

效果
assisted-by添加 Assisted-by: Crush:[ModelID]
co-authored-by添加 Co-Authored-By: Crush <[email protected]>
none不添加归属信息

资料来源:README.md

权限配置

权限系统控制工具调用的安全策略。

当前限制

当前版本仅支持全局 permissions.yolo 开关,无法在运行时动态切换权限模式。社区有计划实现多权限配置文件(Yolo、Safe、Custom)在运行时切换的功能。资料来源:社区 Issue #2935

权限配置示例

{
  "permissions": {
    "yolo": true
  }
}

yolo 设置为 true 时,所有工具调用将被自动批准,无需用户确认。

技能配置

Crush 支持 Agent Skills 开放标准,通过技能包扩展代理能力。

技能搜索路径

系统按以下顺序搜索技能目录:

优先级路径(Unix)路径(Windows)
1$CRUSH_SKILLS_DIR$CRUSH_SKILLS_DIR
2$XDG_CONFIG_HOME/agents/skills%LOCALAPPDATA%\agents\skills
3$XDG_CONFIG_HOME/crush/skills%LOCALAPPDATA%\crush\skills
4~/.agents/skills%USERPROFILE%\.agents\skills
5~/.claude/skills%USERPROFILE%\.claude\skills
6自定义 skills_paths自定义 skills_paths

项目本地技能路径:

  • .agents/skills
  • .crush/skills
  • .claude/skills
  • .cursor/skills

自定义技能路径配置

{
  "options": {
    "skills_paths": [
      "~/.config/crush/skills",
      "./project-skills"
    ]
  }
}

配置验证

Crush 配置文件遵循 JSON Schema 规范,位于项目根目录的 schema.json

Schema 验证

使用 $schema 字段声明配置文件的规范版本:

{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disabled_skills": ["crush-config"]
  }
}

IDE 可利用 schema 提供自动补全和配置验证功能。资料来源:schema.json

客户端-服务端配置同步

当启用实验性的客户端-服务端架构(CRUSH_CLIENT_SERVER=1)时,配置通过 HTTP API 同步。

客户端配置 API

方法端点功能
GET/config获取全局服务器配置
POST/workspaces/{id}/config/preferred-model设置首选模型
POST/workspaces/{id}/config/compact设置紧凑模式
POST/workspaces/{id}/config/provider-api-key设置提供者 API 密钥

API 密钥类型处理

客户端使用显式类型标记 API 密钥,确保跨 Socket 传输时正确解码:

switch v := apiKey.(type) {
case string:
    kind = proto.APIKeyKindApiKey
case *oauth2.Token:
    kind = proto.APIKeyKindOAuthToken
}

资料来源:internal/client/config.go

配置示例

完整配置示例

{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "deepseek": {
      "type": "openai-compat",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "$DEEPSEEK_API_KEY"
    },
    "custom": {
      "type": "anthropic-compat",
      "base_url": "https://api.custom.com/v1",
      "api_key": "$CUSTOM_API_KEY"
    }
  },
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "auto"
      }
    }
  },
  "options": {
    "skills_paths": [
      "~/.config/crush/skills"
    ],
    "trailer_style": "assisted-by",
    "generated_with": true
  },
  "permissions": {
    "yolo": false
  }
}

最佳实践

  1. 使用 Schema:在配置文件中声明 $schema 以获得 IDE 自动补全支持
  2. 环境变量:敏感信息(如 API 密钥)应使用环境变量引用
  3. 项目级配置:项目特定配置放在 .crush.json,避免污染全局配置
  4. 权限策略:生产环境建议关闭 yolo 模式,使用安全权限策略
  5. LSP 配置:为常用编程语言配置 LSP 以提升上下文理解能力

资料来源:schema.json

LSP 与 MCP 集成

Crush 通过集成 LSP (Language Server Protocol) 和 MCP (Model Context Protocol) 两大协议,实现了强大的代码上下文理解和工具扩展能力。LSP 为 Crush 提供代码诊断、符号解析等语言服务功能,而 MCP 则允许通过外部服务器扩展工具、资源和提示词能力。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 整体架构图

继续阅读本节完整说明和来源证据。

章节 核心组件

继续阅读本节完整说明和来源证据。

章节 功能特性

继续阅读本节完整说明和来源证据。

概述

Crush 通过集成 LSP (Language Server Protocol)MCP (Model Context Protocol) 两大协议,实现了强大的代码上下文理解和工具扩展能力。LSP 为 Crush 提供代码诊断、符号解析等语言服务功能,而 MCP 则允许通过外部服务器扩展工具、资源和提示词能力。

这两套系统共享统一的事件发布订阅机制,能够在服务端和客户端之间高效传递状态变化信息。 资料来源:internal/app/lsp_events.go:1-20

架构设计

整体架构图

graph TB
    subgraph "客户端层"
        CLI[CLI 客户端]
        WEB[Web 客户端]
    end
    
    subgraph "服务端层"
        SERVER[HTTP Server]
        BACKEND[Backend]
    end
    
    subgraph "集成层"
        LSP_MGR[LSP Manager]
        MCP[MCP 运行时]
    end
    
    subgraph "协议层"
        LSP[LSP Clients]
        STDIO[stdio 传输]
        HTTP[HTTP 传输]
        SSE[SSE 传输]
    end
    
    CLI --> SERVER
    WEB --> SERVER
    SERVER --> BACKEND
    BACKEND --> LSP_MGR
    BACKEND --> MCP
    LSP_MGR --> LSP
    MCP --> STDIO
    MCP --> HTTP
    MCP --> SSE

核心组件

组件位置职责
LSPManagerinternal/lsp/manager.go管理多个 LSP 客户端生命周期
LSPClientinternal/lsp/client.go与单个语言服务器通信
MCPRuntimeinternal/agent/tools/mcp/管理 MCP 服务器连接
LSPBrokerinternal/app/lsp_events.go分发 LSP 事件
MCPToolinternal/agent/tools/mcp/tools.goMCP 工具调用封装

LSP 集成

功能特性

LSP 集成使 Crush 能够获取语言的诊断信息、代码结构等上下文,帮助 AI 模型做出更准确的决策。主要功能包括:

  • 多语言支持:可同时管理多个 LSP 客户端
  • 实时诊断:接收并展示代码诊断信息
  • 状态追踪:监控 LSP 服务器连接状态
  • 热配置:支持在工作空间中动态启动/停止 LSP 服务器

事件系统

LSP 事件通过 pubsub.Broker 进行分发,支持两种事件类型:

事件类型说明
state_changedLSP 服务器状态变更(连接/断开/错误)
diagnostics_changed诊断信息更新
// internal/app/lsp_events.go:14-19
type LSPEvent struct {
    Type            LSPEventType
    Name            string
    State           lsp.ServerState
    Error           error
    DiagnosticCount int
}

客户端状态管理

每个 LSP 客户端维护以下状态信息:

// internal/app/lsp_events.go:23-31
type LSPClientInfo struct {
    Name            string
    State           lsp.ServerState
    Error           error
    Client          *lsp.Client
    DiagnosticCount int
    ConnectedAt     time.Time
}

状态通过 csync.NewMapstring, LSPClientInfo 线程安全存储在内存中。 资料来源:internal/app/lsp_events.go:35-36

工作空间 LSP 操作

服务端暴露了完整的 LSP 管理 API:

// internal/backend/events.go:120-135
func (b *Backend) GetLSPDiagnostics(workspaceID, lspName string) (any, error)
func (b *Backend) LSPStart(ctx context.Context, workspaceID, path string) error
func (b *Backend) LSPStopAll(ctx context.Context, workspaceID string) error

配置方式

crush.json 中配置 LSP 服务器:

{
  "$schema": "https://charm.land/crush.json",
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "go1.24.5"
      }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    },
    "nix": {
      "command": "nil"
    },
    "deno": {
      "command": "deno",
      "args": ["lsp"],
      "root_markers": ["deno.lock", "deno.json"],
      "filetypes": ["js", "ts", "jsx", "tsx", "json"]
    }
  }
}
注意:LSP 配置目前仅在项目级别生效,不支持全局配置。这与 Issue #2898 中用户反馈的问题一致。

MCP 集成

协议概述

MCP (Model Context Protocol) 是一种用于扩展 AI 代理能力的标准协议。Crush 支持 MCP 服务器的三种传输类型:

传输类型说明典型用途
stdio标准输入输出命令行 MCP 服务器
httpHTTP RESTWeb API 服务器
sseServer-Sent Events实时事件推送

配置结构

{
  "mcp": {
    "servers": {
      "my-server": {
        "transport": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"]
      }
    }
  }
}

Shell 值展开

MCP 配置支持 bash 风格的变量展开:

  • $VAR:简单变量引用
  • ${VAR:-default}:带默认值的变量
  • $(command):命令替换
  • 引号嵌套
{
  "mcp": {
    "servers": {
      "github": {
        "transport": "http",
        "url": "https://api.github.com/mcp",
        "headers": {
          "Authorization": "Bearer $GITHUB_TOKEN"
        }
      }
    }
  }
}

展开通过 Crush 内置 shell 执行,Windows 系统也能完美支持。

工具调用流程

sequenceDiagram
    participant AI as AI 模型
    participant MCP as MCP 运行时
    participant Server as MCP 服务器
    participant Tool as 工具实现
    
    AI->>MCP: 调用工具 (tool_name, arguments)
    MCP->>Server: 发送工具调用请求
    Server->>Tool: 执行工具逻辑
    Tool-->>Server: 返回结果
    Server-->>MCP: 返回响应
    MCP-->>AI: 返回工具结果

资源访问

MCP 资源通过以下 API 获取:

// internal/client/config.go:45-70
func (c *Client) GetMCPResource(ctx context.Context, id, clientID, resourceID string) ([]MCPResourceContents, error)

返回的资源内容类型包括:

  • 文本内容(带 URI)
  • 二进制内容(带 MIME 类型和数据)

提示词检索

MCP 服务器可以提供预定义的提示词模板:

// internal/client/config.go:72-95
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error)

事件转换

MCP 事件在服务端和客户端之间传输时需要转换为协议消息:

// internal/server/events.go:45-58
case pubsub.Event[mcp.Event]:
    return envelope(pubsub.PayloadTypeMCPEvent, pubsub.Event[proto.MCPEvent]{
        Type: e.Type,
        Payload: proto.MCPEvent{
            Type:      mcpEventTypeToProto(e.Payload.Type),
            Name:      e.Payload.Name,
            State:     proto.MCPState(e.Payload.State),
            Error:     e.Payload.Error,
            ToolCount: e.Payload.Counts.Tools,
        },
    })

事件订阅机制

统一事件总线

Crush 使用 pubsub.Broker 作为统一事件分发中心,支持多订阅者模式:

// internal/app/app.go:80-100
func setupSubscriber[T any](
    ctx context.Context,
    wg *sync.WaitGroup,
    name string,
    subscriber func(context.Context) <-chan pubsub.Event[T],
    broker *pubsub.Broker[tea.Msg],
)

订阅者列表

订阅者名称事件源用途
runRunManager工具执行事件
completionsCompletionProvider自动补全事件
mcpMCPSubscribeEventsMCP 状态事件
lspSubscribeLSPEventsLSP 状态事件
skillsSkills.SubscribeEvents技能发现事件

故障排除

LSP 相关问题

问题可能原因解决方案
全局 LSP 配置不生效当前仅支持项目级配置在项目根目录创建 crush.json
LSP 服务器启动失败命令路径或参数错误检查 commandargs 配置
诊断信息不更新服务器连接断开重启 LSP 服务器

MCP 相关问题

问题可能原因解决方案
MCP 服务器无响应传输类型配置错误确认 transport 设置正确
变量展开失败环境变量未设置检查所需的 $VAR 环境变量
资源读取失败服务器不支持资源确认 MCP 服务器实现资源接口

调试方法

Error with Openai API: output new_sensitive (1027)

  1. 启用日志:设置 `R

Please check that you have set the OPENAI_API_KEY environment variable with a valid API key.

来源:https://github.com/charmbracelet/crush / 项目说明书

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 失败模式:installation: Status line obscured by onboarding dialog

Developers may fail before the first successful local run: Status line obscured by onboarding dialog

medium 来源证据:Status line obscured by onboarding dialog

可能增加新用户试用和生产接入成本。

medium 失败模式:configuration: Qwen 3.7 Max on OpenCode Go Unauthorized Error

Developers may misconfigure credentials, environment, or host setup: Qwen 3.7 Max on OpenCode Go Unauthorized Error

medium 失败模式:configuration: v0.68.0

Upgrade or migration may change expected behavior: v0.68.0

Pitfall Log / 踩坑日志

项目:charmbracelet/crush

摘要:发现 27 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:安装坑 - 失败模式:installation: Status line obscured by onboarding dialog。

1. 安装坑 · 失败模式:installation: Status line obscured by onboarding dialog

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this installation risk before relying on the project: Status line obscured by onboarding dialog
  • 对用户的影响:Developers may fail before the first successful local run: Status line obscured by onboarding dialog
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: Status line obscured by onboarding dialog. Context: Observed when using macos
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_a0f07b57c88e616e55f08e80117c394f | https://github.com/charmbracelet/crush/issues/3044 | Status line obscured by onboarding dialog

2. 安装坑 · 来源证据:Status line obscured by onboarding dialog

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:Status line obscured by onboarding dialog
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源问题仍为 open,Pack Agent 需要复核是否仍影响当前版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_e98d3521bdb84c1398a9b2bbf776e5ae | https://github.com/charmbracelet/crush/issues/3044 | 来源讨论提到 macos 相关条件,需在安装/试用前复核。

3. 配置坑 · 失败模式:configuration: Qwen 3.7 Max on OpenCode Go Unauthorized Error

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this configuration risk before relying on the project: Qwen 3.7 Max on OpenCode Go Unauthorized Error
  • 对用户的影响:Developers may misconfigure credentials, environment, or host setup: Qwen 3.7 Max on OpenCode Go Unauthorized Error
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: Qwen 3.7 Max on OpenCode Go Unauthorized Error. Context: Observed when using linux
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_9e6004420beb68218b1e13d4bcf43db6 | https://github.com/charmbracelet/crush/issues/3027 | Qwen 3.7 Max on OpenCode Go Unauthorized Error

4. 配置坑 · 失败模式:configuration: v0.68.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this configuration risk before relying on the project: v0.68.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.68.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.68.0. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_bbaee295de66f70f36b7dc8593a9b7bd | https://github.com/charmbracelet/crush/releases/tag/v0.68.0 | v0.68.0

5. 配置坑 · 失败模式:configuration: v0.70.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this configuration risk before relying on the project: v0.70.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.70.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.70.0. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_13d76ec440a4dbc5cec24de4d067e76e | https://github.com/charmbracelet/crush/releases/tag/v0.70.0 | v0.70.0

6. 配置坑 · 失败模式:configuration: v0.71.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this configuration risk before relying on the project: v0.71.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.71.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.71.0. Context: Observed when using python
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_8c04dff267efacde979bed34b0d877cd | https://github.com/charmbracelet/crush/releases/tag/v0.71.0 | v0.71.0

7. 配置坑 · 失败模式:configuration: v0.74.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:Developers should check this configuration risk before relying on the project: v0.74.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.74.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.74.0. Context: Observed when using windows
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_a06bc501b775f717bcff8195feac4cd4 | https://github.com/charmbracelet/crush/releases/tag/v0.74.0 | v0.74.0

8. 配置坑 · 来源证据:Custom provider models are invisible in the TUI

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个配置相关的待验证问题:Custom provider models are invisible in the TUI
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源问题仍为 open,Pack Agent 需要复核是否仍影响当前版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_fbc15acd4ea14549b9798314e4d6b7df | https://github.com/charmbracelet/crush/issues/3045 | 来源讨论提到 linux 相关条件,需在安装/试用前复核。

9. 配置坑 · 来源证据:Disabled models still appear in the TUI model picker

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个配置相关的待验证问题:Disabled models still appear in the TUI model picker
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源问题仍为 open,Pack Agent 需要复核是否仍影响当前版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_c8619fe17ed64827934419fb0b4880c7 | https://github.com/charmbracelet/crush/issues/3046 | 来源讨论提到 linux 相关条件,需在安装/试用前复核。

10. 配置坑 · 来源证据:rate limited api requests (429) are not retried

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个配置相关的待验证问题:rate limited api requests (429) are not retried
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_bc68f6499e6d498fa2fcd70a2c6bdf8f | https://github.com/charmbracelet/crush/issues/3024 | 来源类型 github_issue 暴露的待验证使用条件。

11. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 建议检查:将假设转成下游验证清单。
  • 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
  • 证据:capability.assumptions | github_repo:987670088 | https://github.com/charmbracelet/crush | README/documentation is current enough for a first validation pass.

12. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
  • 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
  • 证据:evidence.maintainer_signals | github_repo:987670088 | https://github.com/charmbracelet/crush | last_activity_observed missing

13. 安全/权限坑 · 下游验证发现风险项

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:下游已经要求复核,不能在页面中弱化。
  • 建议检查:进入安全/权限治理复核队列。
  • 防护动作:下游风险存在时必须保持 review/recommendation 降级。
  • 证据:downstream_validation.risk_items | github_repo:987670088 | https://github.com/charmbracelet/crush | no_demo; severity=medium

14. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 建议检查:把风险写入边界卡,并确认是否需要人工复核。
  • 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
  • 证据:risks.scoring_risks | github_repo:987670088 | https://github.com/charmbracelet/crush | no_demo; severity=medium

15. 安全/权限坑 · 来源证据:Qwen 3.7 Max on OpenCode Go Unauthorized Error

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:Qwen 3.7 Max on OpenCode Go Unauthorized Error
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_446e93f99e5d4dc1adfcc57444e1ef8d | https://github.com/charmbracelet/crush/issues/3027 | 来源讨论提到 linux 相关条件,需在安装/试用前复核。

16. 能力坑 · 失败模式:capability: Custom provider models are invisible in the TUI

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this capability risk before relying on the project: Custom provider models are invisible in the TUI
  • 对用户的影响:Developers may hit a documented source-backed failure mode: Custom provider models are invisible in the TUI
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: Custom provider models are invisible in the TUI. Context: Observed when using linux
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_95736f381b4ee813c4baceb87c276b87 | https://github.com/charmbracelet/crush/issues/3045 | Custom provider models are invisible in the TUI

17. 能力坑 · 失败模式:capability: Disabled models still appear in the TUI model picker

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this capability risk before relying on the project: Disabled models still appear in the TUI model picker
  • 对用户的影响:Developers may hit a documented source-backed failure mode: Disabled models still appear in the TUI model picker
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: Disabled models still appear in the TUI model picker. Context: Observed when using linux
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_07c27ec8a35d211b3baf8f95bdc94049 | https://github.com/charmbracelet/crush/issues/3046 | Disabled models still appear in the TUI model picker

18. 能力坑 · 失败模式:capability: I hope to enable support for glm, qwen, kimi and minimax in the eastopenrouter.

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this capability risk before relying on the project: I hope to enable support for glm, qwen, kimi and minimax in the eastopenrouter.
  • 对用户的影响:Developers may hit a documented source-backed failure mode: I hope to enable support for glm, qwen, kimi and minimax in the eastopenrouter.
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: I hope to enable support for glm, qwen, kimi and minimax in the eastopenrouter.. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_63a8cad40e7a346a6d7d99b6a8c6c551 | https://github.com/charmbracelet/crush/issues/3043 | I hope to enable support for glm, qwen, kimi and minimax in the eastopenrouter.

19. 能力坑 · 失败模式:capability: rate limited api requests (429) are not retried

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this capability risk before relying on the project: rate limited api requests (429) are not retried
  • 对用户的影响:Developers may hit a documented source-backed failure mode: rate limited api requests (429) are not retried
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: rate limited api requests (429) are not retried. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_issue | fmev_4fd1758958ecbb14a35cdcd3d5d1999a | https://github.com/charmbracelet/crush/issues/3024 | rate limited api requests (429) are not retried

20. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
  • 防护动作:issue/PR 响应未知时,必须提示维护风险。
  • 证据:evidence.maintainer_signals | github_repo:987670088 | https://github.com/charmbracelet/crush | issue_or_pr_quality=unknown

21. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
  • 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
  • 证据:evidence.maintainer_signals | github_repo:987670088 | https://github.com/charmbracelet/crush | release_recency=unknown

22. 维护坑 · 失败模式:maintenance: nightly

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: nightly
  • 对用户的影响:Upgrade or migration may change expected behavior: nightly
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: nightly. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_5728cb735d1e881463679d2371cb1b72 | https://github.com/charmbracelet/crush/releases/tag/nightly | nightly

23. 维护坑 · 失败模式:maintenance: v0.69.0

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: v0.69.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.69.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.69.0. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_5566acb97cddbf499b1f66a5e1c3c551 | https://github.com/charmbracelet/crush/releases/tag/v0.69.0 | v0.69.0

24. 维护坑 · 失败模式:maintenance: v0.69.1

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: v0.69.1
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.69.1
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.69.1. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_9d60f677f778da5c768a8a4010d2b98f | https://github.com/charmbracelet/crush/releases/tag/v0.69.1 | v0.69.1

25. 维护坑 · 失败模式:maintenance: v0.72.0

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: v0.72.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.72.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.72.0. Context: Observed when using windows
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_aaf5977fa237d63e149c54782afa2165 | https://github.com/charmbracelet/crush/releases/tag/v0.72.0 | v0.72.0

26. 维护坑 · 失败模式:maintenance: v0.73.0

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: v0.73.0
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.73.0
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.73.0. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_17c84212866ab12078588df528f11ade | https://github.com/charmbracelet/crush/releases/tag/v0.73.0 | v0.73.0

27. 维护坑 · 失败模式:maintenance: v0.74.1

  • 严重度:low
  • 证据强度:source_linked
  • 发现:Developers should check this maintenance risk before relying on the project: v0.74.1
  • 对用户的影响:Upgrade or migration may change expected behavior: v0.74.1
  • 建议检查:Before packaging this project, run the relevant install/config/quickstart check for: v0.74.1. Context: Source discussion did not expose a precise runtime context.
  • 防护动作:State this as source-backed community evidence, not as Doramagic reproduction.
  • 证据:failure_mode_cluster:github_release | fmev_b32360eb9d88abe0b1576258d57cfdbb | https://github.com/charmbracelet/crush/releases/tag/v0.74.1 | v0.74.1

来源:Doramagic 发现、验证与编译记录