Vibe Kanban 项目学习指南

本指南旨在帮助新开发者快速上手并深入理解 Vibe Kanban 项目。建议按顺序阅读,逐步深入。

1. 项目简介

一句话说明

Vibe Kanban 是一个面向 AI 编程助手(Coding Agents)的任务编排和管理平台,帮助开发者高效地切换、管理和并行执行多个 AI 编程助手(如 Claude Code、Gemini CLI、Codex、Amp 等)来完成开发任务。

核心功能列表

  • 多 Agent 切换与编排:支持在 Claude Code、Gemini、Codex、Cursor、Copilot 等主流 AI 编程助手间快速切换
  • 并行任务执行:支持多个 AI Agent 并行或顺序执行任务
  • 工作区管理:为每个任务创建独立的 Git 分支和工作区,隔离开发环境
  • 任务看板:基于 Kanban 的任务跟踪系统,可视化任务状态
  • MCP 配置中心:统一管理各 AI Agent 的 MCP(Model Context Protocol)服务器配置
  • 远程开发支持:支持通过 SSH 远程连接开发环境
  • 代码审查辅助:集成 PR 审查工具,辅助代码 Review
  • 实时状态同步:使用 ElectricSQL 实现前后端实时数据同步

技术栈总览

后端技术栈

类别技术版本说明
语言Rust2024 Edition主要后端语言
Web 框架Axum0.8.4异步 HTTP 服务框架
数据库SQLite (本地) / PostgreSQL (远程)-使用 SQLx 进行数据库操作
ORMSQLx0.8.6异步 SQL 数据库工具包
实时同步ElectricSQL-基于 Postgres 逻辑复制的实时同步引擎
序列化serde/serde_json1.0Rust 序列化框架
类型生成ts-rsgit 版本Rust 到 TypeScript 类型生成
异步运行时Tokio1.0Rust 异步运行时
错误处理thiserror/anyhow2.0/1.0错误处理库
日志tracing/tracing-subscriber0.1结构化日志和追踪

前端技术栈

类别技术版本说明
语言TypeScript5.9+主要前端语言
框架React18.2UI 框架
路由TanStack Router1.161+类型安全的路由库
状态管理TanStack DB + ElectricSQL0.1+响应式数据库状态管理
UI 组件Radix UI + shadcn-无头组件库和设计系统
样式Tailwind CSS3.4+原子化 CSS 框架
构建工具Vite7.3+现代前端构建工具
表单React Hook Form + Zod-表单验证
动画Framer Motion12+动画库
国际化i18next25+国际化框架

关键依赖

  • AI Agent 集成codex-core (OpenAI Codex)、agent-client-protocol (Acp 协议)
  • Git 操作git2 (libgit2 Rust 绑定)
  • MCP 协议rmcp (Rust MCP 服务器实现)
  • 容器化:Docker (远程部署)

2. 目录结构说明

项目根目录

vibe-kanban/
├── .cargo/                    # Cargo 配置(Rust 工具链配置)
├── .github/                   # GitHub Actions CI/CD 配置
├── .npmrc                     # npm/pnpm 配置
├── assets/                    # 静态资源文件(打包到应用中)
├── crates/                    # Rust workspace 成员(核心后端代码)
├── dev_assets_seed/           # 开发环境种子数据(初始数据库)
├── docs/                      # 项目文档(Mintlify 格式)
├── npx-cli/                   # npm CLI 包(npx vibe-kanban 入口)
├── packages/                  # 前端 monorepo 包
├── scripts/                   # 构建和开发脚本
├── shared/                    # 共享类型定义(Rust 生成 TypeScript 类型)
├── AGENTS.md                  # 项目开发和代码规范指南
├── Cargo.toml                 # Rust workspace 根配置
├── package.json               # pnpm workspace 根配置
├── pnpm-workspace.yaml        # pnpm workspace 配置
├── README.md                  # 项目说明文档
└── Dockerfile                 # Docker 构建配置

crates/ 目录(Rust 后端)

crates/
├── api-types/                 # 共享 API 类型定义(Rust + TypeScript)
│   ├── src/
│   │   ├── workspace.rs       # Workspace 类型
│   │   ├── session.rs         # Session 类型
│   │   ├── issue.rs           # Issue 类型
│   │   └── ...                # 其他共享类型
│   └── Cargo.toml
├── server/                    # 本地服务器(主应用)
│   ├── src/
│   │   ├── main.rs            # 应用入口
│   │   ├── lib.rs             # 库导出
│   │   ├── routes/            # HTTP 路由
│   │   │   ├── mod.rs         # 路由汇总
│   │   │   ├── workspaces.rs  # 工作区路由
│   │   │   ├── sessions.rs    # 会话路由
│   │   │   ├── task_attempts/ # 任务尝试路由
│   │   │   └── ...            # 其他路由
│   │   ├── middleware/        # 中间件
│   │   │   ├── mod.rs
│   │   │   ├── origin.rs      # Origin 验证中间件
│   │   │   └── model_loaders.rs
│   │   ├── preview_proxy/     # 预览代理(用于预览开发服务器)
│   │   └── error.rs           # 错误定义
│   └── Cargo.toml
├── db/                        # 数据库层(SQLx 模型 + 迁移)
│   ├── src/
│   │   ├── models/            # 数据模型
│   │   │   ├── mod.rs
│   │   │   ├── workspace.rs   # Workspace 模型
│   │   │   ├── session.rs     # Session 模型
│   │   │   ├── task.rs        # Task 模型
│   │   │   └── ...            # 其他模型
│   │   └── lib.rs             # 数据库连接和迁移
│   ├── migrations/            # SQL 数据库迁移文件
│   └── Cargo.toml
├── executors/                 # AI Agent 执行器(核心)
│   ├── src/
│   │   ├── executors/         # 各 Agent 实现
│   │   │   ├── mod.rs
│   │   │   ├── claude.rs      # Claude Code 执行器
│   │   │   ├── codex.rs       # Codex 执行器
│   │   │   ├── cursor.rs      # Cursor 执行器
│   │   │   ├── copilot.rs     # GitHub Copilot 执行器
│   │   │   └── ...            # 其他 Agent
│   │   ├── actions/           # 可执行动作
│   │   │   ├── coding_agent_initial.rs    # 初始执行
│   │   │   └── coding_agent_follow_up.rs  # 后续执行
│   │   ├── mcp_config.rs      # MCP 配置管理
│   │   ├── profile.rs         # Agent 配置文件
│   │   └── lib.rs
│   └── Cargo.toml
├── services/                  # 业务服务层
│   ├── src/
│   │   ├── services/
│   │   │   ├── mod.rs
│   │   │   ├── container.rs   # 容器服务
│   │   │   ├── config.rs      # 配置服务
│   │   │   └── ...            # 其他服务
│   │   └── lib.rs
│   └── Cargo.toml
├── deployment/                # 部署抽象层
│   ├── src/
│   │   └── lib.rs             # Deployment trait 定义
│   └── Cargo.toml
├── local-deployment/          # 本地部署实现
│   ├── src/
│   │   └── lib.rs             # LocalDeployment 实现
│   └── Cargo.toml
├── remote/                    # 远程服务器(云端版本)
│   ├── src/
│   │   ├── app.rs             # 应用启动
│   │   ├── config.rs          # 配置
│   │   ├── shapes.rs          # ElectricSQL Shape 定义
│   │   ├── routes/            # 路由
│   │   │   ├── electric_proxy.rs  # ElectricSQL 代理
│   │   │   └── ...
│   │   └── auth/              # 认证模块
│   └── Cargo.toml
├── git/                       # Git 操作封装
├── git-host/                  # Git 托管平台集成(GitHub/Azure)
├── mcp/                       # MCP 服务器实现
├── review/                    # PR 审查工具
├── utils/                     # 通用工具函数
└── api-types/                 # 共享类型(被 remote 和 server 依赖)

