Claudio: run Claude Code as a service

本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。

Claudio: run Claude Code as a service

Claude Code lives in a terminal. That is fine until you want to start a chat from your phone, check on an agent that is still working while you are away from the desk, or run five of them in parallel without losing track of which one needs an answer. I built Claudio to cover that gap: it runs Claude Code as a service. This post covers what Claudio is, how it talks to Claude Code and how to install it.

Claude Code 运行在终端中。这在平时没问题,但当你想要从手机发起对话、在离开工位时查看仍在运行的智能体,或者并行运行五个任务却无法追踪哪个需要回复时,就会感到不便。我构建了 Claudio 来填补这一空白:它将 Claude Code 作为一项服务来运行。本文将介绍 Claudio 是什么、它如何与 Claude Code 交互以及如何安装它。

What you get

Claudio puts the Claude Code CLI behind a REST API and a web UI. The same server also backs a Linux desktop app and an installable web app for your phone. Everything runs on your machine or your server, with your own Claude login. Chats you can start, stream and answer from a browser or over HTTP. Orchestrations: a graph of tasks run by parallel workers, each in its own git worktree. Several Claude accounts, with work moving to the one that still has quota. A review screen for what the agents changed. Projects with a task board and a team of agents. I will go through them one at a time.

你能得到什么

Claudio 将 Claude Code 命令行工具(CLI)封装在 REST API 和 Web UI 之后。同一个服务器还支持 Linux 桌面应用和可安装的手机 Web 应用。所有程序都在你的机器或服务器上运行,并使用你自己的 Claude 登录凭据。你可以通过浏览器或 HTTP 发起、流式传输并回复对话。编排功能:由并行工作者运行的任务图,每个工作者都在各自的 git 工作树中。支持多个 Claude 账号,当某个账号配额耗尽时,工作会自动转移到仍有配额的账号。提供一个用于查看智能体修改内容的审查界面。项目功能包含任务看板和智能体团队。我将逐一介绍这些功能。

The one rule: only the interface the CLI ships for programs

Claudio does not scrape the terminal, call undocumented endpoints or log in a second time on its own. It reaches Claude Code through the CLI’s flags, its stream protocol and the files it writes. docs/cli-surfaces.md lists every surface in use, one row per need. For example: Run / continue a conversation: claude -p --input-format stream-json --output-format stream-json Auth status: claude auth status --json Session history: $CLAUDE_CONFIG_DIR/projects/*/*.jsonl The practical consequence is a ceiling: what the CLI cannot do, Claudio cannot do. Web artifacts and claude.ai chat memory have no CLI surface, so Claudio does not touch them.

唯一准则:仅使用 CLI 为程序提供的接口

Claudio 不会抓取终端内容、调用未公开的端点,也不会自行进行二次登录。它通过 CLI 的标志、流协议以及它所写入的文件与 Claude Code 进行交互。docs/cli-surfaces.md 列出了所有使用的接口,每行对应一个需求。例如: 运行/继续对话:claude -p --input-format stream-json --output-format stream-json 认证状态:claude auth status --json 会话历史:$CLAUDE_CONFIG_DIR/projects/*/*.jsonl 实际的限制在于:CLI 做不到的事情,Claudio 也做不到。Web 工件(artifacts)和 claude.ai 的对话记忆没有 CLI 接口,因此 Claudio 不会触及它们。

Chats over HTTP

A chat is one long-lived claude process fed over stdin, with —resume when the process is gone. You can start one from the UI or from the API: curl -X POST http://localhost:8797/api/chats \ -H 'Content-Type: application/json' \ -d '{"prompt": "Add a unit test for parseDuration", "cwd": "/workspace/my-app"}' The request also accepts worktree (run inside a new git worktree of that name) and jsonSchema (structured output). From there you have POST /api/chats/:id/messages, /stop, /interrupt, /resume and /fork, and GET /api/chats/:id/stream to follow it. When the agent asks for permission, a question or a plan approval, you answer from the UI (or POST /api/chats/:id/permissions/:requestId). The interactive reference is served at /docs and the OpenAPI 3.1 document at /openapi.json. If you turned authentication on, send Authorization: Bearer . The UI does not poll. One server-sent events feed, GET /api/events, carries chats, prompts waiting for you, tasks, orchestrations and account rotation, and it resumes with Last-Event-ID after a drop.

