内容
<p align="center">
<h1 align="center">代码指挥官</h1>
<p align="center">
<strong>实时查看 AI 代理的实际操作。<br/>运行多个编码代理会话。实时查看每个文件更改。一个协调器控制所有。</strong>
</p>
<p align="center">
<a href="#问题所在">问题所在</a> · <a href="#工作原理">工作原理</a> · <a href="#协调器">协调器</a> · <a href="#快速入门">快速入门</a> · <a href="#架构">架构</a>
</p>
<p align="center">
<a href="https://github.com/Dominien/code-commander/stargazers"><img src="https://img.shields.io/github/stars/Dominien/code-commander?style=flat&color=58a6ff" alt="Stars"></a>
<a href="https://github.com/Dominien/code-commander/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-blue?style=flat" alt="License"></a>
<a href="https://github.com/Dominien/code-commander/releases"><img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey?style=flat" alt="Platform"></a>
</p>
</p>
<br/>
<!-- TODO: replace with actual screenshot or demo GIF -->
<!-- <p align="center"><img src="docs/demo.gif" width="900" /></p> -->
## 问题所在
你在一个终端中运行编码代理。它编辑文件,运行命令,构建功能。但是你看不到它在做什么。你盯着终端,滚动过去,只有在完成后才能通过 `git diff` 知道有什么变化。
现在,将其乘以三或四个仓库——一个前端,一个后端,一个共享库。你有多个终端窗口打开,每个窗口都有代理运行,但你无法实时查看所有仓库中实际编写的代码。
目前所有的工具都给你一个聊天窗口。没有一个工具能实时显示代码更改,让你浏览文件树或在代理工作时查看差异。
这就是 Commander 解决的问题。
<br/>
## 工作原理
```mermaid
graph LR
subgraph Commander["代码指挥官"]
direction TB
SB["侧边栏<br/>所有项目"]
TERM["标签页终端<br/>代理 + shell 标签页"]
DIFF["差异视图<br/>每个更改,实时更新"]
TREE["文件资源管理器<br/>更改内容,新增内容"]
ENV["环境变量<br/>每个项目密钥"]
EDIT["文件编辑器<br/>编辑和保存"]
end
YOU([你]) --> SB
SB --> TERM
SB --> DIFF
SB --> TREE
SB --> ENV
SB --> EDIT
style Commander fill:#0d1117,stroke:#30363d,color:#e6edf3
style YOU fill:#3fb950,stroke:#3fb950,color:#fff
```
### 1. 添加项目
在侧边栏中注册任何 git 仓库。添加任意多个项目——你的前端、后端、基础设施、库、monorepo 包。每个项目都有自己的独立工作区。
### 2. 启动会话并与代理对话
点击项目,点击 **开始会话**,在该目录中启动一个真正的 CLI 会话。这不是一个聊天包装器——它是一个完整的 PTY 终端,带有滚动条、ANSI 颜色、可点击链接和键盘输入。与你的代理对话,给它任务,问它问题。你可以在终端中做的一切,都可以在这里做。
### 3. 查看代理正在执行的操作——实时
这是 Commander 的核心。在代理工作时,你会看到:
- **实时文件树** —— 哪些文件被添加、修改或删除,实时更新并带有状态徽章
- **差异视图** —— 统一或并排差异,带有语法高亮,代理编写代码时实时刷新
- **文件编辑器** —— 点击任意文件,阅读和编辑,带有行号、脏指标和 Cmd+S 保存
- **一键恢复** —— 按文件撤销更改或恢复整个代码库
你不必等待代理完成。你不必运行 `git diff`。你实时看到每个更改。
### 5. 环境变量——安全,按项目划分
点击顶部栏中的 **Env** 按钮,打开一个类似 Vercel 的键值编辑器。设置秘密、API 密钥或每个项目的配置。值默认隐藏,带有眼形图标切换。
- 存储在 `~/.commander-central/envs/` 中 —— **永远不会在仓库中**,不会意外提交
- 自动注入到代理会话和 shell 终端中
- `.env*` 文件也会显示在文件树中,以便您可以直接编辑它们
### 6. 代理旁边的 shell 终端
每个项目都有一个 **标签页终端区域**。代理标签页始终存在,您可以根据需要创建任意多个 shell 标签页——运行开发服务器、构建、测试、linters 等。
- 点击终端标签栏中的 **+** 以创建新的 shell
- 每个 shell 都在项目目录中运行,并注入环境变量
- 关闭标签页(x)以杀死进程,或 `exit` 以自动删除它
- 所有终端在切换标签页时保持挂载——不会丢失状态
### 4. 同时管理多个会话
侧边栏显示每个项目,带有实时状态指示器:
```
🟢 活跃 —— 代理正在生成输出
🟡 等待中 —— 代理需要您的输入
🔵 启动中 —— 会话正在启动
⚪ 空闲 —— 已准备好接受下一个提示
🔴 错误 —— 会话崩溃
```
在项目之间即时切换。每个项目都保留其自己的终端历史、差异状态和文件树。切换 **自动接受** 以使代理完全自主运行,或保留手动批准。
<br/>
## 协调器
一旦您运行多个会话,您将需要一个可以看到一切的代理。协调器是一个专用的代理会话,带有 MCP 工具,使其能够控制其他所有会话。
```mermaid
graph LR
You([你]) -->|与| Orch[协调器代理]
Orch -->|启动/停止<br/>发送命令<br/>读取输出| S1[代理:前端]
Orch -->|启动/停止<br/>发送命令<br/>读取输出| S2[代理:后端]
Orch -->|启动/停止<br/>发送命令<br/>读取输出| S3[代理:基础设施]
Orch -->|读取文件<br/>查看差异| Any[任何代码库]
style Orch fill:#58a6ff,stroke:#58a6ff,color:#fff
style You fill:#3fb950,stroke:#3fb950,color:#fff
```
点击侧边栏顶部的协调器图标。它启动时带有权限绕过标志,因此它可以无中断地运行。
### 你可以对协调器说的话
> *"在所有仓库中启动会话并运行它们的测试套件"*
> *"后端代理卡住了——检查其输出并帮助它"*
> *"从前端仓库读取 API 类型并将其发送到后端代理"*
> *"哪些仓库有未提交的更改?全部提交并附上良好的消息"*
### MCP 工具
| 工具 | 描述 |
|:-----|:------------|
| `list_codebases` | 列出所有注册的仓库,带有 ID、名称和路径 |
| `get_all_statuses` | 同时获取每个代码库的会话状态 |
| `get_session_output` | 从任何会话中读取最后 N 行终端输出 |
| `send_to_session` | 向正在运行的代理发送文本输入 |
| `start_session` | 在任何仓库中启动代理会话 |
| `stop_session` | 终止正在运行的会话 |
| `get_diff` | 从任何代码库中获取完整的 git 差异 |
| `read_file` | 从任何已注册的代码库中读取文件 |
<br/>
## 快速入门
```bash
git clone https://github.com/Dominien/code-commander.git
cd code-commander
npm install
npm run dev
```
**前提条件**
- Node.js 20+
- 基于 CLI 的 AI 编码代理已安装并在您的 PATH 中
- Git
<br/>
## 架构
```mermaid
graph TB
subgraph Electron["<b>Electron 主进程</b>"]
direction TB
CM["<b>代码库管理器</b><br/>生命周期编排"]
CM --> SC1["会话控制器<br/><i>仓库 A</i>"]
CM --> SC2["会话控制器<br/><i>仓库 B</i>"]
CM --> SC3["会话控制器<br/><i>仓库 N...</i>"]
CM --> ORC["会话控制器<br/><i>协调器</i>"]
CM --> API["McpServer<br/><i>本地 HTTP API</i>"]
SC1 --- PTY1["node-pty → 代理 CLI"]
SC1 --- GIT1["GitManager<br/>差异 · 文件树 · 编辑 · 恢复"]
SC1 --- FW1["FileWatcher<br/>轮询 · 无 EMFILE"]
SC1 --- SH1["ShellManager<br/>多个 shell PTY"]
CM --- ENV["EnvStore<br/>每个项目的环境变量<br/><i>~/.commander-central/envs/</i>"]
SC2 --- PTY2["node-pty → 代理 CLI"]
SC3 --- PTY3["node-pty → 代理 CLI"]
ORC --- PTY4["node-pty → 代理 CLI<br/><i>带有 MCP 工具</i>"]
end
subgraph MCP["<b>MCP 桥(stdio ↔ HTTP)</b>"]
BRG["mcp-bridge.cjs"]
end
PTY4 <-->|"stdin/stdout<br/>(MCP 协议)"| BRG
BRG <-->|"HTTP<br/>localhost"| API
subgraph UI["<b>渲染进程</b>"]
direction TB
APP["React 19 · Zustand · Tailwind CSS 4"]
APP --- SB["侧边栏<br/>代码库列表 · 状态点"]
APP --- CV["代码库视图<br/>文件树 · 差异 · 终端"]
APP --- OV["协调器视图<br/>仪表盘 · 终端"]
end
Electron <-->|"Electron IPC<br/>预加载桥"| UI
style Electron fill:#0d1117,stroke:#30363d,color:#e6edf3
style UI fill:#0d1117,stroke:#30363d,color:#e6edf3
style MCP fill:#0d1117,stroke:#30363d,color:#e6edf3
```
### 为什么使用 stdio 桥?
大多数 CLI 代理的 MCP 实现仅支持通过 `command`/`args` 启用的服务器(stdio 传输)。它们不支持直接连接到 HTTP/SSE 端点。因此,协调器的 MCP 工具通过一个桥:
```mermaid
sequenceDiagram
participant CC as 协调器<br/>(代理 CLI)
participant Bridge as mcp-bridge.cjs
participant API as McpServer<br/>(Electron 主进程)
participant Session as 目标会话
CC->>Bridge: 通过 stdio 调用工具
Bridge->>API: HTTP POST /api/call
API->>Session: 执行(读取输出,发送输入等)
Session-->>API: 结果
API-->>Bridge: JSON 响应
Bridge-->>CC: 通过 stdio 工具结果
```
桥脚本在运行时生成,带有正确的端口和 `NODE_PATH`。
<br/>
## 技术栈
| | |
|:--|:--|
| **运行时** | Electron 33 · node-pty |
| **前端** | React 19 · TypeScript 5.6 · Tailwind CSS 4 · Zustand 5 |
| **终端** | xterm.js 5.5 (FitAddon, WebLinksAddon) |
| **Git** | simple-git · diff2html · highlight.js |
| **MCP** | @modelcontextprotocol/sdk (StdioServerTransport) |
| **存储** | electron-store |
| **构建** | electron-vite 5 · electron-builder 25 |
<br/>
## 项目结构
```
src/
├── main/ # Electron 主进程
│ ├── CodebaseManager.ts # 代码库 + 协调器生命周期
│ ├── SessionController.ts # 每个代码库的 PTY 会话管理
│ ├── ProcessManager.ts # 通过 node-pty 启动代理 CLI
│ ├── GitManager.ts # 差异、文件树、文件编辑、恢复
│ ├── FileWatcher.ts # 基于轮询(避免大仓库的 EMFILE)
│ ├── EnvStore.ts # 每个项目的环境变量持久化(JSON)
│ ├── ShellManager.ts # 每个代码库的多个 shell PTY
│ ├── ipc-handlers.ts # 所有 IPC 处理器注册
│ ├── store.ts # 持久化代码库存储
│ └── mcp/
│ ├── McpServer.ts # 工具调用的 HTTP JSON API
│ └── mcp-config.ts # 生成桥脚本 + .mcp.json
│
├── renderer/ # React 前端
│ ├── App.tsx # 根 — 视图之间的路由
│ ├── components/
│ │ ├── Sidebar.tsx # 代码库列表 + 协调器按钮
│ │ ├── CodebaseView.tsx # 主工作区(资源管理器 + 差异 + 标签页终端)
│ │ ├── OrchestratorView.tsx # 协调器仪表盘 + 终端
│ │ ├── Terminal.tsx # 带有 PTY 集成的 xterm.js(代理会话)
│ │ ├── ShellTerminal.tsx # xterm.js 包装器,用于 shell PTY
│ │ ├── DiffView.tsx # 统一/分割差异,带有语法高亮
│ │ ├── FileTree.tsx # 递归 git 感知文件资源管理器
│ │ ├── FilePreview.tsx # 文件编辑器,带有行号 + Cmd+S 保存
│ │ ├── EnvPanel.tsx # Vercel 样式的环境变量键值编辑器
│ │ ├── StatusIndicator.tsx # 动画状态点
│ │ ├── AddCodebaseDialog.tsx
│ │ └── EmptyState.tsx
│ ├── hooks/
│ │ ├── useSession.ts # 会话启动/停止/状态
│ │ ├── useDiff.ts # git 差异获取
│ │ ├── useFileTree.ts # 文件树获取
│ │ └── useIPC.ts # 实时 IPC 事件订阅
│ ├── stores/appStore.ts # Zustand — 所有 UI 状态
│ └── styles/globals.css # 暗主题 + xterm + diff2html 覆盖
│
├── shared/types.ts # 跨进程共享的 TypeScript 接口
└── preload/index.ts # 安全 IPC 桥(上下文隔离)
```
<br/>
## 开发
```bash
npm run dev # 开发服务器,带有热重载
npm run build # 生产构建
npm run package # DMG(macOS)/ AppImage(Linux)
npm run rebuild # 为您的平台重建 node-pty
```
<br/>
## 贡献
欢迎 PR。代码库足够小,可以在下午阅读。
如果您为协调器添加新的 MCP 工具:
1. 在 `src/main/mcp/McpServer.ts` 中的 `TOOLS` 数组中添加工具定义
2. 在 `handleToolCalls` switch 语句中添加处理程序
3. 就是这样——桥脚本动态获取工具
<br/>
## 许可证
[AGPL-3.0](LICENSE)