packages/ 目录(前端)

packages/
├── local-web/                 # 本地 Web 应用(主前端)
│   ├── src/
│   │   ├── app/               # 应用入口和提供者
│   │   │   ├── entry/         # 启动入口
│   │   │   ├── providers/     # React Context 提供者
│   │   │   └── router/        # 路由配置
│   │   ├── routes/            # 路由页面(TanStack Router)
│   │   │   ├── _app.tsx       # 应用布局
│   │   │   ├── _app.workspaces.tsx
│   │   │   ├── _app.workspaces_.$workspaceId.tsx
│   │   │   └── ...            # 其他路由
│   │   ├── shared/            # 共享组件和工具
│   │   │   ├── components/    # 通用组件
│   │   │   ├── providers/     # 数据提供者
│   │   │   └── keyboard/      # 键盘快捷键
│   │   ├── features/          # 功能模块(按功能划分)
│   │   └── routeTree.gen.ts   # 自动生成的路由树
│   ├── public/                # 静态资源
│   └── package.json
├── remote-web/                # 远程 Web 应用(云端前端)
│   ├── src/
│   └── package.json
├── web-core/                  # 共享前端库(local + remote 共用)
│   ├── src/
│   │   ├── components/        # 共享组件
│   │   ├── hooks/             # 共享 Hooks
│   │   ├── utils/             # 工具函数
│   │   └── project-routes/    # 项目相关路由
│   └── package.json
└── ui/                        # UI 组件库(基于 shadcn)
    ├── src/
    │   └── components/        # UI 组件
    └── package.json

shared/ 目录(类型共享)

shared/
├── types.ts                   # 本地类型定义(由 Rust 生成)
├── remote-types.ts            # 远程类型定义(由 Rust 生成)
├── jwt.ts                     # JWT 工具
└── remote-types.ts            # 远程类型定义

3. 架构设计

整体架构模式

Vibe Kanban 采用 前后端分离 + monorepo 架构,核心设计理念:

  1. Rust 后端 + React 前端:利用 Rust 的性能和类型安全,结合 React 的生态和开发体验
  2. 本地优先 + 云端同步:本地使用 SQLite 存储,远程版本使用 PostgreSQL + ElectricSQL 实时同步
  3. 插件化 Agent 执行器:通过 trait 抽象不同 AI Agent,支持热插拔
  4. 类型安全的全栈类型系统:使用 ts-rs 从 Rust 自动生成 TypeScript 类型,保证前后端类型一致

架构分层

┌─────────────────────────────────────────────────────────┐
│                    前端层 (React + TypeScript)           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │ local-web   │  │ remote-web  │  │   web-core  │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
│         │                │                │             │
│         └────────────────┴────────────────┘             │
│                          │                              │
│                  TanStack Router + ElectricSQL          │
└──────────────────────────┼──────────────────────────────┘
                           │ HTTP/WebSocket
┌──────────────────────────┼──────────────────────────────┐
│                    后端层 (Rust + Axum)                  │
│  ┌─────────────────────────────────────────────────┐    │
│  │              HTTP 路由层 (routes/)               │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                              │
│  ┌─────────────────────────────────────────────────┐    │
│  │              业务服务层 (services/)              │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                              │
│  ┌─────────────────────────────────────────────────┐    │
│  │           AI Agent 执行器层 (executors/)         │    │
│  │  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐  │    │
│  │  │Claude│ │Codex │ │Cursor│ │Copilot│ │ ...  │  │    │
│  │  └──────┘ └──────┘ └──────┘ └──────┘ └──────┘  │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                              │
│  ┌─────────────────────────────────────────────────┐    │
│  │              数据访问层 (db/)                    │    │
│  └─────────────────────────────────────────────────┘    │
└──────────────────────────┼──────────────────────────────┘

              ┌────────────┴────────────┐
              │                         │
       ┌──────▼──────┐          ┌──────▼──────┐
       │  SQLite     │          │  PostgreSQL │
       │  (本地)     │          │  (远程)     │
       └─────────────┘          └──────┬──────┘

                                ┌──────▼──────┐
                                │ ElectricSQL │
                                │  (实时同步)  │
                                └─────────────┘

核心模块划分与职责

模块职责关键文件
serverHTTP 服务器、路由、中间件、API 端点crates/server/src/main.rs, routes/mod.rs
db数据库连接、迁移、数据模型、CRUD 操作crates/db/src/models/, crates/db/migrations/
executorsAI Agent 执行器抽象、各 Agent 实现、MCP 配置crates/executors/src/executors/mod.rs, mcp_config.rs
services业务逻辑封装、容器管理、配置服务crates/services/src/services/
deployment部署策略抽象(本地/远程)crates/deployment/src/lib.rs
local-deployment本地部署具体实现crates/local-deployment/src/lib.rs
remote远程服务器实现、ElectricSQL 集成、认证crates/remote/src/app.rs, shapes.rs
api-types前后端共享类型定义crates/api-types/src/
gitGit 操作封装(分支、提交、工作树)crates/git/src/
mcpMCP 服务器实现(任务服务器)crates/mcp/src/

模块间调用关系与数据流向

典型请求流程(创建 Workspace)

1. 前端发起请求
   POST /api/remote/workspaces

2. HTTP 路由接收
   crates/server/src/routes/remote/workspaces.rs

3. 调用业务服务
   crates/services/src/services/container.rs::ContainerService::create()