通过 HTTP 进行对话

一个对话就是一个长驻的 claude 进程,通过标准输入(stdin)提供数据,当进程终止时使用 --resume 恢复。你可以从 UI 或 API 发起对话: curl -X POST http://localhost:8797/api/chats \ -H 'Content-Type: application/json' \ -d '{"prompt": "Add a unit test for parseDuration", "cwd": "/workspace/my-app"}' 该请求还接受 worktree(在指定名称的新 git 工作树中运行)和 jsonSchema(结构化输出)参数。之后,你可以使用 POST /api/chats/:id/messages、/stop、/interrupt、/resume 和 /fork,并使用 GET /api/chats/:id/stream 来跟踪对话。当智能体请求权限、提问或请求批准计划时,你可以通过 UI 回复(或通过 POST /api/chats/:id/permissions/:requestId)。交互式参考文档位于 /docs,OpenAPI 3.1 文档位于 /openapi.json。如果你开启了身份验证,请发送 Authorization: Bearer <token>。UI 不会轮询。一个服务器发送事件(SSE)流 GET /api/events 负责传输对话、待处理提示、任务、编排和账号轮换信息,并在连接中断后通过 Last-Event-ID 恢复。

Orchestrations

An orchestration is a graph of tasks. Workers run in parallel, each in its own git worktree, and their branches are merged into one integration branch. After that, a verification phase runs your checks (build, tests) on the integration branch under a timeout, and a pull request can be offered. It exists as the POST /api/orchestrations route and as a screen where you follow the run as steps. Two things to watch for: the checks need worktree: true on the graph engine, and workers do not survive a restart. A task caught by one is marked interrupted and its chat continues in a new execution while it has attempts left.

编排

编排是一组任务图。工作者并行运行,每个工作者都在各自的 git 工作树中,它们的分支会被合并到一个集成分支中。之后,验证阶段会在超时限制内对集成分支运行检查(构建、测试),并可以提交拉取请求(PR)。它以 POST /api/orchestrations 路由的形式存在,并提供一个界面让你按步骤跟踪运行过程。需要注意两点:检查需要在图形引擎上设置 worktree: true,且工作者在重启后无法存活。被中断的任务会被标记为“已中断”,只要还有剩余尝试次数,其对话就会在新的执行中继续。

Several accounts, rotated

Each Claude account gets its own CLAUDE_CONFIG_DIR and is signed in once. Claudio reads usage per window, moves new work to an account with quota before a limit is hit, replays a turn that hits its limit on the next account, and waits for the reset only when none has any quota left. There is also a small CLI, claudio-accounts, in packages/accounts.

多账号轮换

每个 Claude 账号都有自己的 CLAUDE_CONFIG_DIR 并只需登录一次。Claudio 会读取每个窗口的使用情况,在达到限制前将新工作转移到仍有配额的账号,在下一个账号上重放达到限制的轮次,并且仅在所有账号配额都耗尽时才等待重置。此外,在 packages/accounts 中还有一个名为 claudio-accounts 的小型 CLI 工具。

Reviewing changes inside Claudio

For a chat, a task or the integration branch there is a diff screen built from git and the transcript. Each edit carries the sentence Claude wrote just before it, so you read the change together with its reason.

在 Claudio 中审查更改

对于对话、任务或集成分支,有一个基于 git 和转录内容构建的差异(diff)界面。每次编辑都附带了 Claude 在编辑前写下的句子,因此你可以将更改与其原因结合起来阅读。

Projects, a board and a team

