内容
# 动态命令行
一个自托管的看板工具,带有 REST API 后端,采用 **Organic Brutalism** 设计系统。数据存储在服务器上的扁平 JSON 文件中,无需数据库。
<img width="2522" height="1205" alt="screen2" src="https://github.com/user-attachments/assets/4b612036-ff6b-4097-8c4b-2627b3378733" />
---
## 技术栈
| 层级 | 技术 |
|---|---|
| UI | React 18 + Vite 6 |
| 样式 | Tailwind CSS v3 |
| 拖拽功能 | @dnd-kit/core + @dnd-kit/sortable |
| 后端 | Express (Node 20) |
| 存储 | 磁盘上的 JSON 文件 |
| MCP | @modelcontextprotocol/sdk |
---
## 本地运行(开发环境)
```bash
npm install
# 终端 1 — API 运行在端口 7430,数据存储在 ./dev-data
npm run server:dev
# 终端 2 — Vite 运行在端口 5173,代理 /api → 7430
npm run dev # http://localhost:5173
```
---
## 使用 Docker 运行
推荐的生产环境运行方式。
```bash
docker compose up -d
```
这会构建镜像,启动容器,并将数据持久化到一个命名的 Docker 卷(`kanban-data`)中。
应用程序在 **http://localhost:7429** 上提供服务。
### 修改端口
编辑 [docker-compose.yml](docker-compose.yml):
```yaml
ports:
- "YOUR_PORT:7429" # 只需更改左侧
```
或设置环境变量并更新两侧:
```yaml
ports:
- "8080:8080"
environment:
- PORT=8080
```
### 数据持久化
数据存储在 `kanban-data` Docker 卷的 `/data` 目录中。
写入两个文件:`projects.json` 和 `tasks.json`。
要指向主机目录:
```yaml
volumes:
- ./my-data:/data
```
### 有用的 Docker 命令
```bash
docker compose up -d # 在后台启动
docker compose down # 停止并移除容器
docker compose logs -f # 跟随日志
docker compose build --no-cache # 从头重建镜像
```
---
## 不使用 Docker 运行(生产环境构建)
```bash
npm install
npm run build # 编译前端到 dist/
npm start # 在端口 7429 上提供前端 + API 服务
```
设置环境变量进行配置:
```bash
PORT=8080 DATA_PATH=./data npm start
```
---
## 环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
| `PORT` | `7429` | Express 服务器监听的端口 |
| `DATA_PATH` | `/data` | 写入 `projects.json` 和 `tasks.json` 的目录 |
| `NODE_ENV` | — | 设置为 `production` 以禁用仅开发工具 |
---
## REST API
Express 服务器在 `/api` 下公开 JSON API。
| 方法 | 端点 | 描述 |
|---|---|---|
| GET | `/api/projects` | 列出所有项目 |
| POST | `/api/projects` | 创建项目 `{ name }` |
| GET | `/api/tasks` | 列出任务 — 过滤器:`projectId`、`status`、`tag`、`priority`、`limit` |
| POST | `/api/tasks` | 创建任务 `{ projectId, title, description?, status?, dueDate?, tags?, priority? }` |
| PUT | `/api/tasks/:id` | 更新任务 |
| PATCH | `/api/tasks/bulk` | 批量更新状态 + 顺序(用于拖拽) |
| DELETE | `/api/tasks/:id` | 删除任务 |
---
## MCP 服务器
动态命令行附带一个 [MCP](https://modelcontextprotocol.io) 服务器,允许 Claude(或任何 MCP 兼容的 AI)直接读写看板。
### 设置
MCP 服务器位于 [mcp/server.js](mcp/server.js)。它通过 HTTP 连接到正在运行的看板 API。
#### Claude 代码 / Claude 桌面版
将以下内容添加到您的 `.mcp.json`(已包含在此存储库中):
```json
{
"mcpServers": {
"kanban": {
"command": "node",
"args": ["./mcp/server.js"],
"env": {
"KANBAN_URL": "http://localhost:7429"
}
}
}
}
```
如果看板服务器运行在不同的端口,请相应地更新 `KANBAN_URL`。
#### Claude 桌面版(全局配置)
添加到 `~/Library/Application Support/Claude/claude_desktop_config.json`(macOS)或 `%APPDATA%\Claude\claude_desktop_config.json`(Windows):
```json
{
"mcpServers": {
"kanban": {
"command": "node",
"args": ["/absolute/path/to/kanban/mcp/server.js"],
"env": {
"KANBAN_URL": "http://localhost:7429"
}
}
}
}
```
### 可用的 MCP 工具
| 工具 | 描述 |
|---|---|
| `list_projects` | 列出所有项目 |
| `create_project` | 按名称创建项目 |
| `get_tasks` | 获取任务,可选过滤器(见下文) |
| `create_task` | 创建任务,包含标题、描述、状态、截止日期、标签、优先级 |
| `update_task` | 更新现有任务的任何字段 |
#### `get_tasks` 过滤器
| 参数 | 类型 | 描述 |
|---|---|---|
| `projectId` | 字符串 | 按项目过滤 |
| `status` | 字符串 | `backlog` \| `todo` \| `in_progress` \| `done` |
| `tag` | 字符串 | 按单个标签过滤 |
| `priority` | 字符串 | `none` \| `low` \| `medium` \| `high` \| `critical` |
| `limit` | 数字 | 最大结果数(在应用所有过滤器后) |
| `include_done` | 布尔值 | 包括已完成任务 — **默认值:false** |
默认情况下,已完成任务被排除,以便 Claude 只看到可执行的任务。
---
## 项目结构
```
src/ — React 前端
db.js — API 客户端(替换 IndexedDB)
App.jsx — 顶级状态和事件处理程序
components/
Board.jsx — 看板头部,导出/导入控件
Lane.jsx — 可拖拽的车道
TaskCard.jsx — 可排序的卡片
CardModal.jsx — 添加/编辑任务表单
ProjectModal.jsx — 项目 CRUD 模态框
server/ — Express 后端
server.js — HTTP 服务器,静态文件服务
app.js — Express 应用,路由注册
fileStorage.js — JSON 文件读写(项目 + 任务)
api/ — 路由处理程序
mcp/
server.js — MCP 服务器(stdio 传输)
Dockerfile — 多阶段构建(Node 20 Alpine)
docker-compose.yml — 单服务组合配置
```
---
## 功能
- **多个项目** — 创建、重命名和删除项目
- **四个固定车道** — 待办事项、待处理、进行中、已完成
- **任务卡片** — 每张卡片的标题、描述、截止日期、标签和优先级
- **拖拽** — 在车道内和车道之间重新排序卡片
- **持久化存储** — 数据写入服务器上的 JSON 文件
- **MCP 集成** — AI 代理可以通过 MCP 工具读写看板;默认情况下,已完成任务被排除
## 数据模型
四个车道(固定):`backlog` → `todo` → `in_progress` → `done`
**工作流意图:** `backlog` = 尚未批准开发的想法。`todo` = 已批准、已规范、准备好让 Claude Code 接手的任务。
任务字段:`id`、`projectId`、`title`、`description`、`dueDate`、`status`、`order`、`tags[]`、`priority`、`created_at`、`updated_at`
优先级值:`none` | `low` | `medium` | `high` | `critical`