4. 数据库操作
   crates/db/src/models/workspace.rs::Workspace::create()

5. 返回结果
   Workspace { id, branch, container_ref, ... }

6. 前端更新状态
   ElectricSQL 同步到所有连接的客户端

Agent 执行流程

1. 用户触发 Agent 执行

2. 创建 ExecutionProcess 记录
   db::models::execution_process::ExecutionProcess::create()

3. 选择执行器
   executors::executors::get_executor(agent_type)

4. 构建命令
   executor.build_command(prompt, config)

5. 生成进程
   executor.spawn(current_dir, prompt, env)

6. 流式输出日志
   executor.stream_logs() → WebSocket → 前端

7. 更新状态
   执行完成 → 更新 ExecutionProcess.status

4. 核心流程解析

应用启动流程

后端启动(crates/server/src/main.rs

// 1. 安装 rustls 加密提供者
rustls::crypto::aws_lc_rs::default_provider()
    .install_default()
    .expect("Failed to install rustls crypto provider");

// 2. 初始化 Sentry 错误追踪
sentry_utils::init_once(SentrySource::Backend);

// 3. 配置日志系统
let log_level = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
let filter_string = format!(
    "warn,server={level},services={level},db={level},...",
    level = log_level
);
let env_filter = EnvFilter::try_new(filter_string)...;
tracing_subscriber::registry()
    .with(tracing_subscriber::fmt::layer().with_filter(env_filter))
    .with(sentry_layer())
    .init();

// 4. 创建资源目录
if !asset_dir().exists() {
    std::fs::create_dir_all(asset_dir())?;
}

// 5. 迁移数据库(旧版本 → 新版本)
let old_db = asset_dir().join("db.sqlite");
let new_db = asset_dir().join("db.v2.sqlite");
if !new_db.exists() && old_db.exists() {
    std::fs::copy(&old_db, &new_db)?;
}

// 6. 初始化部署实例(核心)
let deployment = DeploymentImpl::new().await?;
// 内部完成:数据库连接、迁移、容器服务初始化等

// 7. 清理孤儿执行进程
deployment.container().cleanup_orphan_executions().await?;

// 8. 预加载执行器选项缓存
tokio::spawn(async move {
    executors::executors::utils::preload_global_executor_options_cache().await;
});

// 9. 创建 Axum 路由
let app_router = routes::router(deployment.clone());

// 10. 绑定端口并启动服务
let main_listener = tokio::net::TcpListener::bind(format!("{host}:{port}")).await?;
let proxy_listener = tokio::net::TcpListener::bind(format!("{host}:{proxy_port}")).await?;

// 11. 启动两个服务器(主服务 + 预览代理)
let main_server = axum::serve(main_listener, app_router)...;
let proxy_server = axum::serve(proxy_listener, proxy_router)...;

// 12. 等待关闭信号
tokio::select! {
    _ = shutdown_signal() => {},
    _ = main_handle => {},
    _ = proxy_handle => {},
}

// 13. 清理资源(终止所有运行中的容器进程)
perform_cleanup_actions(&deployment).await;

前端启动(packages/local-web/src/app/entry/App.tsx

// 1. Bootstrap 组件加载配置
<Bootstrap>
  // 2. 主题提供者
  <ThemeProvider>
    // 3. 配置提供者(加载全局设置)
    <ConfigProvider>
      // 4. 用户提供者(认证状态)
      <UserProvider>
        // 5. 终端提供者(xterm.js 实例管理)
        <TerminalProvider>
          // 6. 键盘快捷键提供者
          <SequenceTrackerProvider>
            // 7. 主应用布局
            <SharedAppLayout />
          </SequenceTrackerProvider>
        </TerminalProvider>
      </UserProvider>
    </ConfigProvider>
  </ThemeProvider>
</Bootstrap>

重要业务流程

流程 1:创建 Workspace 并启动 Agent

调用链路

前端路由:packages/local-web/src/routes/_app.workspaces_.create.tsx
  ↓ POST /api/workspaces
后端路由:crates/server/src/routes/workspaces.rs::create_workspace()

服务层:crates/services/src/services/container.rs::ContainerService::create_workspace()

数据库:crates/db/src/models/workspace.rs::Workspace::create()

返回 Workspace 对象

前端:导航到 /workspaces/{workspaceId}

用户:点击"Start Agent"
  ↓ POST /api/task_attempts
后端:crates/server/src/routes/task_attempts.rs::create_task_attempt()

服务层:创建 ExecutionProcess

执行器:crates/executors/src/executors/{agent}.rs::spawn()

进程启动:tokio::process::Command::spawn()

日志流:WebSocket → 前端终端组件

关键代码片段crates/executors/src/executors/claude.rs):

#[async_trait]
impl StandardCodingAgentExecutor for ClaudeCode {
    async fn spawn(
        &self,
        current_dir: &Path,
        prompt: &str,
        env: &ExecutionEnv,
    ) -> Result<SpawnedChild, ExecutorError> {
        // 1. 构建命令
        let mut builder = CommandBuilder::new("npx")
            .args(["-y", "@anthropic-ai/claude-code"])
            .args(["--verbose", "--output-format", "stream-json"])
            .args(["--allowedTools", "Bash,Edit,Write,Glob,Grep"])
            .arg("--append-prompt")
            .arg(&self.append_prompt.combine_prompt(prompt));
        
        // 2. 添加模型配置
        if let Some(model) = &self.model {
            builder = builder.extend_params(["--model", model]);
        }
        
        // 3. 应用覆盖配置
        apply_overrides(builder, &self.cmd)
            .build_initial()?
            .spawn(current_dir, env)
    }
}

流程 2:ElectricSQL 实时同步

工作流程

1. 前端订阅 Shape
   useElectricQuery(shapeDefinition)

2. 发送 Shape 请求
   GET /shape/{shapeName}?params=...

3. 后端代理验证
   crates/remote/src/routes/electric_proxy.rs
   - 检查用户认证
   - 验证组织/项目成员资格

4. 转发到 ElectricSQL
   POST http://electric:3000/v1/shape/{shapeName}

5. ElectricSQL 返回数据
   - 初始数据快照
   - 建立 WebSocket 长连接

6. 数据变更推送
   Postgres WAL → ElectricSQL → 前端

7. 前端更新 UI
   TanStack DB 自动触发 React 重渲染

Shape 定义示例crates/remote/src/shapes.rs):

define_shape!(
    WORKSPACES_BY_PROJECT,
    "workspaces_by_project",
    Workspace,
    r#"SELECT * FROM workspaces WHERE project_id = {project_id}"#,
    ["project_id"]
);

流程 3:MCP 配置管理

