22/Documentation
管理与更新
从手机或终端更新、回滚、更新 crew、跨大版本升级、停止、卸载,以及将 0.x 安装升级至 1.0
| 你的安装方式为 | 你使用的是 | 指令写法为 |
|---|---|---|
herdr plugin install 或 herdr plugin link | Herdr 托管(herdr plugin list 显示 herdr.collie) | herdr plugin action invoke <verb> --plugin herdr.collie |
| 安装脚本或源码构建 | 独立安装 | 从安装目录运行 bin/collie <verb> |
Herdr 安装方式不会在 PATH 中添加 collie;请使用 Herdr 操作 ID(Herdr 操作)。独立安装会将二进制文件置于 ~/.local/share/collie/current/bin/collie 或 <checkout>/bin/collie 中:
# the install script's layout
cd ~/.local/share/collie/current && bin/collie version
# a source build or a linked clone
cd ~/my/collie-checkout && bin/collie version运行 bin/collie link 将二进制文件符号链接至 ~/.local/bin(将 collie 添加到 PATH)。
配置和状态位于检出目录之外,并在更新后继续保留(bridge/solo-baseline.test.ts)。.env 和 tailscale serve 记录位于配置目录中,在二进制安装中为 ~/.config/collie,在 Herdr 安装中为 Herdr 的插件配置目录;配对设备和 stt.json 位于状态目录中,即 ~/.local/state/collie,除非 COLLIE_STATE_DIR 移动了它。
通过包管理器安装的实例
如果 Collie 由包管理器安装,则更新操作也由包管理器负责,本节以下内容均不适用:
sudo pacman -Syu collie-bin # or `nix profile upgrade collie`, or `brew upgrade collie`Collie 会通过磁盘特征识别此类安装:无 .git、无 versions/ 结构、包含 release 产物附带的 manifest,且根目录处于只读状态、位于用户 home 目录之外或归 root 所有。满足最后三项中的任意一项即可触发识别。随后它会拒绝就地更新;在能够识别出具体包管理器时,还会提示对应的管理命令:
error: /opt/collie is a packaged install — updates come from your package manager.
`collie update` will not replace its files.
Take the new version with: sudo pacman -Syu collie-bin如果前缀路径未对应 Collie 已知的包管理器,它会输出前两行内容并停止,不会随意猜测你无法执行的命令。
collie doctor 将同一个安装报告为正常,且手机上的更新卡片仍然显示存在更新的版本,原本的更新按钮处变为了软件包命令。
注意。 这不是一个需要绕过的限制。该文件夹属于你的包管理器,背着包管理器替换其中的文件会导致其数据库记录的安装信息与实际不符。sudo collie update 也会以相同的方式拒绝执行。要获取新版本,请先运行你的包管理器,然后重启服务:
paru -Syu collie-bin # Arch, or your AUR helper of choice
nix profile upgrade collie # Nix
mise upgrade --bump github:AltanS/collie # mise
collie restartmise 安装属于特例:Collie 不会将其识别为打包安装,因为目录树位于你的主目录中,没有 .git 也没有 versions/ 布局,因此 collie update 会带着 cannot tell how this Collie was installed 拒绝执行且不指定管理器。mise 仍然拥有其控制权。参见 安装。
重启是 Collie 无法为你执行的部分,且不可省略。你的包管理器会在运行中的 bridge 下替换文件,因此该进程在已经报告新版本的同时仍在执行旧代码。Collie 会检测到这种不匹配并作出提示:collie doctor 会引发 restart-pending,手机端会显示“需要重启 Bridge”的横幅,内容为“Collie 在磁盘上已被替换。请重启。”一旦 collie restart 运行完毕,这两处提示都会立刻消失。
在 crew 中,通过包管理器安装的 member 绝不接收来自手机的更新。crew 将其列为"waits for the package manager",并在没有它的情况下将本次运行计为完成,因此上述两条命令用于将其拉平版本。
打包安装的 lead 仅拒绝其自身的迁移。手机仍会将所有成员节点同步到主控节点运行的版本,一次确认即可覆盖它们。在上述两条命令迁移主控节点后,没有任何组件会自动同步:再次点击“更新”页面,各成员节点就会跟随升级到主控节点的新版本。
更新,从手机或终端
存在两条更新路径,两者在每台主机上运行相同的步骤:在当前版本旁暂存新版本、切换 symlink、重启,并检查服务是否响应。在 crew lead 上,两条路径都覆盖整个 crew。手机是简捷路径。终端是手机无法拉平版本的机器的备用途径。
从手机更新
打开 设置 并选择 更新。卡片会显示当前运行版本、最新版本以及更新中包含的中间版本。如果主机已处于最新版本,卡片会提示该状态且不提供任何操作。


