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

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

## 目录

- [项目概览](#page-overview)
- [安装与部署](#page-installation)
- [快速入门](#page-quickstart)
- [系统架构](#page-architecture)
- [数据流与数据库](#page-data-flow)
- [Agent 系统](#page-agent-system)
- [工具系统](#page-tool-system)
- [技能系统](#page-skills)
- [配置系统](#page-configuration)
- [LSP 与 MCP 集成](#page-lsp-mcp)

<a id='page-overview'></a>

## 项目概览

### 相关页面

相关主题：[系统架构](#page-architecture), [安装与部署](#page-installation)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
- [internal/app/testing.go](https://github.com/charmbracelet/crush/blob/main/internal/app/testing.go)
- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/backend/backend_test.go](https://github.com/charmbracelet/crush/blob/main/internal/backend/backend_test.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/client/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/client/proto.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
</details>

# 项目概览

## 简介

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

资料来源：[README.md:1-8]()

## 核心功能

### 多模型支持

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

| 功能类别 | 支持类型 |
|---------|---------|
| 云端 API | OpenAI、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：

```json
{
  "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 服务器 |
| `http` | HTTP 端点 |
| `sse` | Server-Sent Events |

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

资料来源：[README.md:197-215]()

### Hooks 机制

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

资料来源：[v0.67.0 发布说明]()

## 系统架构

### 客户端-服务端架构

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

```mermaid
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），工作空间通过路径索引管理：

- 绝对路径直接解析
- 相对路径基于当前目录
- 不存在的路径会创建新工作空间

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

资料来源：[internal/backend/backend_test.go:13-20]()

### 事件系统

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

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

| 事件类型 | 说明 |
|---------|------|
| `LSPEventStateChanged` | LSP 服务器状态变更 |
| `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_KEY` | Anthropic |
| `OPENAI_API_KEY` | OpenAI |
| `DEEPSEEK_API_KEY` | DeepSeek |
| `OPENROUTER_API_KEY` | OpenRouter |
| `VERTEXAI_*` | Google Cloud VertexAI |
| `AWS_*` | Amazon Bedrock |

资料来源：[README.md:220-260]()

## 客户端 API

### 配置操作

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

```go
// 设置紧凑模式
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 服务器交互：

```go
// 读取 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 操作

```go
// 列出消息
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`**：测试用关闭，仅执行清理函数

```go
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）机制防止意外关闭：

- 注册客户端时获取持有
- 客户端连接时增加引用计数
- 最后一个持有释放时触发工作空间关闭

```go
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 报告 |
| #2928 | OpenRouter 模型授权失败 | 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

---

<a id='page-installation'></a>

## 安装与部署

### 相关页面

相关主题：[项目概览](#page-overview), [配置系统](#page-configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
- [goreleaser.yml](https://github.com/charmbracelet/crush/blob/main/goreleaser.yml)
- [flake.nix](https://github.com/charmbracelet/crush/blob/main/flake.nix)
- [Taskfile.yaml](https://github.com/charmbracelet/crush/blob/main/Taskfile.yaml)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
</details>

# 安装与部署

## 概述

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+ | 最新稳定版 |
| 内存 | 4GB | 8GB+ |
| 磁盘空间 | 200MB | 500MB+ |
| 网络 | 需要访问 LLM API | 稳定高速网络 |

### 外部依赖

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

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

资料来源：[README.md:45-52]()

## 安装方式

### 通过包管理器安装

#### macOS (Homebrew)

```bash
brew install charmbracelet/tap/crush
```

#### NPM

```bash
npm install -g @charmland/crush
```

资料来源：[README.md:59-65]()

#### Linux 包管理器

| 发行版 | 安装命令 |
|--------|---------|
| Arch Linux | `yay -S crush-bin` |
| FreeBSD | `pkg install crush` |
| Nix | `nix run github:numtide/nix-ai-tools#crush` |

#### Windows

| 包管理器 | 安装命令 |
|---------|---------|
| Winget | `winget install charmbracelet.crush` |
| Scoop | `scoop bucket add charm https://github.com/charmbracelet/scoop-bucket.git && scoop install crush` |

资料来源：[README.md:66-80]()

### Nix/NixOS 安装

#### 通过 NUR 安装

Crush 通过官方 Charm [NUR](https://github.com/nix-community/NUR) 提供 Nix 支持，是 Nix 中获取最新版本的最优方式。

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

#### Nix Shell 快速试用

```bash
# 添加 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 配置中：

```nix
{
  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. 克隆仓库

```bash
git clone https://github.com/charmbracelet/crush.git
cd crush
```

#### 编译

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

# 或使用 Taskfile（需要安装 Task）
task build
```

#### Taskfile 构建任务

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

```bash
# 查看所有可用任务
task --list
```

资料来源：[Taskfile.yaml:1-50]()

## 配置管理

### 配置文件位置

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

```mermaid
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]()

### 基本配置示例

```json
{
  "$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 服务器：

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

常见 LSP 配置示例：

| 语言 | 命令 | 参数 |
|------|------|------|
| Go | `gopls` | - |
| TypeScript | `typescript-language-server` | `--stdio` |
| Nix | `nil` | - |

> **注意**：全局 LSP 配置需确保配置文件位于正确路径（`~/.config/crush/crush.json`），部分用户报告过全局 LSP 配置不生效的问题。资料来源：[README.md:54-68]()

### MCP 服务器配置

Crush 支持 Model Context Protocol (MCP)，支持三种传输类型：

| 传输类型 | 说明 |
|---------|------|
| `stdio` | 命令行服务器 |
| `http` | HTTP 端点 |
| `sse` | Server-Sent Events |

```json
{
  "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 按以下顺序搜索技能目录：

```mermaid
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]
```

#### 自定义技能路径

```jsonc
{
  "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]()

### 提交信息配置

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

| 配置项 | 可选值 | 说明 |
|--------|--------|------|
| `trailer_style` | `assisted-by`（默认）、`co-authored-by`、`none` | 提交信息归属风格 |
| `generated_with` | `true`（默认）、`false` | 是否添加 "💘 Generated with Crush" |

资料来源：[README.md:145-165]()

## 环境变量

### API 密钥配置

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

| 环境变量 | 支持的提供商 |
|---------|-------------|
| `ANTHROPIC_API_KEY` | Anthropic |
| `OPENAI_API_KEY` | OpenAI |
| `VERCEL_API_KEY` | Vercel AI Gateway |
| `GEMINI_API_KEY` | Google Gemini |
| `SYNTHETIC_API_KEY` | Synthetic |
| `ZAI_API_KEY` | Z.ai |
| `MINIMAX_API_KEY` | MiniMax |
| `HF_TOKEN` | Hugging Face Inference |
| `CEREBRAS_API_KEY` | Cerebras |
| `OPENROUTER_API_KEY` | OpenRouter |
| `OPENCODE_API_KEY` | OpenCode Zen & Go |
| `GROQ_API_KEY` | Groq |
| `IONET_API_KEY` | io.net |
| `ALIBABA_SINGAPORE_API_KEY` | Alibaba (Singapore) |
| `AVIAN_API_KEY` | Avian |

### AWS / Azure 配置

| 环境变量 | 用途 |
|---------|------|
| `AWS_ACCESS_KEY_ID` | Amazon Bedrock (Claude) |
| `AWS_SECRET_ACCESS_KEY` | Amazon Bedrock (Claude) |
| `AWS_REGION` | Amazon Bedrock (Claude) |
| `AWS_PROFILE` | Amazon Bedrock (自定义 Profile) |
| `AWS_BEARER_TOKEN_BEDROCK` | Amazon Bedrock |
| `AZURE_OPENAI_API_ENDPOINT` | Azure OpenAI |
| `AZURE_OPENAI_API_KEY` | Azure OpenAI |
| `AZURE_OPENAI_API_VERSION` | Azure OpenAI |
| `VERTEXAI_PROJECT` | Google Cloud VertexAI |
| `VERTEXAI_LOCATION` | Google Cloud VertexAI |

资料来源：[README.md:170-195]()

## 客户端-服务器模式

### 架构概述

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

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

### 启用方式

```bash
export CRUSH_CLIENT_SERVER=1
crush
```

### 工作空间管理

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

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

资料来源：[internal/app/app.go:1-45]()

## 桌面通知

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

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

通知发送条件：
- 工具调用需要权限确认
- 代理完成当前回合

> **注意**：macOS 平台的通知目前缺少图标（平台限制）。

资料来源：[README.md:138-155]()

## 订阅服务

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

| 服务 | 说明 |
|------|------|
| [Synthetic](https://synthetic.new/pricing) | 订阅计费 |
| [GLM Coding Plan](https://z.ai/subscribe) | 智谱 AI 代码计划 |
| [Kimi Code](https://www.kimi.com/membership/pricing) | 月之暗面代码助手 |
| [MiniMax Coding Plan](https://platform.minimax.io/subscribe/coding-plan) | MiniMax 代码计划 |

资料来源：[README.md:197-205]()

## 验证安装

### 基本验证

```bash
# 检查版本
crush --version

# 检查配置
crush doctor
```

### 配置测试

```bash
# 测试 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 启动时会自动检查更新，提示用户有新版本可用。

### 手动更新

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

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

### 版本信息

当前稳定版本：v0.74.1

最新版本信息请参阅 [GitHub Releases](https://github.com/charmbracelet/crush/releases)。

资料来源：[README.md:210-220]()

## 卸载

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

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

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

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

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

---

<a id='page-quickstart'></a>

## 快速入门

### 相关页面

相关主题：[项目概览](#page-overview), [配置系统](#page-configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
- [internal/config/init.go](https://github.com/charmbracelet/crush/blob/main/internal/config/init.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/server/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/server/proto.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
</details>

# 快速入门

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

## 安装 Crush

### 系统要求

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

### 安装方式

#### macOS

```bash
brew install charm-cli/tap/crush
```

#### Linux

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

#### Windows

使用 winget 安装：

```powershell
winget install Charm.Crush
```

### 验证安装

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

```bash
crush --version
```

资料来源：[README.md:1-20]()

## 首次启动与登录

### 默认启动

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

```bash
crush
```

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

### 配置 API 密钥

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

#### 环境变量方式

| 提供商 | 环境变量 | 说明 |
|--------|----------|------|
| Anthropic | `ANTHROPIC_API_KEY` | 用于 Claude 系列模型 |
| OpenAI | `OPENAI_API_KEY` | 用于 GPT 系列模型 |
| Google Gemini | `GEMINI_API_KEY` | 用于 Gemini 模型 |
| OpenRouter | `OPENROUTER_API_KEY` | 用于访问多种模型 |
| DeepSeek | `DEEPSEEK_API_KEY` | 用于 DeepSeek 模型 |

资料来源：[README.md:1-100]()

#### 配置文件方式

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

```json
{
  "$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` | 项目本地配置 |
| 2 | `crush.json` | 项目本地配置 |
| 3 | `~/.config/crush/crush.json` | 用户全局配置 |

### 配置结构

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

```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 命令来完成各种任务：

```bash
# 运行 git 命令
crush> git status

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

# 搜索文件内容
crush> grep -r "function" .
```

> [!NOTE]
> 某些敏感命令（如 `curl`、`wget`、`ssh`、`sudo`）可能受到安全限制。社区中有用户反馈希望移除这些限制以获得不受限制的终端访问能力。相关讨论可参考 [GitHub Issue #928](https://github.com/charmbracelet/crush/issues/928)。

### 4. LSP 集成

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

#### 配置示例

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

资料来源：[README.md:200-250]()

#### LSP 事件类型

| 事件类型 | 说明 |
|----------|------|
| `state_changed` | LSP 服务器状态变更 |
| `diagnostics_changed` | 诊断信息变更 |

资料来源：[internal/app/lsp_events.go:1-50]()

### 5. MCP 服务器支持

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

| 传输类型 | 说明 | 配置方式 |
|----------|------|----------|
| `stdio` | 命令行服务器 | 命令行参数 |
| `http` | HTTP 端点 | URL 和 Headers |
| `sse` | Server-Sent Events | URL 配置 |

#### 配置示例

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

#### Shell 变量展开

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

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

资料来源：[README.md:250-300]()

## 工作流程图

### 基本交互流程

```mermaid
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
```

### 工具调用流程

```mermaid
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](https://agentskills.io) 开放标准，可以通过可重用的技能包扩展功能。

### 技能搜索路径

| 优先级 | 路径 |
|--------|------|
| 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](https://github.com/charmbracelet/crush/issues/2935)。

### 提交信息配置

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

支持的提交风格：

| 风格 | 说明 |
|------|------|
| `assisted-by` | 添加 `Assisted-by: Crush:[ModelID]` |
| `co-authored-by` | 添加 `Co-Authored-By: Crush <crush@charm.land>` |
| `none` | 不添加任何标识 |

资料来源：[README.md:50-100]()

## 常见问题与故障排除

### 数据库问题

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

### LSP 配置问题

> [!NOTE]
> 全局 LSP 配置可能不生效。若 LSP 功能无法正常使用，可以尝试使用项目本地的 `.crush.json` 配置文件。相关讨论可参考 [GitHub Issue #2898](https://github.com/charmbracelet/crush/issues/2898)。

### 模型提供商问题

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

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

相关讨论可参考 [GitHub Issue #2928](https://github.com/charmbracelet/crush/issues/2928)。

## 下一步

| 资源 | 说明 |
|------|------|
| [配置文件参考](../configuration/) | 完整的配置选项文档 |
| [工具参考](../tools/) | 所有可用工具的详细说明 |
| [LSP 集成](../lsp/) | LSP 配置高级指南 |
| [MCP 集成](../mcp/) | MCP 服务器配置指南 |
| [技能开发](../skills/) | 创建自定义 Agent Skills |

## 获取帮助

- [GitHub Issues](https://github.com/charmbracelet/crush/issues) - 报告问题和建议功能
- [Slack](https://charm.land/slack) - 加入社区讨论
- [Discord](https://charm.land/discord) - 即时交流
- [Mastodon](https://mastodon.social/@charmcli) - 关注更新动态

---

<a id='page-architecture'></a>

## 系统架构

### 相关页面

相关主题：[数据流与数据库](#page-data-flow), [Agent 系统](#page-agent-system), [工具系统](#page-tool-system)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/app/app.go](https://github.com/charmbracelet/crush/blob/main/internal/app/app.go)
- [internal/app/testing.go](https://github.com/charmbracelet/crush/blob/main/internal/app/testing.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
- [internal/backend/backend.go](https://github.com/charmbracelet/crush/blob/main/internal/backend/backend.go)
- [internal/backend/backend_test.go](https://github.com/charmbracelet/crush/blob/main/internal/backend/backend_test.go)
- [internal/server/server.go](https://github.com/charmbracelet/crush/blob/main/internal/server/server.go)
- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/server/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/server/proto.go)
- [internal/client/client.go](https://github.com/charmbracelet/crush/blob/main/internal/client/client.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/client/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/client/proto.go)
</details>

# 系统架构

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

## 整体架构概览

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

```mermaid
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 应用程序的主入口，负责全局生命周期管理和清理函数注册。

| 组件 | 文件 | 职责 |
|------|------|------|
| App | `internal/app/app.go` | 全局应用状态管理 |
| testing | `internal/app/testing.go` | 测试环境支持 |
| lsp_events | `internal/app/lsp_events.go` | LSP 事件订阅与分发 |

**关键特性：**

- **清理函数注册**：通过 `cleanupFuncs` 切片管理资源释放回调
- **测试支持**：`ShutdownForTest()` 方法提供测试专用的清理路径
- **LSP 事件系统**：基于 `pubsub.Broker` 的发布订阅机制

```go
// 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.go | `internal/backend/backend.go` | 核心业务逻辑 |
| backend_test.go | `internal/backend/backend_test.go` | 单元测试 |

**关键数据结构：**

```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` 控制工作区何时被销毁

```mermaid
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.go | `internal/server/server.go` | HTTP 服务器启动与路由 |
| events.go | `internal/server/events.go` | 事件类型转换 |
| proto.go | `internal/server/proto.go` | API 控制器实现 |

**事件类型转换链：**

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

**主要 API 端点：**

| 端点 | 方法 | 功能 |
|------|------|------|
| `/workspaces` | GET | 列出所有工作区 |
| `/workspaces/:id` | GET | 获取工作区详情 |
| `/workspaces/:id/config` | GET/PUT | 配置管理 |
| `/workspaces/:id/agent/sessions/:sid/summarize` | POST | 会话摘要 |
| `/workspaces/:id/agent/init` | POST | 初始化 Agent |
| `/control` | POST | 服务器控制命令 |

资料来源：[internal/server/proto.go:1-20]()

### 4. Client 模块

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

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

**MCP 资源访问：**

```go
// 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 支持多种凭证类型的安全传输：

```go
// 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.go` | LSP 事件定义与分发 |

**LSP 事件类型：**

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

**LSP 状态管理：**

```go
// 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` 实现线程安全的并发访问：

```go
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]()

### 事件流处理

```mermaid
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
```

**事件序列化示例：**

```go
// 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 结构

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

资料来源：[internal/backend/backend_test.go:22-29]()

### 路径解析与符号链接

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

- 解析符号链接到真实路径
- 对不存在的路径自动创建
- 支持工作区路径索引映射

```go
// 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 | 权限状态变更通知 |

**权限请求结构：**

```go
// 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） | 功能请求 |
| #928 | Bash 命令安全限制 | 用户反馈 |
| #2898 | 全局 LSP 配置不生效 | 问题报告 |
| #2903 | 数据库损坏问题 | 问题报告 |

### 稳定性改进

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

资料来源：[社区讨论 - v0.68.0](https://github.com/charmbracelet/crush/releases/tag/v0.68.0)

## 扩展机制

### LSP 支持

配置示例：

```json
{
  "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、权限系统

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

---

<a id='page-data-flow'></a>

## 数据流与数据库

### 相关页面

相关主题：[系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/app/testing.go](https://github.com/charmbracelet/crush/blob/main/internal/app/testing.go)
- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/client/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/client/proto.go)
- [internal/backend/backend_test.go](https://github.com/charmbracelet/crush/blob/main/internal/backend/backend_test.go)
- [internal/server/events_test.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events_test.go)
- [internal/app/lsp_events.go](https://github.com/charmbret/crush/blob/main/internal/app/lsp_events.go)
</details>

# 数据流与数据库

## 概述

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

## 核心架构

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

```mermaid
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 进行序列化传输。

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

### 事件类型映射表

| 事件类型 | 来源文件 | 说明 |
|---------|---------|------|
| `LSPEvent` | `lsp_events.go` | 语言服务器状态变化 |
| `MCPEvent` | `events.go` | MCP 服务器事件 |
| `PermissionRequest` | `events.go` | 工具调用权限请求 |
| `PermissionNotification` | `events.go` | 权限通知 |
| `SkillsEvent` | `events.go` | 技能状态变化 |

### Proto 转换机制

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

```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 格式：

```go
// 资料来源：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 数据持久化的核心单位。每个工作空间可以包含多个会话，会话存储消息历史、工具调用记录和上下文状态。

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

### 客户端注册与注销

```go
// 资料来源：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）。

```go
// 资料来源：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

### 消息列表获取

```go
// 资料来源：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
    // ...
}
```

### 会话摘要

```go
// 资料来源：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 令牌刷新

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

## LSP 事件处理

### 事件订阅机制

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

### 状态查询接口

```go
// 资料来源：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 资源与提示

### 资源获取

```go
// 资料来源：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"}})
    // ...
}
```

### 提示获取

```go
// 资料来源：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 类型分发：

```go
// 资料来源：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,
        },
    })
```

## 清理与关闭

### 清理函数注册

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

```go
// 资料来源：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](https://github.com/charmbracelet/crush/issues/2903)

## 配置与持久化路径

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

| 环境变量 | 说明 |
|---------|------|
| `CRUSH_GLOBAL_CONFIG` | 覆盖全局配置文件路径 |
| `CRUSH_GLOBAL_DATA` | 覆盖全局数据目录路径 |

```mermaid
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\]
```

## 测试覆盖

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

```go
// 资料来源：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` 中添加对应的消息类型。

---

<a id='page-agent-system'></a>

## Agent 系统

### 相关页面

相关主题：[工具系统](#page-tool-system), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/server/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/server/proto.go)
- [internal/client/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/client/proto.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
</details>

# Agent 系统

## 概述

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

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

## 架构概览

```mermaid
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}/agent` | POST | 发送 Agent 消息 |
| `/workspaces/{id}/agent/init` | POST | 初始化 Agent 处理 |
| `/workspaces/{id}/agent/sessions` | GET | 列出所有会话 |
| `/workspaces/{id}/agent/sessions/{sessionID}/summarize` | POST | 汇总会话 |

#### 消息处理流程

```go
// 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 系统支持的事件类型：

```go
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 事件类型

| 事件类型 | 说明 |
|----------|------|
| `AgentEventTypeResponse` | Agent 响应事件 |
| `AgentEventTypeError` | Agent 错误事件 |
| `AgentEventTypeComplete` | Agent 完成事件 |

### 事件封装机制

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

```go
// 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 客户端接口：

#### 发送消息

```go
// 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 处理

```go
// 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
}
```

#### 会话汇总

```go
// 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：

#### 设置默认模型

```go
// 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
}
```

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

```go
// 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
}
```

#### 获取默认模型

```go
// 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 系统通过事件总线与其交互：

```go
// 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
}
```

事件订阅机制：

```go
// 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` 类型传输，包含：

| 字段 | 类型 | 说明 |
|------|------|------|
| SessionID | string | 会话标识符 |
| Type | AgentMessageType | 消息类型 |
| Content | string | 消息内容 |
| Metadata | map | 元数据 |

### 事件有效载荷类型

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

## 工作流程

```mermaid
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
```

## 测试覆盖

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

```go
// 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` 进行配置：

```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 支持请求

## 扩展阅读

- [Server-Client 架构](../architecture/client-server.md)
- [事件系统](../architecture/events.md)
- [权限系统](./permission.md)

---

<a id='page-tool-system'></a>

## 工具系统

### 相关页面

相关主题：[Agent 系统](#page-agent-system), [配置系统](#page-configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [internal/server/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/server/proto.go)
- [internal/client/proto.go](https://github.com/charmbracelet/crush/blob/main/internal/client/proto.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
</details>

# 工具系统

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

## 系统架构

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

```mermaid
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` | 工具执行完成的通知 |

### 权限请求数据结构

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

```go
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 定义进行序列化，支持在客户端-服务端之间传输：

```go
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 命令存在安全限制，阻止了 `curl`、`wget`、`ssh`、`sudo` 等命令的执行，这影响了开发测试工作流。

> 参考：[Issue #928 - Remove bash command security limits for unrestricted terminal access](https://github.com/charmbracelet/crush/issues/928)

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

### 文件编辑工具

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

### 文件写入工具

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

### Grep 工具

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

### Safe 模式工具

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

## 工具配置

### 权限模式配置

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

```json
{
  "$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](https://github.com/charmbracelet/crush/issues/2935)

### MCP 工具集成

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

| 传输类型 | 说明 |
|---------|------|
| `stdio` | 命令行服务器模式 |
| `http` | HTTP 端点模式 |
| `sse` | Server-Sent Events 模式 |

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

```go
// 获取 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 连接接收实时更新。

```mermaid
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 工具事件携带工具计数信息：

```go
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_KEY` | OpenAI |
| `ANTHROPIC_API_KEY` | Anthropic |
| `OPENROUTER_API_KEY` | OpenRouter |
| `OPENCODE_API_KEY` | OpenCode |
| `DEEPSEEK_API_KEY` | DeepSeek |

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

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

资料来源：[internal/client/config.go:145-170]()

## 错误处理与状态管理

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

```go
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. **错误监控**：通过事件订阅机制实时监控工具执行状态

---

<a id='page-skills'></a>

## 技能系统

### 相关页面

相关主题：[配置系统](#page-configuration), [Agent 系统](#page-agent-system)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/skills/skills.go](https://github.com/charmbracelet/crush/blob/main/internal/skills/skills.go)
- [internal/skills/manager.go](https://github.com/charmbracelet/crush/blob/main/internal/skills/manager.go)
- [internal/skills/catalog.go](https://github.com/charmbracelet/crush/blob/main/internal/skills/catalog.go)
- [internal/skills/embed.go](https://github.com/charmbracelet/crush/blob/main/internal/skills/embed.go)
- [.agents/skills/builtin-skills/SKILL.md](https://github.com/charmbracelet/crush/blob/main/.agents/skills/builtin-skills/SKILL.md)
- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/server/events_test.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events_test.go)
- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
</details>

# 技能系统

## 概述

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

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

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

## 技能发现机制

### 技能搜索路径

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

#### 全局技能路径

| 环境变量/路径 | 描述 |
|-------------|------|
| `$CRUSH_SKILLS_DIR` | 用户指定的技能目录 |
| `$XDG_CONFIG_HOME/agents/skills` | Agent Skills 标准目录 |
| `$XDG_CONFIG_HOME/crush/skills` | Crush 专用技能目录 |
| `~/.agents/skills/` | Claude 兼容路径 |
| `~/.claude/skills/` | Claude 兼容路径 |
| Windows: `%LOCALAPPDATA%\agents\skills\` | Windows 全局路径 |
| Windows: `%LOCALAPPDATA%\crush\skills\` | Windows Crush 专用 |

> 配置来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md)

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

| 相对路径 | 描述 |
|---------|------|
| `.agents/skills` | 标准 agent 技能目录 |
| `.crush/skills` | Crush 项目目录 |
| `.claude/skills` | Claude 兼容目录 |
| `.cursor/skills` | Cursor IDE 兼容目录 |

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

#### 自定义技能路径

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

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

### 技能包结构

技能包是一个文件夹，包含至少一个 `SKILL.md` 文件：

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

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

## 技能状态管理

### 状态数据结构

技能状态通过 `skills.Event` 和 `skills.SkillState` 类型管理：

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

### 技能发现状态

| 状态值 | 描述 |
|-------|------|
| `StateNormal` | 技能正常加载 |
| `StateError` | 技能加载失败，包含错误信息 |

> 配置来源：[internal/server/events.go:71-72](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)

### 事件通知机制

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

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

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

> 配置来源：[internal/server/events.go:64-76](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)

## 技能事件序列化

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

```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
}
```

> 配置来源：[internal/server/events.go:95-111](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)

### 往返序列化测试

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

```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")},
            },
        },
    }
    // 测试事件包装、序列化、反序列化过程
}
```

> 配置来源：[internal/server/events_test.go:89-106](https://github.com/charmbracelet/crush/blob/main/internal/server/events_test.go)

## 内置技能

Crush 附带了一些内置技能：

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

### 禁用内置技能

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

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

> 配置来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md)

## 技能管理器架构

```mermaid
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` 环境变量指定额外的技能目录：

```bash
export CRUSH_SKILLS_DIR=/path/to/my/skills
```

### Windows 路径兼容性

Windows 平台使用 `%LOCALAPPDATA%` 变量，配置文件示例：

```json
{
  "options": {
    "skills_paths": [
      "%LOCALAPPDATA%\\crush\\skills"
    ]
  }
}
```

> 配置来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md)

### 技能加载失败处理

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

---

<a id='page-configuration'></a>

## 配置系统

### 相关页面

相关主题：[LSP 与 MCP 集成](#page-lsp-mcp), [安装与部署](#page-installation)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/config/config.go](https://github.com/charmbracelet/crush/blob/main/internal/config/config.go)
- [internal/config/load.go](https://github.com/charmbracelet/crush/blob/main/internal/config/load.go)
- [internal/config/provider.go](https://github.com/charmbracelet/crush/blob/main/internal/config/provider.go)
- [internal/config/store.go](https://github.com/charmbracelet/crush/blob/main/internal/config/store.go)
- [internal/config/docker_mcp.go](https://github.com/charmbracelet/crush/blob/main/internal/config/docker_mcp.go)
- [schema.json](https://github.com/charmbracelet/crush/blob/main/schema.json)
- [crush.json](https://github.com/charmbracelet/crush/blob/main/crush.json)
</details>

# 配置系统

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

## 配置架构概述

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

### 配置层级

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

配置加载时会按上述顺序搜索配置文件，相同键值在高优先级配置中出现时将覆盖低优先级配置。资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L1-L50)

### 数据存储位置

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

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

环境变量 `CRUSH_GLOBAL_CONFIG` 和 `CRUSH_GLOBAL_DATA` 可分别覆盖全局配置和用户数据存储路径。资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L50-L70)

## 配置加载流程

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

### 加载流程图

```mermaid
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](https://github.com/charmbracelet/crush/blob/main/internal/config/load.go)

## 配置结构

### 核心配置项

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

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

| 配置块 | 类型 | 说明 |
|-------|------|------|
| `providers` | object | AI 模型提供者配置 |
| `lsp` | object | 语言服务器协议配置 |
| `mcp` | object | Model Context Protocol 配置 |
| `options` | object | 全局运行选项 |
| `permissions` | object | 权限控制配置 |
| `hooks` | object | 钩子脚本配置 |

资料来源：[schema.json](https://github.com/charmbracelet/crush/blob/main/schema.json)

## 提供者配置

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

### 内置提供者支持

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

| 环境变量 | 提供者 |
|---------|--------|
| `ANTHROPIC_API_KEY` | Anthropic (Claude) |
| `OPENAI_API_KEY` | OpenAI |
| `DEEPSEEK_API_KEY` | Deepseek |
| `OPENROUTER_API_KEY` | OpenRouter |
| `GOOGLE_API_KEY` / `GEMINI_API_KEY` | Google Gemini |
| `VERTEXAI_PROJECT` / `VERTEXAI_LOCATION` | Google VertexAI |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | Amazon Bedrock (Claude) |
| `AZURE_OPENAI_API_ENDPOINT` | Azure OpenAI |
| `GROQ_API_KEY` | Groq |
| `HF_TOKEN` | Hugging Face Inference |
| `CEREBRAS_API_KEY` | Cerebras |
| `OPENCODE_API_KEY` | OpenCode Zen & Go |
| `HYPER_API_KEY` | Hyper (Charm) |

资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L80-L120)

### 自定义提供者

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

#### OpenAI 兼容 API

```json
{
  "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](https://github.com/charmbracelet/crush/blob/main/README.md#L120-L145)

#### Anthropic 兼容 API

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

## LSP 配置

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

### LSP 配置示例

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

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

| 字段 | 类型 | 说明 |
|-----|------|------|
| `command` | string | LSP 服务器可执行命令 |
| `args` | array | 命令行参数 |
| `env` | object | 环境变量 |
| `root_markers` | array | 工作目录标记文件 |
| `filetypes` | array | 支持的文件类型 |

> **已知问题**：社区反馈全局 LSP 配置有时不生效，需要确保配置文件位于正确路径 `~/.config/crush/crush.json`。资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L150-L175)

## MCP 配置

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

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

### Shell 变量扩展

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

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

支持的扩展语法包括：

- `$VAR` - 基本变量引用
- `${VAR:-default}` - 带默认值的变量
- `$(command)` - 命令替换
- 嵌套引用和转义

> 变量扩展通过 Crush 内置的 Shell 解释器执行，确保在 Windows 和 Unix 系统上行为一致。资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L175-L210)

## 选项配置

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

### 可用选项

| 选项 | 类型 | 默认值 | 说明 |
|-----|------|-------|------|
| `compact` | boolean | false | 紧凑模式，减少输出 |
| `no_env_expansion` | boolean | false | 禁用环境变量扩展 |
| `no_output` | boolean | false | 禁用所有输出 |
| `verbose` | boolean | false | 详细输出模式 |
| `hooks_path` | string | - | 自定义钩子脚本路径 |
| `skills_paths` | array | - | 技能目录路径列表 |
| `disabled_skills` | array | - | 禁用的技能列表 |
| `trailer_style` | string | "assisted-by" | 提交消息归属风格 |
| `generated_with` | boolean | true | 添加生成标记 |

### 提交消息归属风格

| 值 | 效果 |
|---|------|
| `assisted-by` | 添加 `Assisted-by: Crush:[ModelID]` |
| `co-authored-by` | 添加 `Co-Authored-By: Crush <crush@charm.land>` |
| `none` | 不添加归属信息 |

资料来源：[README.md](https://github.com/charmbracelet/crush/blob/main/README.md#L210-L250)

## 权限配置

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

### 当前限制

当前版本仅支持全局 `permissions.yolo` 开关，无法在运行时动态切换权限模式。社区有计划实现多权限配置文件（Yolo、Safe、Custom）在运行时切换的功能。资料来源：[社区 Issue #2935](https://github.com/charmbracelet/crush/issues/2935)

### 权限配置示例

```json
{
  "permissions": {
    "yolo": true
  }
}
```

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

## 技能配置

Crush 支持 [Agent Skills](https://agentskills.io) 开放标准，通过技能包扩展代理能力。

### 技能搜索路径

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

| 优先级 | 路径（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`

### 自定义技能路径配置

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

## 配置验证

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

### Schema 验证

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

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

IDE 可利用 schema 提供自动补全和配置验证功能。资料来源：[schema.json](https://github.com/charmbracelet/crush/blob/main/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 传输时正确解码：

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

资料来源：[internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)

## 配置示例

### 完整配置示例

```json
{
  "$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 以提升上下文理解能力

---

<a id='page-lsp-mcp'></a>

## LSP 与 MCP 集成

### 相关页面

相关主题：[配置系统](#page-configuration), [工具系统](#page-tool-system)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [internal/lsp/client.go](https://github.com/charmbracelet/crush/blob/main/internal/lsp/client.go)
- [internal/lsp/manager.go](https://github.com/charmbracelet/crush/blob/main/internal/lsp/manager.go)
- [internal/app/lsp_events.go](https://github.com/charmbracelet/crush/blob/main/internal/app/lsp_events.go)
- [internal/backend/events.go](https://github.com/charmbracelet/crush/blob/main/internal/backend/events.go)
- [internal/server/events.go](https://github.com/charmbracelet/crush/blob/main/internal/server/events.go)
- [internal/client/config.go](https://github.com/charmbracelet/crush/blob/main/internal/client/config.go)
- [README.md](https://github.com/charmbracelet/crush/blob/main/README.md)
</details>

# LSP 与 MCP 集成

## 概述

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

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

## 架构设计

### 整体架构图

```mermaid
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
```

### 核心组件

| 组件 | 位置 | 职责 |
|------|------|------|
| LSPManager | `internal/lsp/manager.go` | 管理多个 LSP 客户端生命周期 |
| LSPClient | `internal/lsp/client.go` | 与单个语言服务器通信 |
| MCPRuntime | `internal/agent/tools/mcp/` | 管理 MCP 服务器连接 |
| LSPBroker | `internal/app/lsp_events.go` | 分发 LSP 事件 |
| MCPTool | `internal/agent/tools/mcp/tools.go` | MCP 工具调用封装 |

## LSP 集成

### 功能特性

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

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

### 事件系统

LSP 事件通过 `pubsub.Broker` 进行分发，支持两种事件类型：

| 事件类型 | 说明 |
|----------|------|
| `state_changed` | LSP 服务器状态变更（连接/断开/错误） |
| `diagnostics_changed` | 诊断信息更新 |

```go
// internal/app/lsp_events.go:14-19
type LSPEvent struct {
    Type            LSPEventType
    Name            string
    State           lsp.ServerState
    Error           error
    DiagnosticCount int
}
```

### 客户端状态管理

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

```go
// 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.NewMap[string, LSPClientInfo]()` 线程安全存储在内存中。 资料来源：[internal/app/lsp_events.go:35-36]()

### 工作空间 LSP 操作

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

```go
// 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 服务器：

```json
{
  "$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 服务器 |
| `http` | HTTP REST | Web API 服务器 |
| `sse` | Server-Sent Events | 实时事件推送 |

### 配置结构

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

### Shell 值展开

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

- `$VAR`：简单变量引用
- `${VAR:-default}`：带默认值的变量
- `$(command)`：命令替换
- 引号嵌套

```json
{
  "mcp": {
    "servers": {
      "github": {
        "transport": "http",
        "url": "https://api.github.com/mcp",
        "headers": {
          "Authorization": "Bearer $GITHUB_TOKEN"
        }
      }
    }
  }
}
```

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

### 工具调用流程

```mermaid
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 获取：

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

返回的资源内容类型包括：
- 文本内容（带 URI）
- 二进制内容（带 MIME 类型和数据）

### 提示词检索

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

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

### 事件转换

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

```go
// 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` 作为统一事件分发中心，支持多订阅者模式：

```go
// 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],
)
```

### 订阅者列表

| 订阅者名称 | 事件源 | 用途 |
|------------|--------|------|
| `run` | RunManager | 工具执行事件 |
| `completions` | CompletionProvider | 自动补全事件 |
| `mcp` | MCPSubscribeEvents | MCP 状态事件 |
| `lsp` | SubscribeLSPEvents | LSP 状态事件 |
| `skills` | Skills.SubscribeEvents | 技能发现事件 |

## 故障排除

### LSP 相关问题

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

### MCP 相关问题

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

### 调试方法

1. **启用日志**：设置 `R
Error with Openai API: output new_sensitive (1027)

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

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：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

<!-- canonical_name: charmbracelet/crush; human_manual_source: deepwiki_human_wiki -->