调用链路

用户配置 MCP 服务器

前端:设置页面 → 保存配置
  ↓ POST /api/config/mcp
后端:crates/server/src/routes/config.rs

服务层:crates/services/src/services/config.rs

读取 Agent 配置文件
  - Claude: ~/.claude.json
  - Cursor: ~/.cursor/mcp.json
  - Codex: ~/.codex/config.json

更新 MCP 服务器配置
  crates/executors/src/mcp_config.rs::update_mcp_config()

写入文件(保留注释)
  write_jsonc_preserving_comments()

重启 Agent(可选)

MCP 配置结构

pub struct McpConfig {
    pub servers: HashMap<String, serde_json::Value>,  // MCP 服务器配置
    pub servers_path: Vec<String>,                    // 搜索路径
    pub template: serde_json::Value,                  // 默认模板
    pub preconfigured: serde_json::Value,             // 预配置服务器
    pub is_toml_config: bool,                         // 是否 TOML 格式
}

流程 4:Git 工作区管理

Workspace 创建流程

1. 接收创建请求
   POST /api/workspaces
   { project_id, issue_id, ... }

2. 生成唯一分支名
   let branch = format!("vibe-kanban/{}", uuid::Uuid::new_v4());

3. 创建 Git 分支
   git::ops::create_branch(repo_path, &branch, base_branch)?;

4. 记录到数据库
   Workspace::create(pool, &data, id).await?;

5. 返回工作区信息
   { id, branch, agent_working_dir, ... }

关键代码crates/git/src/ops.rs):

pub fn create_branch(
    repo_path: &Path,
    branch_name: &str,
    base_branch: &str,
) -> Result<(), GitError> {
    let repo = Repository::open(repo_path)?;
    
    // 查找基础分支
    let base_ref = repo.find_reference(&format!("refs/heads/{}", base_branch))?;
    let base_commit = base_ref.peel_to_commit()?;
    
    // 创建新分支
    repo.branch(branch_name, &base_commit, false)?;
    
    Ok(())
}

5. 关键设计与实现

设计模式

1. 策略模式(Strategy Pattern)- Agent 执行器

应用场景:不同 AI Agent 的执行逻辑差异很大,但需要统一的接口

// Trait 定义(策略接口)
#[async_trait]
pub trait StandardCodingAgentExecutor: Send + Sync {
    async fn spawn(
        &self,
        current_dir: &Path,
        prompt: &str,
        env: &ExecutionEnv,
    ) -> Result<SpawnedChild, ExecutorError>;
    
    fn build_command_builder(&self) -> Result<CommandBuilder, CommandBuildError>;
}

// 具体策略实现(支持的 AI Agent)
pub struct ClaudeCode {
    pub model: Option<String>,
    pub approvals: Option<bool>,
    pub plan: Option<bool>,
    // ... 其他配置
}

pub struct Codex {
    pub sandbox: Option<SandboxMode>,
    pub ask_for_approval: Option<AskForApproval>,
    pub model: Option<String>,
    // ... 其他配置
}

pub struct CursorAgent { ... }
pub struct Copilot { ... }
pub struct Gemini { ... }
pub struct QwenCode { ... }
pub struct Amp { ... }
pub struct Opencode { ... }
pub struct Droid { ... }

// 上下文使用
pub fn get_executor(agent_type: &str) -> Box<dyn StandardCodingAgentExecutor> {
    match agent_type {
        "claude-code" => Box::new(ClaudeCode::default()),
        "codex" => Box::new(Codex::default()),
        "cursor" => Box::new(CursorAgent::default()),
        _ => panic!("Unknown executor"),
    }
}

优势

  • 新增 Agent 只需实现 trait,无需修改现有代码
  • 运行时动态切换 Agent
  • 统一的错误处理和日志记录

2. 工厂模式(Factory Pattern)- 部署实例

应用场景:根据编译目标(本地/远程)创建不同的部署实例

// crates/server/src/lib.rs
// #[cfg(feature = "cloud")]
// type DeploymentImpl = vibe_kanban_cloud::deployment::CloudDeployment;
// #[cfg(not(feature = "cloud"))]
pub type DeploymentImpl = local_deployment::LocalDeployment;

使用

// main.rs
let deployment = DeploymentImpl::new().await?;
// 编译时决定使用 LocalDeployment 或 CloudDeployment

3. 构建者模式(Builder Pattern)- 命令构建

应用场景:构建复杂的命令行参数

pub struct CommandBuilder {
    command: String,
    args: Vec<String>,
    env: HashMap<String, String>,
}

impl CommandBuilder {
    pub fn new(cmd: &str) -> Self { ... }
    
    pub fn args<I, S>(mut self, args: I) -> Self
    where
        I: IntoIterator<Item = S>,
        S: Into<String>,
    {
        self.args.extend(args.into_iter().map(Into::into));
        self
    }
    
    pub fn param(mut self, key: &str, value: &str) -> Self {
        self.args.push(format!("--{}={}", key, value));
        self
    }
    
    pub fn build(self) -> Command { ... }
}

// 使用示例
let command = CommandBuilder::new("npx")
    .args(["-y", "@anthropic-ai/claude-code"])
    .param("model", "claude-sonnet-4-20250514")
    .param("allowed-tools", "Bash,Edit,Write")
    .build();

数据模型 / 数据库设计

核心表结构

核心数据表(基于 crates/db/migrations/20250617183714_init.sql 及后续迁移):

projects 表

CREATE TABLE projects (
    id            BLOB PRIMARY KEY,
    name          TEXT NOT NULL,
    git_repo_path TEXT NOT NULL DEFAULT '' UNIQUE,
    setup_script  TEXT DEFAULT '',
    created_at    TEXT NOT NULL DEFAULT (datetime('now', 'subsec')),
    updated_at    TEXT NOT NULL DEFAULT (datetime('now', 'subsec'))
);

tasks 表

CREATE TABLE tasks (
    id          BLOB PRIMARY KEY,
    project_id  BLOB NOT NULL,
    title       TEXT NOT NULL,
    description TEXT,
    status      TEXT NOT NULL DEFAULT 'todo'
                   CHECK (status IN ('todo','inprogress','done','cancelled','inreview')),
    created_at  TEXT NOT NULL DEFAULT (datetime('now', 'subsec')),
    updated_at  TEXT NOT NULL DEFAULT (datetime('now', 'subsec')),
    FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);

workspaces 表(后续迁移添加):