其下方是预检项,每项检查占一行:doctor、disk、bun、tree、upstream 和 service。在 lead 上,每个 crew member 也会被检查。
- Green 表示正常。
- Amber 值得了解且绝不阻塞:整个 crew 中的版本偏差、不常见的安装类型、已发布但未采用的主版本。检出目录中未跟踪的临时文件保持为绿色。
- Red 会阻塞更新。该行会指明原因,例如
collie doctor为 red、暂存构建的可用空间不足 1 GB、主机上缺少bun,或无法连接上游。若某条命令可解决该问题,卡片会将其显示为Fix: <command>。
点击 Update to <version> 会提示确认一次,确认文本含义明确:终端会话保持活跃,手机视图最多中断 30 秒。重启只会关闭 bridge,不会关闭复用器,因此 agent 保持运行,手机端重新连接后即为新版本。日常更新绝不会自动跨大版本:跨大版本升级需要单独确认,明确标出新大版本号,并提示先阅读发布说明。
运行时,浮层会占满屏幕。请参见下方的更新运行时手机显示的内容。“更新”页面上的卡片包含相同的状态,细节更详尽:
| State | 含义 |
|---|---|
preflight | 正在检查本机。未做任何更改。 |
staging | 正在旧版本旁构建或下载新版本。 |
restarting | 桥接连接已主动断开。这不是故障停机。 |
verifying | 正在等待新版本响应。 |
done | 新版本已响应。 |
rolled-back | 新版本未响应,更新程序已恢复旧版本。 |
stuck | 两个版本均未响应。系统不会再次自动重启。 |
interrupted | 运行在完成前停止。没有残留的半安装状态。 |
前四项代表进度;卡片会显示该信息并提示保持屏幕开启。rolled-back 显示当前仍处于的版本、服务日志末尾内容并提供 重试。stuck 会输出需要在终端中执行的那条命令。interrupted 也会提供 重试。
在下次摘要中提醒我 会忽略卡片的提示。这不是静音:下一次推送既要等待更新的发布版本,也要等待新的时间窗口。
通知频率。 更新推送采用摘要形式,每天最多一次,且绝不早于宿主机当地时间 09:00。仅包含补丁版本的增量更新会等待每周窗口推送,因此一连串补丁版本会合并为一次推送发出,而不是分成四次;次要版本或主要版本则保持每日推送节奏,并顺带包含等待中的补丁。积压的版本会被合并,绝不遗漏。补丁也可以请求每日推送节奏:若某个修复必须在今天应用,会在发布时被标记为紧急,更新卡片随后会显示 紧急 标签并附带一句说明原因的文字。你会在发布时收到通知,或在发布后的下一个 09:00 收到通知。只要包含一个紧急版本,整个等待中的发布队列就会转为每日节奏,而版本本身仍是普通的补丁版本。早于该功能安装的版本在完成一次更新之前,针对紧急补丁仍会保持每周窗口。无论处于哪个窗口,卡片始终显示当前状态。Settings → notifications(Web Push)下的 updates 通知偏好是唯一的总开关。
在 crew lead 上,按钮显示 将 crew 更新至 <version>,一次确认适用于每台机器。lead 先更新,受其自身的健康门禁约束。然后每个 peer 逐一将自身拉平到相同版本,使用各自的预检、各自的健康门禁和各自的回滚。没有针对单个 peer 的按钮,也没有第二次确认提示。有关详情、两条恢复路径以及手机无法修复的一种情况,请参阅 更新 crew 中的其余机器。

每个屏幕顶部的横条显示静态信息,而非运行中的操作:当前提供的版本、未能更新的 peer,以及手中应用落后于 bridge 时的New version — tap to update。正在运行的更新属于浮层,不属于横条。

