内容
# ClaudeDeck
**一个可自行托管的网页用户界面和管理员控制台,用于 [Claude Code](https://claude.com/claude-code)。**
ClaudeDeck 将 Claude Code 命令行界面转变为一个多用户聊天服务,您可以在自己的服务器上运行。用户打开浏览器,选择一个代理,然后进行聊天 - 每条消息都是在后端运行的 Claude Code,逐个 token 流式传输回来。管理员可以通过网页面板配置所有内容:使用哪个模型、每个代理可以访问哪些 MCP 服务器、代理的系统指令,以及允许哪些用户访问。
它最初是作为内部“AI 分析师”产品的可重复使用的核心开发而来,后来被提取成一个通用框架:**您可以自定义代理角色和 MCP 工具,并拥有一个围绕 Claude Code 的生产就绪型聊天应用程序,而无需编写管道代码。**
---
## 截图
**聊天** - 流式 Markdown 回复、可搜索的会话侧边栏和代理生成的工件卡(查看/复制/下载):

**结构化问题** - 代理可以询问可点击的单选/多选/自由文本问题;答案作为下一条消息返回:

**管理员控制台** - 管理代理(每个代理的模型、启用/禁用)、MCP 服务器、指令和用户,都可以在浏览器中进行:



## 为什么
Claude Code 命令行界面在终端中非常好用,但将其转变为共享的 Web 服务意味着每次都需要解决相同的问题:通过 WebSocket 流式传输 `claude -p`、持久化对话、恢复会话、允许非技术用户与其交互,并为管理员提供一种安全的方式来更改模型/工具/提示而无需重新部署。ClaudeDeck 就是这一层。
## 功能
- **流式聊天**,通过 WebSocket 实现,逐个 token 流式传输,会话历史记录在 PostgreSQL 中持久化,并支持 `--resume` 功能,在消息之间保持连续性。
- **多个代理**。每个代理都是一个 Claude Code *工作区*(其自己的 `CLAUDE.md`、规则文件、MCP 服务器和模型)。用户可以选择要交互的代理;管理员可以从面板中创建和编辑它们。
- **每个代理的 MCP 管理**。在管理员界面中添加/删除/启用 HTTP 和 SSE MCP 服务器,并检查其实时连接状态 - 无需重新部署。(stdio/command 服务器被故意拒绝通过界面,以避免将面板变成远程代码执行。)
- **实时指令编辑**。在浏览器中编辑代理的 `CLAUDE.md` 和 `.claude/rules/*.md`;更改将应用于下一条消息。
- **模型选择**。全局默认模型加上每个代理的覆盖,都可以在面板中编辑。
- **结构化输出(可选)**。代理可以发出两个标记块,UI 将其特别渲染:**问题**(可点击的单选/多选/文本表单)和最终 **工件**(显示为查看/复制/下载卡的 Markdown 文档)。参见 [结构化输出](#structured-output)。
- **本地用户帐户**,具有管理员角色,在面板中管理。密码经过 scrypt 哈希处理。
- **管理员控制台**:设置、代理、指令、MCP 服务器、用户和 Claude CLI 状态/版本。
- **Docker 化**:`docker compose up` 启动应用程序、PostgreSQL 和固定的 Claude CLI。
## 架构
```
浏览器(聊天/管理员)
│ HTTP + WebSocket
▼
Node.js + Express 后端 ──spawn──> claude -p (Claude Code CLI)
│ │
├── PostgreSQL 16 ├── agents/<key>/CLAUDE.md + .claude/rules/*.md
│ 用户/会话/消息 └── agents/<key>/.mcp.json (MCP 服务器)
│ 设置/代理
└── express-session (cookie)
```
- 每条聊天消息都会启动 `claude -p <message> --output-format stream-json --include-partial-messages --resume <id> --model <model>`,工作目录为代理的工作区。后端解析流,过滤掉标记块,并将可见文本转发到浏览器。
- CLI 版本在 `backend/Dockerfile` 中**固定**,因为流式 JSON 输出合同对版本敏感。
```
claudedeck/
├── backend/ # Node.js + TypeScript (Express, ws, pg)
│ ├── src/
│ │ ├── index.ts # 服务器,会话 cookie,WebSocket,引导和优雅关闭
│ │ ├── auth/ # 本地身份验证(登录),密码(scrypt),访问(requireAuth/Admin)
│ │ ├── claude/ # 会话管理器(spawn CLI),标记解析器,mcp-admin
│ │ ├── config/ # 设置,代理,代理逻辑(纯)
│ │ ├── db/migrate.ts # 幂等 SQL 迁移运行器
│ │ ├── ws/ # 聊天处理程序,过期 cron
│ │ └── api/ # 路由(会话/代理),管理员(设置/代理/mcp/用户)
│ └── test/ # node:test 单元测试
├── frontend/ # 静态 HTML/CSS/vanilla JS(聊天,管理员,登录)
├── agents/
│ ├── _base/ # 模板,创建新代理时复制
│ └── default/ # 内置“助手”代理
├── db/migrations/ # 001_init.sql(基本模式)
├── docker-compose.yml
└── .env.example
```
## 快速入门(Docker)
要求:Docker + Docker Compose,以及 Claude 订阅/CLI 的 API 访问。
```bash
git clone https://github.com/<you>/claudedeck.git
cd claudedeck
cp .env.example .env
# 编辑 .env:设置 SESSION_SECRET(随机 32+ 字节)和 ADMIN_PASSWORD。
# 容器以 uid 1000 运行,并将代理配置从管理员面板写入 ./agents:
sudo chown -R 1000:1000 ./agents
docker compose up -d --build
```
然后**一次性**验证 Claude CLI(其身份验证存储在命名卷中,并随容器重启):
```bash
docker compose exec -it app claude login
```
打开 `http://localhost:3000`,使用 `.env` 中的管理员凭证登录,然后开始聊天。检查管理员面板中的 **Claude CLI** 选项卡以确认 CLI 已通过身份验证。
### 首次管理员
启动时(空用户表),ClaudeDeck 使用 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 创建管理员(默认为 `admin` / `admin`,并带有警告)。**更改密码**在管理员面板中或在公开服务之前设置 `ADMIN_PASSWORD`。
## 配置
大多数内容在两个地方配置:环境变量(基础设施)和管理员面板(运行时)。环境变量位于 `.env`(参见 `.env.example` 获取完整列表):
| 变量 | 用途 | 默认值 |
|---|---|---|
| `PORT` | HTTP/WS 端口 | `3000` |
| `SESSION_SECRET` | Cookie 签名密钥(32+ 字节)。生产环境中必填。 | `change-me` |
| `COOKIE_SECURE` | 在 HTTPS 上运行时设置为 `true` | `false` |
| `APP_TITLE` | UI 中显示的品牌(也可以在面板中编辑) | `ClaudeDeck` |
| `ADMIN_USERNAME` / `ADMIN_PASSWORD` | 首次创建的管理员 | `admin` / `admin` |
| `CLAUDE_MODEL` | 代理没有覆盖时的默认模型 | `sonnet` |
| `CLAUDE_MAX_SESSIONS` | 最大并发 CLI 进程 | `5` |
| `CLAUDE_MAX_TURNS` | 每条消息的最大 CLI 回轮 | `100` |
| `CLAUDE_SESSION_EXPIRY_HOURS` | 会话空闲时标记为过期小时数 | `24` |
| `POSTGRES_*` | 数据库连接 | 参见 `.env.example` |
### 管理员面板选项
以管理员身份打开 `/admin`:
- **设置** - 默认模型(`opus` / `sonnet` / `haiku` 或确切的模型 ID)和应用程序标题。
- **代理** - 创建、编辑、启用/禁用和排序用户可以选择的代理。每个代理都有一个键(不可变)、标签和可选的每个代理模型覆盖。创建代理会从 `agents/_base` 复制模板到 `agents/<key>/`。
- **指令** - 编辑所选代理的 `CLAUDE.md` 和 `.claude/rules/*.md` 文件。更改将在下一条消息时生效(每条消息都是一个全新的 CLI 进程,读取这些文件)。
- **MCP 服务器** - 管理所选代理的 HTTP/SSE MCP 服务器并检查其实时状态。`.mcp.json`(定义)和 `.claude/settings.json`(启用 + 工具预批准)一起写入,以便服务器在非交互式 `claude -p` 中实际工作。
- **用户** - 创建/编辑/删除本地帐户,切换管理员和禁用标志,重置密码。最后一位活跃的管理员受到保护,不会被删除。
- **Claude CLI** - CLI 是否已通过身份验证,其版本和只读更新检查。
## 定义代理
代理只是 `agents/` 下的一个目录。默认代理是一个很好的例子:
```
agents/default/
├── CLAUDE.md # 角色 + 指令(代理的系统上下文)
├── .claude/
│ ├── rules/structured-output.md # 从 CLAUDE.md 引用的额外规则文件
│ └── settings.json # 启用的 MCP 服务器 + 工具允许列表(由面板管理)
└── .mcp.json # MCP 服务器定义(由面板管理)
```
要添加代理,可以在管理员面板中创建(推荐 - 它从 `_base` 构建),或者复制 `agents/_base` 到 `agents/<key>/`,编辑 `CLAUDE.md`,并在管理员 **代理** 选项卡中添加一行具有相同键的代理。
## 结构化输出
代理可以选择加入两个标记块(每个标记都在一行上)。它们会从可见的聊天文本中过滤掉,并特别渲染。所有其他内容都会作为正常的 Markdown 流式传输。
**问题** - 显示可点击的选择:
```
<<<QUESTIONS>>>
{ "questions": [
{ "id": "env", "text": "Which environment?", "type": "single", "options": ["dev","staging","prod"] },
{ "id": "notes", "text": "Anything else?", "type": "text" }
] }
<<<QUESTIONS_END>>>
```
`type` 可以是 `single`(单选)、`multi`(多选)或 `text`。用户的答案作为代理的下一条消息返回。
**工件** - 用户可以保留的最终文档:
```
<<<ARTIFACT>>>
# Title
...markdown...
<<<ARTIFACT_END>>>
```
渲染为具有查看/复制/下载功能的卡片,并保存在会话中。这些由 `agents/default/.claude/rules/structured-output.md` 为代理记录;可以重用或按代理丢弃。
## 安全说明
- **身份验证** 是本地用户名/密码,密码经过 scrypt 哈希处理,并带有签名、HTTP-only 会话 cookie。在生产环境中,请将应用程序放在 HTTPS 后面(`COOKIE_SECURE=true`)。
- **通过面板的 MCP** 仅限于 http/sse - `stdio`/`command` 服务器被拒绝,因此管理员界面不能用于在主机上运行任意命令。
- **工作区路径在 `agents/` 下隔离**;指令/MCP 文件路径被允许,并防止遍历。
- 容器以**非 root** 用户(`node`,uid 1000)运行。
- 这是单个共享的 Claude Code 身份(CLI 登录)。所有代理都使用它;代理隔离在工作区/MCP/指令级别,而不是单独的 Claude 凭证。
## 升级 Claude CLI
CLI 版本在 `backend/Dockerfile` 中**固定**(`npm install -g @anthropic-ai/claude-code@<version>`),因为此应用程序解析的流式 JSON 合同可能在版本之间更改。要升级:更新 Dockerfile 中的版本,`docker compose build app && docker compose up -d app`,然后进行流式检查。**Claude CLI** 管理员选项卡显示当前版本与最新版本,但不会自动更新。
## 开发(无 Docker)
```bash
cd backend
npm install
npm run build # tsc → dist/
npm test # node:test 单元测试
npm run dev # tsx 监视(需要可访问的 PostgreSQL + 登录的 claude CLI 在 PATH 上)
```
您需要 PostgreSQL 实例(指向 `POSTGRES_*`),`claude` CLI 在您的 `PATH` 上并已通过身份验证,以及 `CLAUDE_AGENTS_DIR` 指向存储库的 `agents/` 目录。后端在启动时应用迁移并引导默认代理 + 管理员。
## 许可证
[MIT](./LICENSE).
> 不隶属于 Anthropic。“Claude”和“Claude Code”是 Anthropic 的商标。
> ClaudeDeck 驱动 Claude Code CLI;您提供自己的 Claude 访问权限。