You can import a directory as a project. It gets a Tasks board with work items (AGN-12-style keys, five fixed columns, epics, milestones), and a team where each member is a Claude Code agent file with a role. With the flow switched on, a card entering a column starts that role’s run. Only you move a card to Done.

项目、看板与团队

你可以将一个目录导入为项目。它会获得一个包含工作项的任务看板(AGN-12 风格的键、五个固定列、史诗任务、里程碑),以及一个团队,其中每个成员都是一个带有角色的 Claude Code 智能体文件。开启流程后,当卡片进入某一列时,该角色的运行就会启动。只有你可以将卡片移动到“完成”状态。

Guards

Claudio can add PreToolUse hooks that hold even in bypassPermissions: no push, no —no-verify, no recursive delete outside the worktree, no secret written. They are on for orchestration workers and the flow, and configurable per project for chats. The mechanism is a settings file with only Claudio’s hooks, passed with —settings. See docs/guards.md.

防护措施

Claudio 可以添加即使在 bypassPermissions 模式下也有效的 PreToolUse 钩子:禁止推送、禁止 --no-verify、禁止在工作树外进行递归删除、禁止写入密钥。这些防护措施在编排工作者和流程中默认开启,并可针对每个项目的对话进行配置。其机制是一个仅包含 Claudio 钩子的设置文件,通过 --settings 参数传递。详见 docs/guards.md。

Install

Docker (amd64): docker run -d --init --name claudio --restart unless-stopped -p 127.0.0.1:8797:8797 \ -v claudio-config:/home/node/.claude -v claudio-data:/data -v claudio-workspace:/workspace \ ghcr.io/yeyo11/claudio Open http://localhost:8797, sign in with the owner token the container printed once (docker logs claudio), then sign in to Claude in the setup assistant. Name all three volumes, or replacing the container to update starts again with empty ones.

安装

Docker (amd64): docker run -d --init --name claudio --restart unless-stopped -p 127.0.0.1:8797:8797 \ -v claudio-config:/home/node/.claude -v claudio-data:/data -v claudio-workspace:/workspace \ ghcr.io/yeyo11/claudio 打开 http://localhost:8797,使用容器打印一次的所有者令牌登录(查看 docker logs claudio),然后在设置向导中登录 Claude。请务必命名所有三个卷,否则更新容器时会从空状态重新开始。

Desktop app (Linux x86_64, .deb or AppImage): curl -fsSL https://raw.githubusercontent.com/yeyo11/claudio/main/scripts/install.sh | bash As with any script piped to a shell, read it first. The app runs with your own claude and ~/.claude login, so nothing is sandboxed and chats start in acceptEdits.

桌面应用 (Linux x86_64, .deb 或 AppImage): curl -fsSL https://raw.githubusercontent.com/yeyo11/claudio/main/scripts/install.sh | bash 与任何通过管道传输到 shell 的脚本一样,请先阅读它。该应用使用你自己的 claude 和 ~/.claude 登录信息运行,因此没有任何沙盒限制,且对话默认以 acceptEdits 模式启动。

From source (Node 22+, pnpm 10, a logged-in claude on your PATH): git clone https://github.com/yeyo11/claudio && cd claudio pnpm install pnpm dev # API on :8797, UI on :5181 Then: open Claudio, let the setup assistant check Claude Code, press New chat, pick a directory and write a prompt.

从源码安装 (Node 22+, pnpm 10,且 PATH 中已登录 claude): git clone https://github.com/yeyo11/claudio && cd claudio pnpm install pnpm dev # API 运行在 :8797, UI 运行在 :5181 然后:打开 Claudio,让设置向导检查 Claude Code,点击“新建对话”,选择一个目录并输入提示词。

Before you expose it

A container creates an owner token on its first start. A source install or the desktop app has authentication off until you turn it on. That is right for a port bound to 127.

在暴露服务之前

容器在首次启动时会创建一个所有者令牌。源码安装或桌面应用在手动开启前,身份验证是关闭的。这对于绑定到 127.0.0.1 的端口是合适的。