更新运行时手机显示的内容
点击确认的设备上会弹出一个浮层占满屏幕,其他所有设备则会显示角标。
浮层中每台机器占一行,lead 排在最前,各行显示机器的版本和当前状态。这些行下方是此设备自身的行,对应你手中的应用而非某台机器:一旦 bridge 开始提供新版本,手机就会在后台拉取该应用,该行会随文件到达实时计数。浮层还会以小字说明一次:更新在机器上运行,关闭应用不会停止更新。
发起运行的设备无法使用浮层背后的应用。其他一切均未受阻:第二部手机或平板电脑会显示一行内容,点击即可打开,随后再次关闭。
当所有机器均已完成且手机运行新应用时,浮层会自动关闭,并显示一条包含版本号的简短消息。在 crew 上显示为Crew updated to <version>;在单台机器上则会改用该机器的名称。
仅更新 member 的运行任务(例如 Retry crew update)同样会占用屏幕。lead 所在的行显示为 already up to date,因为 lead 不属于该运行任务,也不会重启。结束时显示为 Members updated to <version>,无法更新的 member 会在发起该任务的手机上保持工作表开启,并显示具体原因。
有三种状态可能会卡住,每种状态都有应对方法。它们都不会取消更新,也不会重新加载应用。
| 显示内容 | 含义 | 应对方法 |
|---|---|---|
某台机器上出现 last seen <time> ago | 该机器已停止响应 lead。 | 查看“更新”查看原因,或保持现状。 |
| 仍在下载。请继续使用当前应用… | 手机自身的下载已有两分钟没有任何进展。 | 继续使用应用。 下载继续进行。 |
| 仍在运行。目前一切正常… | 该运行任务已在一种状态下停留了三分钟。 | 请继续等待。 运行继续进行。 |
注意。 “仍在下载,请继续使用应用”指的是手机上的应用,与机器无关。各机器已完成处理;只是新应用尚未送达。你正在使用的应用仍可正常工作,下载完成后会自动切换。
从终端执行
collie update --check # read-only preflight, --json for a script
collie update --check --local # the same, this instance only, no crew members
collie update # stage, flip, restart, verify
collie update --status # what the updater did, or is doing, --json for a script
collie update --rollback # put the previous version back
collie update --major # cross one major, see belowcollie update --help 会输出用法说明且不启动任何内容。每个 collie 命令在执行任何工作之前,都会以相同的方式响应 -h 和 --help。
在由 Herdr 管理的安装中,相同的动词对应 Herdr 操作:
herdr plugin action invoke update --plugin herdr.collie # Herdr-managed
bin/collie update # Standalonecollie update --check 不会更改任何内容。它运行 collie doctor,读取空闲空间、bun 版本、工作区、上游发布列表以及 service unit,并在 lead 上通过你自己的 SSH 向每个 crew 成员询问相同的信息。除非存在异常项,否则退出代码为 0,并且 --json 会输出带有版本的报告。添加 --local 可以仅检查此实例并跳过 crew 成员。手机在自己的主机上运行该本地检查,并通过 crew link 读取每个对等节点的行,因此其 preflight 不需要 SSH。
collie update 会获取当前主版本的最新发布并暂存。随后该命令将切换操作移交给独立的更新程序并退出,因为重启会终止请求更新的桥接连接。该更新程序将 current 指向新版本,通过新二进制文件重启,并轮询 GET /api/health 最多 30 秒,等待包含刚安装版本号的响应。如果未收到响应或响应来自旧版本,它会将 current 切换回原状并再次重启,同时记录包含服务日志末尾内容的 rolled-back。如果旧版本也无法启动,它会记录包含手动执行命令的 stuck,此后不再尝试重启。回滚仅执行一次,绝不执行第二次。
如果你的机器上 30 秒不够用,请设置 COLLIE_UPDATE_HEALTH_TIMEOUT_MS。超出时间预算的缓慢冷启动会被判定为更新失败并触发回滚。
collie update --status 会输出更新程序保存的记录,手机端读取的也是同一份记录。当主端口关闭时,deputy 的备用端口会在 /standby/update 上提供该记录。
如果有新的 beacon hook 事件可用,update 会输出提示以重新运行 hooks install claude。
每次成功更新、回滚或切换后,新构建会运行 collie skill sync。它会将 walky talky 技能安装到这台机器上的每个 agent harness 中,并更新落后的副本,以便你的 agent 能够识别你当前运行的构建。它会为每个更改的文件输出一行信息,且绝不会导致更新失败:如果无法运行,update 会输出一条提示,你可以手动运行 collie skill sync。它会跳过你运行过 collie skill uninstall 的 harness。设置 COLLIE_SKILL_SYNC=off 可保留你的指令文件原样;此时更新只会在技能落后时输出一条提示(安装 skill)。
版本存放位置
二进制安装与链接克隆在安装根目录下共享同一种布局(二进制安装为 ~/.local/share/collie 或 $COLLIE_DIR,源码检出则为克隆目录本身):
current -> versions/v1.3.0
versions/v1.3.0/
versions/v1.2.0/在源码检出中,每个 versions/vX.Y.Z 都是发布标签的 git worktree,共享同一个 .git,因此一个版本仅占用一个 worktree 的开销,而不需要第二个对象库。构建在新建的目录中运行,并在最后写入完成标记;若没有该标记,切换操作会直接拒绝,因此被中断的构建不会影响正在运行的版本。上线操作仅是对 current 符号链接的一次重命名。保留策略会保留 current 以及最新的两个历史版本,且只有成功的运行才会触发清理,因此可能需要回滚目标的运行绝不会删除该目标。
Herdr 托管 检出是特例,它会原地向前推进(ADR 0006,2026-09-03 修订)。它处于分离头指针状态且为浅克隆,存放在 Herdr 所有的目录中,因此旁边没有 versions/ 布局,无需移交,也无法切换回滚。该模式下会拒绝 --rollback;恢复路径是重新安装指定的标签(herdr plugin install AltanS/collie --ref vX.Y.Z --yes)。
从 1.8.0 回滚到 1.7.0 需要在状态目录中手动编辑两次。 1.8.0 在首次启动时会重命名这三个状态文件,因此 ~/.local/state/collie/ 现在包含 crew-trust.json、crew-ops.json 和 crew-runtime.json,而 1.7.0 构建版本只读取旧名称。在启动 1.7.0 构建版本之前,将这三个文件全部改回原名:
cd ~/.local/state/collie
mv crew-trust.json pack-trust.json
mv crew-ops.json pack-ops.json
mv crew-runtime.json pack-runtime.json然后在 pack-trust.json 中编辑两个键名。1.8.0 两种拼写均可读取 crew 块,并将其写回为 "crew"(内部包含 "crewId"),而 1.7.0 写入的是 "pack" 和 "packId"。1.7.0 构建版本仅读取自己的拼写,因此一旦 1.8.0 写入了该存储(在任何加入、轮换、warrant 刷新或移除时都会写入),请将该块改回 "pack",将其 id 字段改回 "packId"。这三个文件中的其他内容均未更改,crew-ops.json 和 crew-runtime.json 完全不需要编辑。如果你不想修改文件,可以恢复更新前备份的 pack-trust.json 副本,或者保留在 1.8.0:无法读取信任存储的 1.7.0 构建版本会以单机模式启动,且不强制执行花名册规则。
反向操作进入 1.9.0 也需要手动进行相同的两处修改。 1.8.x 在首次启动时已为你重命名这三个文件;1.9.0 则不会重命名任何文件。因此,从未运行过 1.8.x 的状态目录仍保留 1.7.0 的名称,而 1.9.0 构建版本只读取 crew 名称。它会在启动时提示该信息,列出这两处修改,并保持 solo 状态而不是直接接管该目录。启动前请先完成修改:
cd ~/.local/state/collie
mv pack-trust.json crew-trust.json
mv pack-ops.json crew-ops.json
mv pack-runtime.json crew-runtime.json然后在 crew-trust.json 中重命名两个键名:块 "pack" 改为 "crew",其内部的所有 "packId" 改为 "crewId"。这三个文件中的其他内容均不改动。保留旧名称的文件不会丢失数据,只会影响 crew:在完成重命名之前,该 collie 会以 solo 模式启动。
验证
bin/collie update --status
herdr plugin action invoke version --plugin herdr.collie
bin/collie version预期应为最新标签。
手机端自带的 Bundle 是独立的部分。PWA 会自行检查新构建并在约一分钟内重新加载,在更新运行期间它会推迟该重新加载。如果你正在进行任务,它会显示“点击以更新”横幅并等待你点击。
在 Windows 上
对于源码检出版本,在 Windows 上,源码检出版本从不自行更新;zip 安装版本则会自行更新。 collie update 和手机端的 Update 按钮会用一句话明确提示且不作任何更改。改用 zip 安装是一次性手动步骤:
collie uninstall
powershell -ExecutionPolicy Bypass -File .\install.ps1完成此操作后,collie update 即可在终端和手机上正常使用。该调用链在 Windows 11 虚拟机中针对发布文件的本地副本进行过演练,但移动操作本身并未演练。v1.15.0 及更早版本也无法热替换运行中的 collie.exe。请参阅 Windows 上的 Collie。
如果版本未变动
collie update 每次运行都会直接查询 GitHub:源码检出查询 git ls-remote,二进制安装则查询 GitHub tags API。它不会缓存发布列表。几秒前发布的版本可能仍需要一分钟才会显示,因为 GitHub 本身需要时间同步。接下来运行 collie doctor。如果仍无法解释,请查看 当 collie 无法运行时。
如果 GitHub 限制 release 检查的速率
二进制安装上的 collie update 会通过 GitHub 的 API 列出 release,手机端的更新横幅和 install.sh 也是如此。GitHub 允许匿名调用者每小时进行 60 次 API 调用,按网络地址计算,因此处于同一个路由器后的所有机器共享该额度。额度耗尽时,检查会按失败处理且不做任何更改:
error: GitHub rate-limited the release check (HTTP 403). Wait an hour, or set GH_TOKEN
to a GitHub token with no scopes, so the limit is yours (docs/upgrading.md).
Nothing was changed.使用 token 可以让你独享速率限制。Collie 会从环境中读取 token,绝不会主动索取:
| 名称 | 设置方 |
|---|---|
COLLIE_GITHUB_TOKEN | 你,针对该服务:实例的 .env,或者 config.toml 中 [update] 下的 github_token |
GH_TOKEN | gh CLI 自带的名称 |
GITHUB_TOKEN | GitHub Actions |
以最先设置的为准。标签列表是公开的,因此 token 仅需 完全无需任何权限:一个将仓库访问权限设为 Public repositories (read-only) 且不勾选任何权限的 fine-grained 个人访问 token,或者不勾选任何 scope 的 classic token。切勿使用具有任何写权限的 token。
若要在终端中运行一次,可以借用 gh CLI 的凭据。该值绝不会出现在命令行或 shell 历史记录中:
GH_TOKEN=$(gh auth token) collie update对于服务,请将其放入实例 .env(Collie 将其权限保持为 600),或放入 [update] 下的 config.toml 中,然后重启:bridge 在启动时读取 token,因此手机端的横幅只有在 collie restart 之后才会使用新设置或修改后的 token。collie config 会将其显示为 set 或 unset,绝不会打印具体值。该 token 仅发送至 api.github.com:版本发布文件的下载来自 github.com,该地址没有此类限制,且绝不会携带该 token。提及该 token 的消息只会指出其来源变量名,绝不输出具体值。被 GitHub 拒绝的 token 会在检查失败时返回 HTTP 401 并附带该变量名,因此错误的 token 不会被误判为触发速率限制。bridge 会在其日志中记录一次相同内容,随后保留它看到的最后一个版本;因此如果 token 过期后横幅不再更新,原因就在该日志行中;随时运行 collie update --check 均可查看其名称。
collie update --check 在 upstream 下报告相同的这三种情况。git 检出副本则会使用 git ls-remote 列出标签,这不受 API 速率限制的约束。在 crew 中,每台机器读取各自的 token:成员通过运行自己的 collie update,从其自身的 .env 进行更新。
跨主版本升级
update 绝不会自动跨主版本升级。
herdr plugin action invoke update-major --plugin herdr.collie # Herdr-managed
bin/collie update --major # Standalone这会将版本推进一个主版本至其最新的严格发布版。它不会以预发布版本为目标(ADR 0020)。另请参阅:从 0.x 升级至 1.0。
如果升级失败并提示 "You are not currently on a branch"
在 0.23.1 之前从 GitHub 安装的版本缺少分支跟踪引用(#63)。重新安装以恢复更新功能:
# replaces the checkout, rebuilds the UI
herdr plugin install AltanS/collie --yes
# reinstall doesn't restart the service
herdr plugin action invoke restart --plugin herdr.collie
# expect 0.23.1 or newer
herdr plugin action invoke version --plugin herdr.collie你在 Herdr 插件配置目录中的配置(按惯例为 ~/.config/herdr/plugins/config/herdr.collie)会被保留。
更新 crew 中的其余机器
collie crew update <member>… # on the lead
collie crew update --all那是终端路径,适用于手机无法更新的 peer。通过手机,只需一次点击和一次确认即可更新整个团队:在 lead 上打开 Settings → System → Updates 并选择 将 crew 更新至 <version>。按钮上方的预检涵盖所有成员,而不仅是 lead。如果任何一处检查变红,该按钮将被禁用,并显示发生故障的机器及其原因。
lead 先更新,受其自身的健康门禁约束。只有在其稳定后,第一个 peer 才会启动。从 1.7.0 开始,该顺序对文字表述也很重要:低于 1.7.0 版本的 lead 通过 member 输出的第一行读取其状态,而 1.7.0 版本的 member 输出 crew …(1.6.0 版本输出 pack …),因此未更新的 lead 无法识别。1.7.0 版本的 lead 能识别两者。然后每个 peer 拉平 自身:它读取其 lead 正在运行的版本,从 GitHub 获取该完全相同的 tag,并运行各自的预检、各自的健康门禁和各自的回滚。peer 逐一推进。Updates 页面为每个 member 保留一行:waiting、checking、staging、restarting、verifying、updated、rolled back 或 unreachable。
成员自身每小时最多更新一次。如果在该小时内已更新过(例如手动更新),该成员行下方会显示 rate-limited, retries in about N min 并等待,该时间过去后运行继续。如果 lead 自身的更新发生回滚,则不会改动成员,其对应行会说明这一点。新的更新会等待 crew 运行结束,最多等待 2 小时。
1.7.0 到 1.8.0。 同样先升级 lead,原因有二:1.8.0 将通信路径、两个环境变量键名、三个状态文件以及日志前缀重命名为 crew。1.8.0 的 lead 会在一个版本周期内兼容旧的 /pack/v1/* 路径,因此仍处于 1.7.0 的 member 可以通过现有连接完成同步。这两个旧名称将在 1.9.0 中彻底移除。具体名称及其在本机上的作用见 从 1.7.0 或 1.8.x 升级到 1.9.0。在将 lead 升级到 1.9.0 之前,请确保所有 member 都已升至 1.8.x:1.9.0 不再响应旧路径,届时仍处于 1.7.0 的 member 会在 lead 的预检中显示为红斑,并标明两个版本以及该机器上需运行的命令。该版本发布的 collie-release.json 资产决定了通知栏、Updates 卡片以及每日推送中的提示文案,它绝不会改变更新本身的执行逻辑。它还会向检查机制表明某个版本已经发布:资产仍返回 404 的 tag 不会被推送,下一次检查会再次重试。
两项要求决定了 peer 是否能够跟进:
- peer 需要至
github.com的出站 HTTPS 访问权限。 这就是其代码来源。如果没有该访问权限,该 peer 会被报告为落后,并且需要使用上述命令在终端中进行更新。 -dev+构建版本从不跟进。 运行开发构建版本的机器将保持在该版本,无论其 lead 运行什么版本。
回滚的 peer 会在 Updates 页面上显示该状态,并且不会自行重试。两条路径可供其再次尝试:

- 从手机。 一旦 lead 为最新而某个 peer 落后,按钮会显示为 Retry crew update。它会启动一次仅包含 peer 的新运行过程,正是该新运行过程赋予了每个 peer 再试一次的机会。
- 从终端,在 lead 上。 适用于手机完全无法同步的 peer。命令保持不变:
collie crew update <member>… # on the lead
collie crew update --all在 lead 上运行它是一个通过你自己的 SSH 执行的单一序列。它会首先预检每台机器,并将每个 peer 自己的报告与通过 SSH 获取的响应并排打印,从而让差异直接显现,而不是被平均化。它会请求一次确认。如果 lead 尚未运行它正在分发的构建版本,它会接着更新 lead 本身。随后它会依次处理各个 peer:peer 会收到以 git bundle 形式推送的 lead commit,随后重新构建、重启,并在相同的 30 秒预算内持续轮询,直到它响应新构建。对于没有 git 检出副本的 lead(来自独立安装或软件包),由于没有可推送的 commit,它会改为通过相同的 ssh 在每个 peer 上安装其自身运行的版本,并固定到该标签;此时运行自 git 检出副本的 peer 将被跳过,并在其所在行标明 collie update --to-tag v<version>。
第一次失败就会停止运行。其后的每个 member 都保持原样并报告为"not attempted",摘要会指出清除该失败所需的一条命令。无法完成自身更新的 lead 完全不会触碰任何 peer。在此停止是安全的,因为 crew 容忍版本偏差(CREW_PROTOCOL.md §7.1),因此半更新的 crew 是受支持的状态,而强行推进则不受支持。
手机无法修复的一种情况。 如果在各 peer 完成同步后,你通过 git 或手动复制文件对 lead 执行回滚,peer 的版本将高于 lead。Collie 无法感知此类回滚,因此没有 member 会降级。通过手机端的 回滚 或使用 collie update --rollback 执行回滚,以及切回 Stable,均会触发 member 降级。参见 发布线 下的「The crew follows the lead」。只有这两种操作会使 member 降至更低版本,因为如果 lead 能随意让 peer 回滚,就能将其置于任意版本。手动回滚引起的版本偏差并无大碍,在 lead 上执行 collie crew update <member> 即可修复。
代码通过你的 SSH 传输到 peer,绝不通过 crew 链路传输(ADR 0016,2026-09-04 补充说明)。当 peer 自行升级时,其代码通过匿名 HTTPS 来自 GitHub,并且由 peer 自行决定。lead 仅声明其运行的版本以及哪个 peer 可以继续。
如果更新器本身崩溃
当更新器消失时,上述内容都无法提供帮助。这是仅假设存在终端的处理路径。
更新器写入一条记录 <state dir>/update.json(默认为 ~/.local/state/collie/update.json,或位于 $COLLIE_STATE_DIR 下)。请先阅读它:它标明了状态、本次运行来源的版本、目标版本、更新器的 pid,并在失败时包含服务日志的尾部以及恢复命令。
由手机发起的更新完全不会输出到终端。在带有 systemd 用户管理器的 Linux 上,它在名为 collie-api-update-<stamp> 的独立临时 unit 下运行,且 --collect 在其退出时立即移除该 unit,因此其记录仅保存在 journal 中:
journalctl --user -u 'collie-api-update-*' --since '30 min ago'在其他所有环境下(包括 macOS),更新程序自身的输出会写入状态目录中的一个文件:
cat ~/.local/state/collie/update-runner.log手机发起的每次更新都会清空该文件,并将上一次运行记录保留为 update-runner.log.1。在 systemd 层级,该文件仅包含 systemd-run 输出的一行内容,其余部分见上述 journal。
在 crew 更新后,某个 crew 成员可能仍停留在旧版本。此时其检出目录显示新标签,但 /standby/health 或页脚仍显示旧构建。使用 systemctl --user list-units 'collie-api-update-*' 检查是否有更新程序正在运行。如果没有,请在该机器上运行 collie update。它会重新构建未完成构建的检出目录。
在切换前中止的运行(例如无法在此机器上启动的新版本)不会更改磁盘上的任何内容。发起更新的手机会提示该机器更新失败并给出原因,该原因同样记录在 update.json 的 reason 字段中。
当手机报告成功但下游未执行某些操作时,应排查该处。例如运行记录无法写入的警告,这表示 lead 自行更新了版本,但不会升级其 crew。bridge 自身的 journal 记录了另一半内容:每次运行一条 [crew] update <run id>: levelling peers to <version> 行,在 lead 提取该记录时生成。在 1.8.0 之前,该前缀为 [pack]。若没有此类行,则表示各轮次从未启动。
1.5.4 之前的版本在更新时卡在 bunx
在 1.5.4 版本之前,从手机发起的更新会在缺少你的 PATH 的临时 systemd 用户单元中运行。当检出安装(checkout install)中的 Bun 仅存在于 ~/.bun/bin 时,检出会推进,但重新构建会因 bunx: command not found 而失败。要解决此问题,请在 PATH 中包含 Bun 的终端中运行一次 collie update,或者运行 Herdr 操作(其 shim 会自行定位 Bun)。两种方法都可以重新构建已推进的检出代码。从 1.5.4 开始,更新程序会自动查找 Bun。
它旁边是 <state dir>/update.lock,保存着 pid 和时间戳。一次只允许一个运行。如果一条记录仍显示为 preflight、staging、restarting 或 verifying,且 10 分钟内未发生变化,并且其 pid 已不在进程表中,则说明该运行已结束:它被视作 interrupted,新的运行可以获取该锁。
要手动恢复上一版本,将 current 指向它并重启:
cd ~/.local/share/collie # or $COLLIE_DIR, or the checkout root
ls versions/
ln -sfn versions/<previous> current
collie restart或者让上一版本为你执行相同的操作,这就是 stuck 记录所携带的命令:
~/.local/share/collie/versions/<previous>/bin/collie update --rollback使用完整路径,而不是 collie:PATH 上的名称会通过 current 解析,而 current 正是可能出错的地方。
健康检查门禁无法捕获的情况
门禁仅证明一件事:服务已恢复并以已安装的版本响应了 /api/health。这是一个有边界的保证,而不是“绝变砖”。在门禁报告成功的同时,可能有四种情况发生损坏:
- 手机上的 web bundle 过期。 主机已处于新版本,而手机仍从其 service worker 运行旧的 JavaScript。PWA 会按自己的计划替换其 bundle;健康检查门禁无法感知它。
- 配置或 schema 迁移。 Collie 不会以此节奏发布此类迁移,更新器也不会运行任何迁移。门禁仅检查服务是否响应,而不检查其数据格式是否正确。
- 仅在交互时崩溃的 mux 驱动。 bridge 启动并响应健康检查,但 adapter 在第一次实际 attach 或 send 时失败。健康检查是一个存活性探测,而不是一致性测试运行。
- 运行旧版本代码的更新器。 分离的更新器是从正在被替换的版本中启动的。它保持小巧且稳定,并且其记录带版本控制,因此旧更新器和新 bridge 仍然可以互相理解,但这是一项缓解措施,而不是绝对保证。
在脚本中解析最新版本
查询 git 标签并按 semver 排序。避免使用 GET /repos/AltanS/collie/releases/latest,它会排除预发布版本。
# newest stable release
git ls-remote --tags --refs https://github.com/AltanS/collie | \
sed 's#.*refs/tags/##' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1发布线
每台机器属于两条发布线之一。默认是 Stable。
- Stable 仅接收正式版本,例如
1.23.0。 - Edge 也会接收 Edge 构建,例如
1.23.0-edge.2。Edge 构建是 GitHub pre-release,在正式发布前几天从同一代码树切出。它会先推送给志愿者,以便在波及所有人之前发现回归问题。
在手机上设置发布线:Settings → Updates → Release line。切换操作本身不安装任何内容。它会保存发布线配置并显示收据。随后 Updates 卡片会通过常规更新界面提供新发布线的内容。
- 在 Edge 上,提供的是高于当前运行版本的最新构建,包括同一大版本内的 Edge 构建和正式版本。在两条发布线上,正式版本都会替代其对应的 Edge 构建。
- 机器回滚过的构建绝不会在任何一条发布线上再次被推送。
- 在 Edge 上,新构建的推送会在下一次检查时发出,而不是等到下一次摘要。推送仍会等待至本地时间 09:00。Stable 则保留摘要时间窗口。
Edge 的发布节奏。 Edge 构建预计最多每天一次,每次都会带来可见的变更。Bridge 每六小时检查一次新构建。每个构建推送一次,且绝不早于宿主机本地时间 09:00。当单次检查发现多个新构建时,会合并为一条推送。更新提示条对每个构建仅提示一次,你可以跳过某个构建:下一次更新将采用最新构建。忽略提示条仅对该版本有效,下一个构建会再次提示。
切回 Stable。 在运行 Edge 构建的机器上切换至 Stable,页面会显示以下三种情况之一:
- 已有不低于你当前构建的正式版本发布。Updates 卡片会将其作为常规更新提供。
- 你的 Edge 构建领先于所有正式版本。页面提供两个选项:- 立即返回 在确认后安装低于你当前构建的最新正式版本。若本机保留了该 Stable 构建,则直接使用;若没有,则进行下载。如果你当前构建中的某个状态文件无法被该版本读取,页面会在按钮前列出该文件。- 等待 Stable 保留当前构建。系统不再推送 Edge 构建,下一个正式版本将在发布当天提供。
- 你已经在运行正式版本。无需执行任何操作。
保留的构建。 当机器处于 Edge 时,它会保留当前运行构建、上一个构建以及最新的 Stable 构建。最新的 Stable 构建在机器切回 Stable 之前不会被清理,因此「立即返回」仅是切换操作,无需重新下载。
回滚。 从 Edge 构建回滚会将机器置于 Stable,并将该构建标记为已回滚。在手机上使用 回滚 以及使用 collie update --rollback 均是如此。未能通过自身健康检查的 Edge 构建会被更新器自动回滚并作相同标记,之后不再提供该构建。发布线仍保持为 Edge,后续 Edge 构建将照常提供。
crew 跟随 lead。 lead 所在的发布线即为 crew 的发布线。当 lead 处于 Edge 时,member 会跟随 lead 升级到 Edge 构建,并将 lead 的发布线作为自己的发布线。member 仅在 lead 回滚或切回 Stable 时才会降级。只有这两种情况会导致 member 安装更低版本。Crew 页面显示了 member 所跟随的发布线。
在终端中运行。 发布线在手机上设置。有两个仅针对单次运行生效的 flag:
collie update --line edge # resolve this one run on Edge; the saved line stays
collie update --to-tag v1.22.6 --downgrade # go down to a lower final release--to-tag 在没有 --downgrade 的情况下绝不会获取更低的 tag。它仅在处于 Edge 分支的机器上获取更高的 Edge tag。在由 Herdr 管理的安装中,两个分支以及回退流程都走相同的就地更新:更新程序检出 tag,并自行将 Edge 后缀写入版本文件。
预发布版本
Stable 安装不会接收预发布版本。Edge 构建版本除外,属于 Edge 分支(见 发布线)。选择使用预发布版本会持续跟踪该主版本的各个预发布版本,直到最终发布版到达(ADR 0020):
# Standalone — the install script's opt-in flag takes the newest prerelease
curl -fsSL https://colliepwa.dev/install.sh | sh -s -- --beta
# Herdr-managed — install the tag; that is the whole opt-in
herdr plugin install AltanS/collie --ref <tag> --yes
# a reinstall does not restart the service
herdr plugin action invoke restart --plugin herdr.collie使用 在脚本中解析最新版本 解析 <tag>。
要返回稳定版本:
herdr plugin install AltanS/collie --yes
herdr plugin action invoke restart --plugin herdr.collie升级至 1.24.0
版本 1.24.0 添加了用量圆点、Stop 按钮和大屏布局。如果你是从 1.23.4 升级,升级当天无需做任何操作。你会注意到的变化:
- Collie 不会修改你的 statusLine。 启用自动换行需要通过
collie hooks install claude --statusline手动选择。如果你从 Edge 构建版本获得了换行配置并想移除它,请运行collie hooks uninstall claude,然后运行collie hooks install claude(Collie 将 hook 写入 Claude 自身的设置中)。 - 上下文圆点无需新 hook。 1.23.4 安装的 hook 已经包含
SessionStart,并且它们运行相同的命令。新的 Collie 通过它们读取会话文件。如果你从未运行过collie hooks install claude,请运行一次。已经在运行的 Claude 会话在重新启动、恢复、清空或压缩之前不会显示圆点,因为窗口大小是在会话启动时确定的。 - 5 小时和 7 天圆点读取你自己的登录凭据。 对于 Claude,Collie 会读取本机的登录文件并询问
api.anthropic.com。对于 Codex,它会读取 Codex 的会话文件且不询问任何服务。两者默认均开启。在.env中设置COLLIE_ACCOUNT_WINDOWS=0,或在[bridge]下设置account_windows = false即可将其关闭。OpenCode Go 和 Grok 会保持关闭状态,直到你明确指定它们(用量窗口)。 - 宽屏会显示侧边栏。 当宽度达到 600px 且高度达到 480px 时,窗格屏幕会并排显示多个窗格。若要在单台设备上保持手机布局,请在 Settings 中将 大屏布局 设置为 Off。
升级到 1.19.0
1.19.0 版本将启动操作整合到一个页面,并允许每台手机自行定制 Keys 和启动器。升级当天无需任何操作。你会注意到的变化:
- New 浮层现已改为独立页面。 仪表板上的 + 新建 会打开
/new,包含机器选择、Agent 或 Command 下拉菜单、文件夹以及 新建 worktree 开关。原来的 new-space 浮层、空间标签及其已有 worktree 列表已移除。在对应机器上通过herdr worktree open打开已有 worktree(从手机启动 agent 或 shell)。 - 手机可以添加启动器。 在默认的
[phone] adds = true设置下,已配对的手机最多可向一台机器添加 20 行,保存在launchers-added.json中。在launchers.toml中设置adds = false可关闭该功能(从手机添加的启动器)。 - 纯文件夹名表示 home 下的文件夹。 Folder 字段中的
projects现在表示~/projects,不存在的文件夹会被拒绝并弹出提示。
升级到 1.18.0
1.18.0 版本对读操作和写操作均强制要求配对(ADR 0086)。升级当日的变化如下:
- 已配对的手机仍可正常使用。 其存储的 token 已满足新规则。无需任何操作。
- 未配对的浏览器会显示配对界面。 从未配对且之前允许读取的桌面浏览器,现在会收到
403 device not paired。在主机上运行collie pair,然后在该浏览器的“设置”中输入验证码(配对设备)。 - 已安装的应用在再次加载前可能会保留旧界面。 已安装的应用在再次加载之前,可能仍会显示上一版本的界面。如果在更新到 1.18 或更高版本后显示“Sign in”,请重新加载该应用,或者将其关闭后重新打开。然后按照上述步骤进行配对。
- 脚本必须配对一次。 之前无需 token 即可读取 API 的脚本现在会收到
403。运行collie pair --expires 30d,然后向/api/pair发送携带{"code": "...", "label": "script"}和同源Origin请求头的 POST 请求以认领验证码。token 仅在该响应中返回一次。在后续的每次调用中将其作为Authorization: Bearer <token>发送。请像密码一样保管它。 - 主机 CLI 无需任何配置。
collie doctor、collie history以及 crew update sweep 会使用 bridge 写入状态目录的本地凭据来读取其自身的 bridge。 - 回滚至 1.18.0 以下版本将忽略 token 过期时间。 较旧版本的 bridge 无法识别
expiresAt字段,因此过期的设备在 bridge 更新前仍可继续使用。如果有需要,可以使用collie devices revoke <label>将其撤销(为设备设置过期时间)。 - 旧的审计文件可能包含键入的字符。 在 1.18.0 之前写入的文件可能会记录在手机上键入的字符。请轮换或删除更新前的
audit.log文件。 - 遮蔽可能会带来干扰。 “文件”中的文件主体与“变更”中的 diff 现在会经过与窗格文本相同的机密遮蔽处理。如果它隐藏了你所需的内容,请在
.env中设置COLLIE_REDACT=off并重启(配置)。 - 1.18.0 版本的 lead 也会遮蔽其 member 的文本。 仍处于 1.17.x 版本的 member 不会进行遮蔽,因此 lead 会在手机接收前遮蔽该 member 的文本。若要查看 member 未经遮蔽的文本,需在 lead 和 member 上同时设置
COLLIE_REDACT=off。
从 0.x 升级至 1.0
如果 BUN_INSTALL 仅在 .env 中定义,请改为在 shell 配置文件或服务环境中导出它。然后运行:
# Herdr-managed
herdr plugin action invoke update-major --plugin herdr.collie
# Linked clone
bin/collie update --major使用 bin/collie version 或 herdr plugin action invoke version --plugin herdr.collie 进行验证。
针对 crew 设置: 先更新 lead,然后运行 collie crew update <member>…(更新 crew 中的其余机器)。注意:
join对于纯http://lead 需要--insecure。- 1.0 之前的邀请令牌必须使用
crew invite重新生成。 - 较旧的成员记录需要
reconnect。
1.0 对你的改变
Herdr 操作 ID 和 scripts/collie-ctl.sh 路由保持不变(ADR 0006)。
CLI 动词被编译到 <checkout>/bin/collie(命令)。使用 bin/collie link 将 collie 添加到 PATH(将 collie 添加到 PATH,ADR 0021)。
新功能:
doctor:配置诊断。
并排,如果 herd 是真实的
辅助实例配置记录在 单台主机上运行多个 Collie 实例 中。
回滚
检出最后一个 0.x 标签并重新构建:
last0x=$(git ls-remote --tags --refs origin | sed 's#.*refs/tags/##' | \
grep -E '^v0\.[0-9]+\.[0-9]+$' | sort -V | tail -1)
git fetch --depth 1 origin tag "$last0x"
git checkout --detach --force "$last0x"
rm -f bin/collie # 1.0's binary otherwise survives the rollback使用 bash scripts/collie-ctl.sh build 重新构建并调用 Herdr 的 restart 操作。状态文件(crew-trust.json、crew-runtime.json、paired-devices.json、pairing-pending.json)可以保留。回滚会移除设备配对强制要求;如果需要写保护,请配置 COLLIE_DEVICE_HEADER。
验证是否生效
检查 version 是否报告 1.0.0 或更高版本。升级后的安装不会自动配对任何设备:运行 pair 为手机签发写凭据,若手机丢失则运行 devices revoke(配对设备)。
停止或卸载
暂停服务:
herdr plugin action invoke stop --plugin herdr.collie # Herdr-managed
bin/collie stop # standalone删除服务定义和端口映射(保留 .env 和检出目录):
herdr plugin action invoke uninstall --plugin herdr.collie # Herdr-managed
bin/collie uninstall # standalone如需删除程序以及你自己的文件,请按照 安装 → 卸载 下的三个步骤操作,该处针对不同安装类型(包含软件包)进行了详细说明。
当 collie 无法运行时
对于二进制安装(~/.local/share/collie 或 $COLLIE_DIR),直接执行较旧的二进制文件:
ls ~/.local/share/collie/versions/
~/.local/share/collie/versions/<previous>/bin/collie update --rollback直接安装指定版本:
curl -fsSL https://colliepwa.dev/install.sh | COLLIE_TAG=v1.0.0 sh对于源码检出或 Herdr 安装,运行 git checkout <tag> 或 herdr plugin install AltanS/collie --ref vX.Y.Z --yes。
运行自定义 fork
collie update 会对比 origin 与 COLLIE_UPDATE_REPO(默认为 AltanS/collie),若两者不同则中止。如果你的 fork 自行发布标签,请设置 COLLIE_UPDATE_REPO=you/collie。
手动将上游更新合并到你的 fork:
git remote add upstream https://github.com/AltanS/collie.git
git fetch upstream --tags
git merge v1.0.0 # the tag you decided to take
# resolve the conflicts, commit the merge, then rebuild and restart:
bash scripts/collie-ctl.sh build
# Herdr-managed: invoke the `restart` action instead
bin/collie restart不要在 fork 上使用 update --major;请手动合并 v1.* 标签。运行 collie doctor 检查当前生效的 COLLIE_UPDATE_REPO。
在系统重启后保持运行
在 Linux 上,为无人值守的用户服务启用 lingering:
loginctl enable-linger $USER使用 systemctl --user status collie 验证状态。
在 macOS 上,start 会自动管理 ~/Library/LaunchAgents/herdr.collie.plist。它在用户登录时运行。使用 launchctl print gui/$(id -u)/herdr.collie 检查状态。