CREATE TABLE workspaces (
    id                BLOB PRIMARY KEY,
    task_id           BLOB,
    container_ref     TEXT,              -- 容器引用/工作区路径
    branch            TEXT NOT NULL,     -- Git 分支名
    agent_working_dir TEXT,
    setup_completed_at TEXT,
    created_at        TEXT NOT NULL,
    updated_at        TEXT NOT NULL,
    archived          INTEGER NOT NULL DEFAULT 0,
    pinned            INTEGER NOT NULL DEFAULT 0,
    name              TEXT
);

task_attempts 表

CREATE TABLE task_attempts (
    id            BLOB PRIMARY KEY,
    task_id       BLOB NOT NULL,
    worktree_path TEXT NOT NULL,
    merge_commit  TEXT,
    executor      TEXT,
    stdout        TEXT,
    stderr        TEXT,
    created_at    TEXT NOT NULL,
    updated_at    TEXT NOT NULL,
    FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
);

task_attempt_activities 表

CREATE TABLE task_attempt_activities (
    id              BLOB PRIMARY KEY,
    task_attempt_id BLOB NOT NULL,
    status          TEXT NOT NULL DEFAULT 'init'
                       CHECK (status IN (
                           'init','setuprunning','setupcomplete','setupfailed',
                           'executorrunning','executorcomplete','executorfailed','paused'
                       )),
    note            TEXT,
    created_at      TEXT NOT NULL,
    FOREIGN KEY (task_attempt_id) REFERENCES task_attempts(id) ON DELETE CASCADE
);

sessions 表(后续迁移添加):

CREATE TABLE sessions (
    id          BLOB PRIMARY KEY,
    workspace_id BLOB NOT NULL,
    executor    TEXT,
    created_at  TEXT NOT NULL,
    updated_at  TEXT NOT NULL
);

execution_processes 表(后续迁移添加):

CREATE TABLE execution_processes (
    id              BLOB PRIMARY KEY,
    session_id      BLOB NOT NULL,
    status          TEXT NOT NULL,     -- running/completed/failed/killed
    run_reason      TEXT NOT NULL,
    executor_action JSON NOT NULL,
    started_at      TEXT,
    completed_at    TEXT,
    created_at      TEXT NOT NULL,
    dropped         INTEGER NOT NULL DEFAULT 0
);

数据库迁移

迁移文件位于 crates/db/migrations/,使用 SQLx 管理:

# 创建新迁移
sqlx migrate add <migration_name>

# 运行迁移
pnpm run prepare-db

# 检查迁移(CI)
pnpm run prepare-db:check

迁移文件示例20250617183714_init.sql):

-- 创建 workspaces 表
CREATE TABLE IF NOT EXISTS workspaces (
    id TEXT PRIMARY KEY,
    task_id TEXT,
    container_ref TEXT,
    branch TEXT NOT NULL,
    agent_working_dir TEXT,
    setup_completed_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL,
    archived INTEGER NOT NULL DEFAULT 0,
    pinned INTEGER NOT NULL DEFAULT 0,
    name TEXT
);

-- 创建索引
CREATE INDEX idx_workspaces_task_id ON workspaces(task_id);
CREATE INDEX idx_workspaces_archived ON workspaces(archived);

状态管理 / 数据流方案

前端状态管理(TanStack DB + ElectricSQL)

架构

ElectricSQL (Postgres)
       ↓ HTTP
TanStack Electric Collection
       ↓ 响应式
TanStack React DB
       ↓ React Context
组件使用 useQuery()

使用示例

// 定义 Shape
const workspacesShape = defineShape({
  name: 'workspaces',
  tableName: 'workspaces',
  where: { projectId: '{projectId}' },
  columns: ['id', 'name', 'branch', 'archived', ...],
});

// 组件中使用
function WorkspaceList({ projectId }) {
  const workspaces = useQuery(
    workspacesShape,
    { projectId },
    { orderBy: { updated_at: 'desc' } }
  );
  
  return (
    <div>
      {workspaces.map(ws => (
        <WorkspaceCard key={ws.id} workspace={ws} />
      ))}
    </div>
  );
}

乐观更新

