请先确认后台服务在前台能够正常连接，再使用本指南。这些命令适用于受支持的常驻运行后端：Claude Code、Codex、Kiro 和 Pi。

[Hermes](/zh/reference/agents/hermes/) 通过自己的网关保持在线，不使用 Chorus 后台服务。支持评论审批命令和中断/恢复；网关不执行调研和创建想法的专用操作轮次。

## 将后台服务的运行后端升级到 0.20.0

通过[升级命令](/zh/reference/cli/#升级-cli-与插件)更新 Chorus CLI，并在不影响进行中工作的时机重启后台服务。宿主 CLI 需要单独更新。后台服务首次开始工作前，请核对对应后端的要求：

- [Codex App Server](/zh/reference/agents/codex/#0200-的-daemon-行为)：已在 codex-cli 0.157.1 上验证；后台服务的 `args` 只接受模型参数和允许的配置覆盖。使用 `--chorus-only` 时，请在 Codex 配置中确认所需 MCP 工具已获授权。
- [Claude Code stream-json](/zh/reference/agents/claude-code/#0200-的-daemon-行为)：已在 Claude Code 2.1.283 和 2.1.284 上验证；中断会优先通过协议发送，后台运行时的提问必须通过 Chorus 评论或澄清流程进行。
- [Pi RPC](/zh/reference/agents/pi/#0200-的-daemon-行为)：需要 Pi 0.85.0 或更新版本（已在 0.85.1 上验证）；`--plugins` 会更新 Chorus 相关包，但不会升级 Pi 本身。

## 选择后台服务可访问的目录

每个 `--cwd` 参数都会把一个工作目录注册为 Chorus 中的一个独立目标：

```sh
chorus daemon \
  --agent claude-code \
  --cwd /home/demo/workspace \
  --cwd /home/demo/workspace/service \
  --chorus-only
```

不指定 `--cwd` 时，Chorus 使用你启动命令时所在的目录。只有当用户需要在某个更大的根目录下选择子目录时，才使用 `--browse-root`（可重复指定）：

```sh
chorus daemon --browse-root /home/demo/workspace
```

浏览根目录只用于发现目录，不会把其中每个目录都注册为在线连接。

为项目的智能体[固定工作目录](/zh/guides/create-a-project/)时，该路径必须是本后台服务所服务的目录之一；请把它加入本后台服务的 `cwds` 集合，固定的目录才能解析为在线连接。

:::caution[限制文件系统访问]
只注册允许智能体读取和修改的目录。远程启动的智能体拥有运行后台服务的用户所具有的文件系统和工具权限。
:::

## 配置 `daemon.json`

后台服务的设置都读自 `~/.chorus/daemon.json`。常见的单智能体场景下，它是一个扁平的 JSON 对象，同时保存智能体凭据和运行选项；若要用一个后台服务同时服务多个智能体，则改为在 `agents` 数组中逐一列出，参见[在一个后台服务中运行多个智能体](#在一个后台服务中运行多个智能体)。无论哪种形式，该文件都以 `0600` 权限（仅所有者可读写）原子写入，因此写入过程中崩溃也不会留下被截断的文件。可用 `CHORUS_DAEMON_CONFIG_PATH` 指定其他文件。使用覆盖路径时，请为 CLI 与后台服务一致地设置该变量；在 shell 中导出它不会改变已运行的服务。

### 字段

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `url` | string | Chorus 服务器 URL。 |
| `apiKey` | string | 智能体 API 密钥（`cho_…`）。 |
| `agentUuid` | string | 已认证的智能体 UUID（仅供参考）。 |
| `agentName` | string | 已认证的智能体名称（仅供参考）。 |
| `cwds` | string[] | 本后台服务所服务的工作目录。每个路径都是一个独立的在线连接。 |
| `browseRoots` | string[] | 向远程工作目录发现开放的根目录。浏览根目录不会创建连接。 |
| `agent` | string | 要唤醒的本地运行后端：`"claude-code"`、`"codex"`、`"kiro"`、`"pi"` 或 `"dsh"`。 |
| `sigintTimeoutMs` | number | 中断后强制终止前的宽限时间（毫秒）；Claude Code、Codex 和 Pi 会先发送协议中断。默认 `10000`。 |
| `agents` | object[] | *可选。* 用一个后台服务服务多个独立智能体；每个条目可覆盖共享运行默认值，但不会继承 `args` 和 `env`。参见[在一个后台服务中运行多个智能体](#在一个后台服务中运行多个智能体)。 |

执行 `chorus login` 加 `chorus daemon install` 后的最简文件：

```json
{
  "url": "https://chorus.example.com",
  "apiKey": "cho_REDACTED",
  "agentUuid": "8a1c…",
  "agentName": "Build Agent",
  "cwds": ["/home/demo/work/project-a"],
  "browseRoots": ["/home/demo/work"],
  "agent": "claude-code",
  "sigintTimeoutMs": 10000
}
```

### 文件如何创建

- `chorus agents add` 是该文件首次创建的常规方式：它会校验每个已配置智能体的凭据，并将其作为 `agents` 数组中的一个条目写入。参见[连接智能体运行环境](/zh/guides/operator-onboarding/)。
- `chorus login` 校验 URL 和密钥后，写入 `url`、`apiKey`、`agentUuid` 和 `agentName`，对应一个扁平的单智能体。
- `chorus daemon install` 会额外写入 `cwds`、`browseRoots` 和 `agent`（当这些项尚未设置时，会提示输入所服务的目录和运行后端）。
- 首次在终端运行 `chorus daemon` 时，会以交互方式补全缺失的凭据并写入。

### 文件如何更新

每个写入方都执行**浅合并**：新字段合并到磁盘上已有内容之上，无关字段予以保留。重新运行 `chorus login` 会刷新凭据，而不会清除你的 `cwds`、`agent` 或 `sigintTimeoutMs`；重新运行 `chorus daemon install` 会更新所服务的目录集合，而不会丢弃凭据。缺失或损坏的文件会被当作空对象处理，因此重新登录始终能生成有效文件，而不会失败。

### 字段、命令行参数与环境变量

下表中的运行选项可通过三种方式提供。优先级为命令行参数，其次是环境变量，最后是 `daemon.json`，因此一次性的参数或环境变量覆盖无需写入文件：

| 关注点 | `daemon.json` 字段 | 命令行参数 | 环境变量 |
| --- | --- | --- | --- |
| 服务器 URL | `url` | `--url` | `CHORUS_URL` |
| API 密钥 | `apiKey` | `--api-key` | `CHORUS_API_KEY` |
| 工作目录 | `cwds` | `--cwd`（可重复） | `CHORUS_DAEMON_CWDS` |
| 浏览根目录 | `browseRoots` | `--browse-root`（可重复） | `CHORUS_DAEMON_BROWSE_ROOTS` |
| 运行后端 | `agent` | `--agent` | `CHORUS_AGENT` |
| SIGINT 宽限 | `sigintTimeoutMs` | `--sigint-timeout` | `CHORUS_DAEMON_SIGINT_TIMEOUT` |
| 权限模式 | *（不持久化）* | `--yolo` / `--chorus-only` | `CHORUS_YOLO` / `CHORUS_CHORUS_ONLY` |

权限模式特意不保存到 `daemon.json`。请在启动时传入 `--chorus-only`（或设置 `CHORUS_CHORUS_ONLY=1`）；安装为服务时，`--chorus-only` 会被写入服务单元，而不是文件。

## 在一个后台服务中运行多个智能体

一个 `chorus daemon` 进程可以**同时服务多个完全独立的智能体**（不同的人设、权限、账户，甚至不同的运行后端），而无需为每个智能体单独运行一个后台服务。把它们逐一列在 `agents` 数组中，每个条目就是一个智能体：

```json
{
  "url": "https://chorus.example.com",
  "sigintTimeoutMs": 8000,
  "agents": [
    { "apiKey": "cho_alpha", "agentType": "claude-code", "cwds": ["/home/demo/project-a"] },
    { "apiKey": "cho_beta", "agentType": "kiro", "cwds": ["/home/demo/project-b"], "permissionMode": "chorus" }
  ]
}
```

`url`、`sigintTimeoutMs` 等共享运行设置提供默认值，智能体自己的设置可覆盖这些默认值。`args` 和 `env` 只属于单个智能体，不是共享默认值。

每个智能体都有自己的身份（由其密钥决定）、自己的连接（每个 `cwds` 一个）、自己的唤醒队列和自己的运行后端，因此它们各自独立地被唤醒和运行，一个智能体出错不会影响其他智能体。在服务器端，每个智能体都以智能体、主机、目录为键，作为独立连接显示在**设置 → 智能体**中。多个智能体甚至可以共享同一个工作目录；后台服务不会让它们串行执行，因此请避免在同一个 git 工作树中并发地做互相冲突的工作（改用不同的分支或 worktree）。

:::note[向后兼容]
若没有 `agents` 数组，扁平的顶层 `url` / `apiKey` / `cwds` 会被视为唯一的一个智能体，现有的单智能体安装照旧运行，无需改动。
:::

### 每个智能体的字段

| 字段 | 含义 |
| --- | --- |
| `apiKey`（必填） | 该智能体的 `cho_` 密钥，决定其身份。 |
| `url` | Chorus 服务器（可按智能体不同，例如不同的服务器或工作区）。 |
| `agentType` | `claude-code`、`codex`、`kiro` 或 `pi`（后端可以混用）。 |
| `cwds` | 该智能体服务的工作目录（每个一个连接）。 |
| `permissionMode` | `yolo` 或 `chorus`。 |
| `maxConcurrency` | 该智能体自己的唤醒并发上限（默认 `4`）。 |
| `sigintTimeoutMs` | 中断后强制终止进程前的等待时间（毫秒）。 |
| `browseRoots` | 目录发现的允许列表。 |
| `args` | 可选的字符串数组，作为后端 CLI 的额外参数，默认 `[]`。参见[设置智能体的模型、思考级别和环境变量](#设置智能体的模型思考级别和环境变量)。 |
| `env` | 可选的对象，将环境变量名映射到字符串值，默认 `{}`。 |

### 设置智能体的模型、思考级别和环境变量

在 `~/.chorus/daemon.json` 中为目标智能体添加字段。下面的 Pi 示例使用示例凭据和非敏感的环境变量值；请将 URL、密钥和模型替换为适合你环境的值，并合并到现有文件中，不要覆盖其他智能体：

```json
{
  "url": "https://chorus.example.com",
  "agents": [
    {
      "agentName": "pi-worker",
      "apiKey": "cho_REDACTED",
      "agentType": "pi",
      "args": ["--model", "anthropic/claude-sonnet-4-6", "--thinking", "high"],
      "env": { "PROVIDER_REGION": "us-east-1" }
    }
  ]
}
```

模型仅为示例，不是 Chorus 默认值。请使用后端支持的参数和值；没有独立的 `model` 或 `thinking` 字段。后台服务的唤醒和 `chorus agents run --name pi-worker` 都会使用这个条目。`offline` 智能体仍然不会被唤醒。

- **不继承全局设置**：存在非空 `agents` 数组时，顶层 `args` 或 `env` 会报错。请把它们移入每个需要的条目。其他智能体和你的 shell 不受影响。
- **按字面传递**：`args` 的每个元素是一个参数，不要额外加 shell 引号。`$HOME`、`${TOKEN}` 和 shell 命令不会展开。Chorus 不额外加载 dotenv、不插值、不查询密钥服务，也不对 env 值做特殊处理。`env` 覆盖子进程继承的环境，但 Chorus 管理的控制项仍优先。Windows 环境变量名不区分大小写，POSIX 区分。
- **校验**：`null`、非字符串参数或值、NUL 字符，以及不符合 `[A-Za-z_][A-Za-z0-9_]*` 的变量名会在启动前被拒绝。允许空字符串值。请填写选项，而非位置提示词或子命令。未知选项在后端支持时用 `"--future=value"`；`"--future", "value"` 存在歧义，会被拒绝。
- **受保护的控制项**：持久化参数不能更改已知的会话/恢复、提示词、传输/输出、工作目录、托管 MCP 或权限控制。帮助、版本以及其他只输出信息就退出的选项也被禁止，单独的 `--` 和标准输入标记 `-` 同样不允许。所有 `CHORUS_*` 环境变量名以及嵌套 Claude 上下文变量 `CLAUDECODE` / `CLAUDE_CODE_ENTRYPOINT` 均保留，不区分大小写；配置这些名称会报错，而不是被静默删除。请改用专用的 Chorus 设置或显式前台透传。
- **Windows 命令包装器**：通过 `.cmd`/`.bat` 启动时，配置中的空参数，以及含空白、引号或命令元字符的参数会被拒绝。需要这些值时请用原生可执行文件；通过包装器的显式前台透传不保证 shell 安全。

`env` 中可能包含明文的模型提供方凭据。请保护文件（POSIX 上用 `chmod 600 ~/.chorus/daemon.json`），切勿提交密钥。Chorus 的校验和启动消息不会显示配置值，但子程序或操作系统层面的检查仍可能暴露它们；Chorus 不提供加密或密钥库。若设置 `CODEX_HOME` 或 `PI_CODING_AGENT_DIR` 等自定义目录，也需在其中配置 Chorus 集成。

**应用更改**：运行 `chorus daemon restart`。后台服务在启动时读取这些设置，而非每次唤醒时；编辑文件既不会改变运行中的子进程，也不会影响重启前的后续唤醒。每次新的 `chorus agents run` 都会重读配置，但不影响已运行的子进程。删除 `args`/`env` 即可恢复未自定义的行为。

**旧式扁平文件**：没有非空 `agents` 数组时，顶层 `args`/`env` 用于后台服务中唯一的智能体。要在前台按名称选择智能体，必须使用 `agents[]`。若要共用设置，请将扁平的 URL、密钥、身份信息、`args` 和 `env` 移入一个条目，并将 `agent` 改名为 `agentType`。通过 `chorus agents add` 或 `chorus login --add` 添加智能体，也会将已有的扁平凭据配置及其 `args`/`env` 移入 `agents[0]`，并删除对应的顶层键。缺少密钥的不完整扁平配置需要先补全或手动转换。

一次性覆盖和子命令的具体规则见 [chorus 命令行工具](/zh/reference/cli/)。

### 添加另一个智能体

- **`chorus login --add`** 校验一个新密钥并把它追加为另一个智能体。在扁平文件上首次使用 `--add` 时，会把已有凭据迁移到 `agents[0]`，并把新密钥添加为 `agents[1]`；重复的密钥会被拒绝，已有的智能体绝不会被覆盖。
- **`chorus daemon install --add`** 会循环运行安装向导，让你在一次运行中添加多个智能体（仅限终端）。
- 始终支持**手动编辑** `~/.chorus/daemon.json`。

编辑文件后请重启后台服务（`chorus daemon restart`），然后在**设置 → 智能体**中确认每个智能体都已出现。

### 各后端如何拿到自己的密钥

每个智能体都用自己的密钥认证，但这个密钥*如何*传给被唤醒的子进程，取决于后端：

- **Claude Code**：自动。后台服务会为每次唤醒写入一份携带该智能体 URL 和密钥的 MCP 配置。无需额外配置。
- **Kiro**：自动，通过环境变量。已安装的 `mcp.json` 引用 `${CHORUS_URL}` 和 `${env:CHORUS_API_KEY}`，后台服务会在每次唤醒时导出它们，因此每个 Kiro 智能体都用自己的密钥认证。
- **Codex**：自动，通过环境变量。`chorus agents add` 会把 Codex 配置为不内置密钥：它把 `CHORUS_URL` / `CHORUS_API_KEY` / `CHORUS_AGENT_PROFILE` 写入 `~/.codex/.env`（Codex 在启动时加载它），并在 `config.toml` 中设置 `bearer_token_env_var = "CHORUS_API_KEY"`，因此 Codex 从环境变量读取密钥，而不是从配置文件中读取。后台服务会在每次唤醒时注入各智能体自己的密钥，因此一个后台服务中的多个 Codex 智能体各自以自己的身份认证。
- **Pi**：自动，通过环境变量。后台服务会在每次唤醒时把各智能体自己的 `CHORUS_URL` / `CHORUS_API_KEY` / `CHORUS_AGENT_PROFILE` 导出到被唤醒的 Pi 会话中，由 `chorus-pi` 扩展读取，因此每个 Pi 智能体都用自己的密钥认证。

## 安装 Linux 服务

在 Linux 上，可将验证过的配置安装为用户服务：

```sh
chorus daemon install --agent claude-code --cwd /home/demo/workspace --chorus-only
chorus daemon status
```

安装程序会立即启动该服务，并将其配置为在用户登录时自动启动。请先运行 `chorus agents add`（或 `chorus login`），服务才能读取已保存的凭据；也可以给 `chorus agents add` 传入 `--daemon-autostart`，在同一步中安装这个服务。

:::note[为什么凭据要存进文件]
`systemd --user` 单元在干净的启动环境中运行，**不会**继承你在 shell 中导出的 `CHORUS_URL` / `CHORUS_API_KEY`。因此 `chorus daemon install` 会在写入服务单元之前，先解析、校验凭据并将其持久化到 `~/.chorus/daemon.json`（`0600`）。服务单元既不引用文件路径，也不引用凭据，它只设置 `HOME`，让后台服务在启动时能定位到 `~/.chorus/daemon.json`。所服务的 `cwds` 和所选的 `agent` 也存在同一个文件中；只有 `--chorus-only` 会写入服务单元。
:::

### 为被唤醒的智能体提供所需凭据

后台服务自动提供 Chorus 连接（`CHORUS_URL`、`CHORUS_API_KEY` 和 `CHORUS_AGENT_PROFILE`），但不提供模型提供方凭据。若后端从环境变量读取提供方凭据，可通过该智能体的 `env` 提供，也可通过后台服务继承的环境提供。`systemd --user` 服务不会继承登录 shell 中导出的变量；如需通过服务提供，请添加 drop-in 配置后重启：

```sh
# ~/.config/systemd/user/chorus-daemon.service.d/provider-env.conf
[Service]
Environment=EXAMPLE_PROVIDER_API_KEY=…
```

```sh
systemctl --user daemon-reload && systemctl --user restart chorus-daemon
```

从文件读取提供方认证的后端（例如 Claude Code 和 Codex，位于 `~/.claude` / `~/.codex`）只需正确设置
后台服务的 `HOME`，已安装的服务单元已经做到了这一点。

日常运维使用以下命令：

```sh
chorus daemon status
chorus daemon logs
chorus daemon restart
chorus daemon stop
chorus daemon uninstall
```

更改凭据、工作目录、运行后端或权限模式后，请重新安装或重启服务，并在**设置 → 智能体**中确认连接正常。

:::note[macOS 与 Windows]
在 macOS 上，`chorus daemon install` 会像在 Linux 上一样安装真正的 launchd 开机服务。在 Windows 上，它会输出服务模板和手动配置步骤；测试连接时，请以前台运行的 `chorus daemon` 作为基准。
:::

### 退出登录后继续运行 Linux 后台服务

从 Chorus 0.21.0 起，`chorus daemon install` 会尝试为当前用户启用 **systemd lingering（用户驻留）**，让用户服务在最后一次退出登录后继续运行，并在开机后无需登录即可启动。授权尝试为非交互且有超时限制，不会等待密码对话框。

若授权被拒绝或 logind 不可用，服务安装仍可成功，但 Chorus 会警告无法保证退出登录后或开机时继续运行。运行 `chorus daemon status` 检查 `linger: yes`。若主机策略允许，请管理员执行输出中的 `sudo loginctl enable-linger <user>` 命令。

已有主机可重新运行 `chorus daemon install` 修复。`chorus agents add` 在安装服务或发现已有服务时也会检查驻留，即使未加 `--daemon-autostart` 或拒绝自动启动。两个命令都可加 `--no-linger` 跳过尝试，但不会关闭已有设置。未启用驻留时，后台服务可能在退出登录后停止，直到下次登录才启动。卸载 Chorus 服务不会关闭驻留，因为其他用户服务可能依赖它。

## 不安装服务直接运行

短期使用的连接可以让 `chorus daemon` 保持在前台运行。也可以使用分离（后台）模式：

```sh
chorus daemon -d --agent codex --cwd /home/demo/workspace --chorus-only
```

使用同样的 `status`、`logs`、`restart` 和 `stop` 命令管理它。不要把分离模式与另外编写的进程守护程序组合使用。

## 检查运行状况

同时查看命令行和网页中的状态：

1. 运行 `chorus daemon status`。
2. 用 `chorus daemon logs` 查看最近的输出。
3. 在**设置 → 智能体**中，确认每个预期的工作目录都处于**在线**状态。
4. 发起一个小型测试会话，确认它指向预期的目录。

日志可能包含路径、提示词和命令输出，分享前请删除敏感值。遇到故障时，请继续阅读[排查智能体连接故障](/zh/guides/troubleshooting/)。

## Claude 后台子智能体等待上限（0.22.0）

Claude 后台服务唤醒现在默认在**主轮次结束后等待 60 分钟**，让尚未完成的后台子智能体收尾。
这是主轮次后的等待上限，不是整次唤醒的总时限，也不是中断后的宽限时间。
交互式 Claude 会话不受影响。更新 Chorus CLI 和 Claude 插件后，重启后台服务以应用到新唤醒。

- `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`: Claude 原生值，显式设置时原样传递，优先级最高，包括 `0` 和空字符串。
- `CHORUS_CLAUDE_BG_WAIT_CEILING_MS`: 仅在原生变量不存在时使用。单位为毫秒，接受非负安全整数，去除首尾空白。
- 默认值: 原生变量不存在且 Chorus 值未设置或无效时使用 `3600000` 毫秒（60 分钟）。非空但无效的 Chorus 覆盖值会告警；空值或纯空白使用默认值。

优先级为**原生变量 → Chorus 覆盖值 → 3600000**。显式 `0` 表示无限等待，卡住的子智能体
可能让唤醒永不结束。原生变量为空时仍原样传递，不要用空字符串请求默认值：Claude 可能把它当作
未设置并恢复自身更短的上限。要使用 Chorus 设置，请彻底移除原生变量。原生值的验证与解释由 Claude 负责。

在 `~/.chorus/daemon.json` 中对应智能体的 `env` 对象里配置，例如：

```json
{
  "env": {
    "CHORUS_CLAUDE_BG_WAIT_CEILING_MS": "3600000"
  }
}
```

也可配置后台服务自身的环境。登录 shell 的 export 不会传入已运行的服务。
修改后运行 `chorus daemon restart`。如果 Chorus 覆盖值没有生效，先检查是否继承了原生变量。

主智能体必须收齐后台子智能体的完成结果，或明确停止它们后再结束轮次；扩大上限不能替代此责任。
若 Claude 输出 `Background tasks still running after …s; terminating.`，即使原始退出码为零，
Chorus 也记录异常唤醒，并尝试在触发的想法或任务上发布说明。显式中断或关闭仍按中断处理，而不是崩溃。
不会自动修复任务状态，也不新增自动重试。恢复前检查部分完成的工作；评论发布失败时，唤醒诊断仍保留错误。

**不要混淆后端时限**：`CHORUS_DSH_TIMEOUT_MS` 限制的是**整次 dsh 唤醒**，默认
`1800000` 毫秒（30 分钟），仅接受正安全整数；`0` 或无效值回退默认值，不表示无限等待。
Claude 的主轮次后等待设置不适用于 Codex、Pi、Kiro 或 Hermes，不能据此推断其他运行环境的后台子智能体生命周期。