// 创建 Workspace
const createWorkspace = useMutation({
  mutationFn: async (data) => {
    // 1. 乐观更新本地 DB
    const optimisticId = uuid();
    electricCollection.insert({
      ...data,
      id: optimisticId,
      pending: true,
    });
    
    // 2. 发送请求到后端
    const response = await fetch('/api/workspaces', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    const { data: workspace, txid } = await response.json();
    
    // 3. 等待 ElectricSQL 同步(通过 txid)
    await waitForTxid(txid);
    
    // 4. 替换乐观更新为真实数据
    electricCollection.update(optimisticId, {
      ...workspace,
      pending: false,
    });
  },
});

错误处理与日志策略

后端错误处理

错误类型定义

// crates/server/src/error.rs
#[derive(Debug, Error)]
pub enum VibeKanbanError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    
    #[error(transparent)]
    Sqlx(#[from] SqlxError),
    
    #[error(transparent)]
    Deployment(#[from] DeploymentError),
    
    #[error(transparent)]
    Other(#[from] AnyhowError),
}

// executors 错误
#[derive(Debug, Error)]
pub enum ExecutorError {
    #[error("Executor not found: {0}")]
    NotFound(String),
    
    #[error("Command execution failed: {0}")]
    CommandFailed(String),
    
    #[error("MCP configuration error: {0}")]
    McpConfigError(String),
    
    #[error(transparent)]
    Io(#[from] std::io::Error),
}

错误处理最佳实践

// 1. 使用 ? 操作符传播错误
pub async fn create_workspace(
    pool: &SqlitePool,
    data: &CreateWorkspace,
) -> Result<Workspace, WorkspaceError> {
    let workspace = Workspace::create(pool, data, id).await?;
    Ok(workspace)
}

// 2. 使用 anyhow 处理非结构化错误
pub async fn complex_operation() -> anyhow::Result<()> {
    let result = some_fallible_operation().await
        .context("Failed to perform operation")?;
    Ok(())
}

// 3. 使用 tracing 记录错误上下文
pub async fn spawn_agent(...) -> Result<SpawnedChild, ExecutorError> {
    tracing::info!(
        prompt_length = prompt.len(),
        executor = %agent_type,
        "Spawning coding agent"
    );
    
    match executor.spawn(current_dir, prompt, env).await {
        Ok(child) => Ok(child),
        Err(e) => {
            tracing::error!(error = %e, "Failed to spawn agent");
            Err(e)
        }
    }
}

日志策略

日志级别配置

// main.rs
let filter_string = format!(
    "warn,server={level},services={level},db={level},executors={level}",
    level = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string())
);

// 开发环境:debug
RUST_LOG=debug pnpm run dev

// 生产环境:info
RUST_LOG=info cargo run --release

结构化日志

tracing::info!(
    workspace_id = %workspace.id,
    branch = %workspace.branch,
    "Workspace created successfully"
);

tracing::error!(
    error = %e,
    workspace_id = %workspace_id,
    "Failed to create workspace"
);

前端日志

// 使用 Sentry 进行错误追踪
import * as Sentry from '@sentry/react';

try {
  await createWorkspace(data);
} catch (error) {
  Sentry.captureException(error, {
    tags: { workspace_type: 'local' },
    extra: { data },
  });
}

安全机制

认证与授权

本地版本

  • 无强制认证(本地使用)
  • Origin 验证防止 CSRF

远程版本crates/remote/src/auth/):

// JWT 认证
pub struct JwtClaims {
    pub sub: String,      // 用户 ID
    pub email: String,
    pub exp: usize,       // 过期时间
}

// 中间件验证
pub async fn require_session(
    auth_header: Option<TypedHeader<Authorization<Bearer>>>,
    Extension(state): Extension<AppState>,
) -> Result<RequestContext, AuthError> {
    let token = auth_header.ok_or(AuthError::MissingToken)?;
    let claims = verify_jwt(token.token(), &state.jwt_secret)?;
    
    // 检查用户是否存在
    let user = db::users::find_by_id(&state.pool, &claims.sub).await?
        .ok_or(AuthError::UserNotFound)?;
    
    Ok(RequestContext { user, .. })
}

OAuth 提供商

// 支持 GitHub 和 Google
pub enum OAuthProvider {
    GitHub,
    Google,
}

// 配置(至少需要一个)
let github_client_id = std::env::var("VIBEKANBAN_REMOTE_GITHUB_CLIENT_ID");
let google_client_id = std::env::var("VIBEKANBAN_REMOTE_GOOGLE_CLIENT_ID");

// 至少一个必须配置
if github_client_id.is_err() && google_client_id.is_err() {
    panic!("At least one OAuth provider must be configured");
}

Origin 验证

防止 CSRF 攻击

// crates/server/src/middleware/origin.rs
pub async fn validate_origin(
    request: Parts,
    next: Next,
) -> Result<Response, StatusCode> {
    let origin = request.headers.get(http::header::ORIGIN);
    let host = request.headers.get(http::header::HOST);
    
    // 开发环境:允许 localhost
    if cfg!(debug_assertions) {
        if origin.map_or(false, |o| o == "http://localhost:3000") {
            return Ok(next.run(request).await);
        }
    }
    
    // 生产环境:检查 VK_ALLOWED_ORIGINS
    let allowed_origins = std::env::var("VK_ALLOWED_ORIGINS")
        .unwrap_or_default();
    
    if allowed_origins.split(',').any(|allowed| {
        origin.map_or(false, |o| o == allowed)
    }) {
        Ok(next.run(request).await)
    } else {
        Err(StatusCode::FORBIDDEN)
    }
}

ElectricSQL 安全

Shape 访问控制

// crates/remote/src/routes/electric_proxy.rs
pub async fn proxy_shape_request(
    RequestContext { user, .. }: RequestContext,
    Path(shape_name): Path<String>,
    Query(params): Query<HashMap<String, String>>,
) -> Result<Response, ApiError> {
    // 1. 验证 Shape 是否存在
    let shape = get_shape_definition(&shape_name)
        .ok_or(ApiError::ShapeNotFound)?;
    
    // 2. 检查用户是否有权访问
    match shape.scope {
        ShapeScope::Organization(org_id) => {
            check_org_membership(&user.id, &org_id).await?;
        }
        ShapeScope::Project(project_id) => {
            check_project_membership(&user.id, &project_id).await?;
        }
    }
    
    // 3. 转发请求到 ElectricSQL
    let response = reqwest::Client::new()
        .post(format!("{}/v1/shape/{}", state.electric_url, shape_name))
        .json(&params)
        .send()
        .await?;
    
    Ok(response)
}

6. 环境搭建与运行

环境依赖与前置条件

系统要求

组件版本要求说明
操作系统macOS / Linux / Windows推荐 macOS 或 Linux
Rust最新稳定版使用 rustup 安装
Node.js>= 20LTS 版本
pnpm>= 8包管理器
Git最新版本控制

可选工具

# Cargo watch(开发时自动重新编译)
cargo install cargo-watch

# SQLx CLI(数据库迁移)
cargo install sqlx-cli

# Docker(远程部署)
# 参考 https://docs.docker.com/get-docker/

安装步骤

1. 克隆仓库

git clone https://github.com/BloopAI/vibe-kanban.git
cd vibe-kanban

2. 安装 Rust

# 使用 rustup 安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# 验证安装
rustc --version
cargo --version

3. 安装 Node.js 和 pnpm

# 使用 nvm 安装 Node.js(推荐)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 20
nvm use 20

# 安装 pnpm
npm install -g pnpm

# 验证安装
node --version  # 应该 >= 20
pnpm --version  # 应该 >= 8

4. 安装依赖

# 安装 pnpm 依赖
pnpm install

# 安装 Rust 依赖(自动完成)

5. 准备数据库

# 初始化 SQLite 数据库(本地)
pnpm run prepare-db

# 如果是远程部署,准备 PostgreSQL
pnpm run remote:prepare-db

启动开发环境

启动本地开发服务器

# 一键启动(后端 + 前端)
pnpm run dev

这会:

  1. 自动分配端口(前端 3000,后端 3001)
  2. 启动 Rust 后端(带热重载)
  3. 启动 Vite 前端开发服务器
  4. 自动打开浏览器

分别启动

# 只启动后端(带热重载)
pnpm run backend:dev:watch

# 只启动前端
pnpm run local-web:dev

访问应用

打开浏览器访问:http://localhost:3000(端口可能自动变化,查看终端输出)

关键环境变量

本地开发环境变量

创建 .env 文件(可选):

# 端口配置(可选,默认自动分配)
FRONTEND_PORT=3000
BACKEND_PORT=3001
HOST=127.0.0.1

# MCP 服务器配置
MCP_HOST=127.0.0.1
MCP_PORT=3001

# PostHog 分析(可选)
POSTHOG_API_KEY=your_key
POSTHOG_API_ENDPOINT=https://app.posthog.com

# 允许的来源(自托管时必需)
VK_ALLOWED_ORIGINS=http://localhost:3000

# 禁用工作树清理(调试用)
DISABLE_WORKTREE_CLEANUP=1

远程部署环境变量

# JWT 密钥(必需)
VIBEKANBAN_REMOTE_JWT_SECRET=your-secret-key-here

# OAuth 配置(至少一个)
VIBEKANBAN_REMOTE_GITHUB_CLIENT_ID=github_client_id
VIBEKANBAN_REMOTE_GITHUB_CLIENT_SECRET=github_client_secret
VIBEKANBAN_REMOTE_GOOGLE_CLIENT_ID=google_client_id
VIBEKANBAN_REMOTE_GOOGLE_CLIENT_SECRET=google_client_secret

# 数据库配置
DATABASE_URL=postgresql://user:password@localhost:5432/vibekanban

# ElectricSQL 配置
ELECTRIC_URL=http://localhost:3000

# 前端 URL(构建时)
VITE_APP_BASE_URL=https://vibekanban.example.com
VITE_API_BASE_URL=https://api.vibekanban.example.com

构建生产版本

构建本地版本

# 构建 Rust 后端
cargo build --release

# 构建前端
cd packages/local-web
pnpm run build

# 构建 npx CLI
pnpm run build:npx
cd npx-cli
pnpm pack

Docker 构建(远程)

# 从 crates/remote 目录构建
cd crates/remote
docker compose --env-file .env.remote up --build

测试

# Rust 测试
cargo test --workspace

# 前端类型检查
pnpm run check

# 前端 Lint
pnpm run lint

# 后端 Lint
pnpm run backend:lint

格式化代码

# 格式化所有代码
pnpm run format

7. 推荐学习路线

第一阶段:入门(1-2 周)

目标

理解项目整体架构,能够运行和调试项目

阅读顺序

  1. 项目文档(第 1 天)

    • README.md - 项目概述
    • AGENTS.md - 开发规范
    • docs/getting-started.mdx - 用户入门指南
  2. 代码结构(第 2-3 天)

    • Cargo.toml - Rust workspace 配置
    • package.json - pnpm workspace 配置
    • crates/server/src/main.rs - 后端入口
    • packages/local-web/src/app/entry/App.tsx - 前端入口
  3. 核心概念(第 4-5 天)

    • Workspace 概念:crates/db/src/models/workspace.rs
    • Session 概念:crates/db/src/models/session.rs
    • Executor 概念:crates/executors/src/executors/mod.rs
  4. 实践任务

    • 在本地成功启动项目
    • 创建一个 Workspace 并运行一次 Agent
    • 修改前端的一个文本,验证热重载

关键理解点

  • 理解 Workspace、Session、ExecutionProcess 的关系
  • 理解前后端通信流程
  • 理解 ElectricSQL 同步机制的基本原理
  • 能够使用调试工具(tracing 日志、浏览器 DevTools)

第二阶段:进阶(2-4 周)

目标

深入理解核心模块,能够修改和扩展功能

学习模块

  1. Executor 系统(第 1 周)

    • 阅读:crates/executors/src/executors/mod.rs
    • 深入一个具体执行器:crates/executors/src/executors/claude.rs
    • 理解 MCP 配置:crates/executors/src/mcp_config.rs
    • 实践:添加一个新的 Executor 配置选项
  2. 数据库层(第 2 周)

    • 阅读:crates/db/src/models/mod.rs
    • 理解迁移系统:crates/db/migrations/
    • 学习 SQLx 使用模式
    • 实践:添加一个新字段到 Workspace 表
  3. HTTP API 层(第 3 周)

    • 阅读:crates/server/src/routes/mod.rs
    • 深入一个路由:crates/server/src/routes/workspaces.rs
    • 理解中间件:crates/server/src/middleware/mod.rs
    • 实践:添加一个新的 API 端点
  4. 前端架构(第 4 周)

    • 阅读:packages/local-web/src/routes/_app.tsx
    • 理解 TanStack Router:packages/local-web/src/routeTree.gen.ts
    • 学习 ElectricSQL 集成:packages/web-core/src/hooks/
    • 实践:添加一个新的前端页面

关键理解点

  • 理解 Executor trait 设计和实现
  • 掌握 SQLx 异步数据库操作
  • 理解 Axum 路由和中间件机制
  • 掌握 TanStack Router 和 ElectricSQL 集成
  • 理解前后端类型生成机制(ts-rs)

第三阶段:精通(1-2 月)

目标

掌握高级主题,能够独立设计和实现新功能

深入学习

  1. ElectricSQL 深度集成

    • 阅读:crates/remote/src/shapes.rs
    • 理解 Shape 定义和同步机制
    • 学习 txid 握手机制
    • 实践:添加一个新的 Shape 定义
  2. 远程部署架构

    • 阅读:crates/remote/src/app.rs
    • 理解认证授权系统
    • 学习 Docker 部署配置
    • 实践:部署一个本地测试实例
  3. 性能优化

    • 学习缓存策略:crates/executors/src/executors/utils.rs
    • 理解并发控制
    • 分析性能瓶颈
    • 实践:优化一个慢查询或接口
  4. 测试与质量保证

    • 学习 Rust 测试:crates/*/src/**/*.rs 中的 #[cfg(test)]
    • 学习前端测试策略
    • 实践:为新功能编写测试

实践项目建议

  1. 添加新的 AI Agent 支持

    • 实现一个新的 Executor
    • 添加前端配置 UI
    • 编写文档
  2. 增强 MCP 配置管理

    • 添加 MCP 服务器市场
    • 实现配置导入导出
    • 添加配置验证
  3. 改进工作区管理

    • 添加工作区模板
    • 实现工作区克隆
    • 添加批量操作
  4. 优化用户体验

    • 添加键盘快捷键
    • 改进错误提示
    • 添加性能监控

8. 常见问题与注意事项

容易踩的坑

1. 端口冲突

问题:启动时报端口已被占用

解决方案

# 方法 1:使用自动端口分配(默认)
unset FRONTEND_PORT BACKEND_PORT
pnpm run dev

# 方法 2:手动指定不同端口
export FRONTEND_PORT=3002
export BACKEND_PORT=3003
pnpm run dev

# 方法 3:查找占用端口的进程
lsof -i :3000  # macOS/Linux
netstat -ano | findstr :3000  # Windows

2. 数据库迁移失败

问题pnpm run prepare-db 失败

可能原因

  • SQLx 离线模式数据过期
  • 数据库文件损坏

解决方案

# 删除旧数据库和缓存
rm -rf crates/db/.sqlx
rm -rf assets/db.v2.sqlite

# 重新准备数据库
pnpm run prepare-db

3. Rust 编译错误

问题:依赖编译失败或版本冲突

解决方案

# 更新 Rust 工具链
rustup update

# 清理构建缓存
cargo clean

# 重新构建
cargo build

4. 前端类型错误

问题:TypeScript 类型不匹配

可能原因

  • Rust 类型变更后未重新生成 TypeScript 类型

解决方案

# 重新生成类型
pnpm run generate-types

# 检查类型
pnpm run check

5. ElectricSQL 同步问题

问题:前端数据不同步或卡住

排查步骤

  1. 检查 ElectricSQL 服务是否运行
  2. 查看浏览器控制台网络请求
  3. 检查 Shape 定义是否正确
  4. 验证 txid 握手机制

代码中的特殊约定

1. 命名规范

Rust

// 文件名:snake_case
// crates/executors/src/standard_coding_agent.rs

// 模块名:snake_case
mod coding_agent;

// 类型名:PascalCase
pub struct CodingAgent;

// 函数名:snake_case
pub fn create_workspace() {}

// 常量:SCREAMING_SNAKE_CASE
const MAX_WORKSPACE_NAME_LEN: usize = 60;

TypeScript

// 文件名:kebab-case 或 PascalCase(组件)
// routes/workspace-list.tsx
// components/WorkspaceCard.tsx

// 组件名:PascalCase
function WorkspaceCard() {}

// 函数/变量:camelCase
const createWorkspace = () => {};

// 类型:PascalCase
interface Workspace {
  id: string;
  name: string;
}

// 常量:UPPER_CASE
const MAX_NAME_LENGTH = 60;

2. 错误处理约定

// 库代码:使用具体错误类型
pub fn operation() -> Result<T, SpecificError> { ... }

// 应用代码:使用 anyhow
pub fn operation() -> anyhow::Result<T> { ... }

// 永远不要吞掉错误
// 错误做法:
if let Err(e) = operation() {
    // 什么都不做
}

// 正确做法:
if let Err(e) = operation() {
    tracing::error!(error = %e, "Operation failed");
    return Err(e);
}

3. 数据库操作约定

// 所有数据库操作使用 sqlx::query! 或 sqlx::query_as!
// 编译时检查 SQL 语法

// 查询单个记录
let workspace = sqlx::query_as!(
    Workspace,
    r#"SELECT * FROM workspaces WHERE id = $1"#,
    id
)
.fetch_optional(pool)
.await?;

// 查询多个记录
let workspaces = sqlx::query_as!(
    Workspace,
    r#"SELECT * FROM workspaces WHERE archived = FALSE"#,
)
.fetch_all(pool)
.await?;

// 插入记录
let workspace = sqlx::query_as!(
    Workspace,
    r#"INSERT INTO workspaces (id, branch, ...) VALUES ($1, $2, ...) RETURNING *"#,
    id,
    branch,
    ...
)
.fetch_one(pool)
.await?;

4. 前端数据获取约定

// 使用 ElectricSQL 进行实时数据
const workspaces = useQuery(
  workspacesShape,
  { projectId },
  { orderBy: { updated_at: 'desc' } }
);

// 使用 TanStack Query 进行一次性请求
const { data } = useQuery({
  queryKey: ['workspace', workspaceId],
  queryFn: () => fetch(`/api/workspaces/${workspaceId}`),
});

// 使用 Mutation 进行写操作
const mutation = useMutation({
  mutationFn: (data) => fetch('/api/workspaces', {
    method: 'POST',
    body: JSON.stringify(data),
  }),
});

值得注意的 TODO / 技术债务

已知限制

  1. SQLite vs PostgreSQL 差异

    • 本地使用 SQLite,远程使用 PostgreSQL
    • 某些 SQL 语法不兼容,需要注意
    • [待确认] 是否有自动化测试覆盖两种数据库
  2. ElectricSQL 仅用于远程版本

    • 本地版本没有实时同步
    • 前端需要处理两种数据源
    • 可能增加维护成本
  3. Executor 配置的持久化

    • 当前配置存储在用户本地文件
    • 多设备同步需要手动导出导入
    • [待确认] 是否有云同步计划
  4. 测试覆盖率

    • 核心逻辑有单元测试
    • 集成测试覆盖不足
    • 前端测试较少
  5. 文档完整性

    • 用户文档较完整
    • API 文档需要补充
    • 架构设计文档需要更新

改进方向

  1. 性能优化

    • 数据库查询优化(添加更多索引)
    • 前端 bundle 大小优化
    • ElectricSQL 同步性能
  2. 用户体验

    • 添加更多键盘快捷键
    • 改进错误提示和恢复
    • 添加引导教程
  3. 可维护性

    • 增加集成测试
    • 完善 API 文档
    • 添加架构决策记录(ADR)
  4. 功能扩展

    • 支持更多 AI Agent
    • 添加团队协作功能
    • 集成更多 Git 托管平台

附录:快速参考

常用命令速查

# 开发
pnpm run dev                    # 启动开发环境
pnpm run backend:dev:watch      # 只启动后端(热重载)
pnpm run local-web:dev          # 只启动前端

# 构建
pnpm run build:npx              # 构建 npx CLI
cargo build --release           # 构建 Rust 后端

# 测试
cargo test --workspace          # Rust 测试
pnpm run check                  # 前端类型检查
pnpm run lint                   # 前端 Lint

# 数据库
pnpm run prepare-db             # 准备 SQLite 数据库
pnpm run remote:prepare-db      # 准备 PostgreSQL 数据库

# 类型生成
pnpm run generate-types         # 生成 TypeScript 类型
pnpm run remote:generate-types  # 生成远程类型

# 代码格式化
pnpm run format                 # 格式化所有代码

关键目录速查

# 后端核心
crates/server/src/main.rs           # 后端入口
crates/server/src/routes/mod.rs     # 路由定义
crates/db/src/models/               # 数据模型
crates/executors/src/executors/     # Agent 执行器

# 前端核心
packages/local-web/src/routes/      # 页面路由
packages/web-core/src/hooks/        # 共享 Hooks
packages/ui/src/components/         # UI 组件

# 配置
Cargo.toml                          # Rust workspace 配置
package.json                        # pnpm workspace 配置
crates/db/migrations/               # 数据库迁移

关键概念速查

概念说明关键文件
Workspace独立的工作区(Git 分支)crates/db/src/models/workspace.rs
Session工作区中的会话(Agent 实例)crates/db/src/models/session.rs
ExecutionProcess具体的执行进程crates/db/src/models/execution_process.rs
ExecutorAI Agent 执行器抽象crates/executors/src/executors/mod.rs
MCPModel Context Protocolcrates/executors/src/mcp_config.rs
ShapeElectricSQL 数据订阅crates/remote/src/shapes.rs
txidPostgres 事务 ID(用于同步)crates/remote/src/response.rs

最后更新:2026-02-25
维护者:Vibe Kanban 团队
贡献指南:请在 PR 前通过 GitHub Discussions 或 Discord 讨论想法和变更