Cryochamber
Cryochamber 是 AI 智能体(Claude、OpenCode、Codex、Pi、Kimi Code)的休眠舱。 它在两次会话之间让智能体休眠,并在合适的时机唤醒它——而不是按照固定的时间表。智能体阅读自己的计划,完成任务,然后自行决定下一次何时唤醒。这让 AI 智能体可以运行跨越数天、数周甚至数年的任务,就像星际旅行者在冷冻休眠中一样。
为什么不用 cron?
Cron 按固定时间表唤醒,不管有没有事情要做。Cryochamber 把调度决定交给智能体:
- 省 token。 由 cron 驱动的智能体每次 tick 都会烧掉一整次会话,即使什么都没变化。Cryochamber 的智能体会一直休眠,直到有理由唤醒——它自己安排的 TODO,或收件箱里的一条消息。
- 省心。 使用 cron 时,人类必须预先猜对时间表:太快浪费钱,太慢错过事情。在这里,智能体根据实际情况推理——推迟的截止日期、等待作者推送修复的评审、国际象棋对手的节奏——然后选择自己的下一次唤醒时间。
- 应对紧急情况。 当有事情需要关注时,智能体可以把唤醒安排在几分钟后,而收件箱消息可以立即唤醒它。Cron 在关键时刻无法加速。
两分钟上手
平台支持: 仅支持 macOS 和 Linux。
cargo install cryochamber
mkdir my-chamber && cd my-chamber
cryo init # 生成 plan.md 和 cryo.toml(或让 make-plan 技能引导你)
cryo start # 启动守护进程,安装为操作系统服务
cryohub start # 在浏览器中打开打印出的仪表盘 URL
然后编辑 plan.md 来描述智能体的目标和任务。可运行的示例 chamber(mr-lazy、chess-by-mail 等)位于 GitHub 上的 examples/chambers/。
亲眼看看它如何工作
cryohub start # 打印本地仪表盘 URL——在浏览器中打开
Cryohub 提供 Agent Console:每个 chamber 都有主消息流和专注的话题视图,并提供状态、TODO、笔记、日志尾部与生命周期控制,手机和桌面浏览器都能用。它内嵌在 cryohub 二进制中——无需安装。可以通过邀请链接把单个 chamber 分享给他人,或用 cryo-zulip 把它桥接到 Zulip。
Chamber 的保证
- 每次唤醒都会产生一条可见消息。 如果智能体未回复就退出,守护进程会写入一条兜底消息——会话绝不会静默。
- 每条收件箱消息都会得到回复。 即使智能体会话中途崩溃,发送方仍会收到回复。
- 每个 TODO 都会被兑现。 失败的会话会被重新安排为带指数退避的可见重试。
- 任何内容都不会被消费两次。 已被领取的消息和 TODO 绝不会悄悄回到待处理状态。
下一步
- 快速上手——从零到一个运行中的 hub:安装 Pi、建一个照看主机的第一个 chamber、分享给朋友。
- 工作原理——五分钟讲解:chamber 文件和会话循环。
- Agent Console——网页与手机界面:登录、邀请、公网部署。
- CLI 参考——所有
cryo、cryohub、cryo-agent和cryo-zulip命令。 - 配置——所有
cryo.toml和cryohub.toml字段。
快速上手
这一页带着一台机器从零走到一个运行中的 hub:建好第一个 chamber,在手机上就能读, 还能分享给朋友。一共五步:启动 hub、装好 Pi agent、连接、创建第一个 chamber、分享。
平台: hub 运行在 macOS 和 Linux 上。原生 App 支持 Apple Silicon 的 macOS;在手机上,浏览器控制台可以作为 PWA 安装使用。
1. 启动 hub
本页介绍当前 main 的功能,控制台和认证功能晚于 v0.2.8。下次发布前, 请安装 Rust 和 Node.js 22,并在仓库源码目录运行:
make console-build
cargo install --path . --locked
cryohub start
cryohub start 会把 hub 安装为用户级服务(重启后依然存活),绑定
http://127.0.0.1:8765,并在第一次运行时打印 owner token:
Owner token (save it — or reprint later with `cryohub token owner`):
3f9c…
这个 token 就是你的登录凭证——没有账号、密码或邮箱。任何时候都可以用
cryohub token owner 重新打印。
2. 装好 Pi agent
chamber 需要 hub 主机上装有一个 agent 运行器。Pi 是内置默认:
npm install -g @mariozechner/pi-coding-agent
which pi # hub 在启动 chamber 前会验证这个可执行文件存在
Pi 从环境变量读取模型提供商的 API key,而你不需要在全局导出任何东西:下一步的
+ New chamber 表单里有一个折叠的 API key 区域,会把 key 写进该 chamber 自己的
cryo.toml 的 [provider] env,daemon 在每个会话启动时注入。
想用别的运行器?claude、opencode、codex、kimi 都在 Settings → Default
agent 下拉框里——见选择 chamber
运行哪个智能体。
3. 连接
在 hub 所在机器上: 用浏览器打开 http://127.0.0.1:8765,粘贴 owner token。
从手机或另一台机器: hub 始终只绑定 loopback,所以要在前面架一个终结 TLS 的反向 代理——公网部署一节有完整的 Caddy 配方。然后二选一:
- 在手机浏览器打开
https://agents.example.com,添加到主屏幕;或者 - 在 Mac 上安装原生 App,添加 hub——地址加 owner token。App 可以同时持有多份访问链接,并按 Owned 与 Joined 分类;浏览器安装的 PWA 只绑定提供它的那一个 hub。
4. 第一个 chamber:host manager
一个很好的引导型 chamber,就是照看 hub 主机自身的那个。在控制台里点
+ New chamber,取名 host-manager,把 API key 粘贴进折叠的 API key 区域,然后
创建——表单会在一次操作里搭好 chamber 并启动它。接着打开 ⋯ Chamber controls →
Plan → Edit plan,给它一份这样的任务简报:
# Host manager
你负责照看这台机器。每天一次:
- 检查磁盘剩余空间(`df -h /`);使用率超过 85% 时提醒我。
- 检查 `cryohub status` 和其他 chamber 的 `cryo status` 是否健康。
- 用几行字汇报;只把需要人处理的事提出来。
每天 09:00 左右醒来一次。如果我给你发消息,处理并回复。
编辑计划后不需要重启任何东西:agent 在每个会话开始时都会读 plan.md。从这里开始,
它自己安排唤醒时间,把每个会话的结果汇报到 chamber 的对话里,并回复你发去的任何消息。
5. 把 chamber 分享给朋友
打开这个 chamber,点标题栏里的 Invite,可选地填上朋友的名字,然后 Copy invite link。把链接发给对方:
- 在浏览器里打开,这个链接就是登录——对方直接落在这一个 chamber 里;
- 粘贴进 App 的 Add a chamber → Admin or invite link 字段,它会替对方填好地址和 token。
链接只限定在这一个 chamber:访客可以在里面阅读和发送,但永远看不到你的其他 chamber 和任何控制项。同一张表单上的 People with access 列出每条有效链接; Remove 立即吊销一条。分享的前提是朋友能访问到这个 hub——也就是第 3 步的反向代理。
工作原理
五分钟了解 chamber 的各个部件。
Chamber 就是一个目录
cryo init 会创建三个文件:
plan.md—— 智能体的使命:目标、任务和规则。智能体在每次会话开始时都会重新阅读它。cryo.toml—— chamber 配置:运行哪个智能体命令、会话超时、收件箱监听。参见 配置。NOTES.md—— 智能体跨会话的记忆。它直接读取并向该文件追加内容。
守护进程运行时,旁边会出现运行时状态:日志、todo.json,以及 messages/inbox/ 和 messages/outbox/。
计划就是纯 Markdown
一个监听 GitHub 仓库新版本的 chamber:
# Release watcher
## Goal
Tell me when acme/widgets publishes a new release.
## Tasks
1. Run `gh release list --repo acme/widgets --limit 1` and compare
the version with the one recorded in NOTES.md.
2. If it changed: send me the release notes with `cryo-agent send`,
then record the new version in NOTES.md.
3. Schedule the next check with `cryo-agent todo add` — every 2 hours
on weekdays, once a day on weekends.
4. Hibernate with `cryo-agent hibernate --summary "..."`.
不需要代码,也不需要 cron 表达式——智能体自己判断情况(这里是工作日还是周末)并决定下一次唤醒时机。
会话循环
daemon wakes agent <- earliest TODO due, or inbox message
│
v
agent reads plan.md + NOTES.md
│
v
does the work
│
v
cryo-agent send "..." <- a visible message, never silent
│
v
cryo-agent todo add "..." --at <when> <- declares the next wake
│
v
cryo-agent hibernate <- daemon sleeps until that wake
│
└────────────── back to the top ──────────────┘
一次唤醒、一次智能体运行、再回到休眠——这就是一个会话:
- 当最早到期(due)的 TODO 到来时,守护进程唤醒智能体;若有收件箱消息到达,则立即唤醒。
- 智能体阅读
plan.md和NOTES.md,然后开始干活。 - 它用
cryo-agent send至少发送一条可见消息。如果它在发送前退出,守护进程会写入一条兜底消息——会话绝不会静默。 - 它用
cryo-agent todo add "..." --at <time>声明自己的下一次唤醒。守护进程的下一次唤醒永远是「最早到期的 TODO」——没有 TODO,就不唤醒。 - 它调用
cryo-agent hibernate并退出。守护进程一直休眠到下一个触发时机。hibernate --complete则彻底结束计划。
与智能体对话
从终端(cryo send "...")或 Cryohub 仪表盘发送消息。消息会落入 messages/inbox/,并在默认的 watch_dirs 配置下立即唤醒智能体。智能体的回复会出现在 messages/outbox/ 以及仪表盘的消息历史中。
仪表盘会在专注视图中打开每个话题。一次 cryo-agent receive 或 cryo-agent dialog 只领取一段对话:第一条待处理话题中的消息,或主消息流中未加入话题的待处理消息。领取后,智能体必须先回复当前对话,才能领取另一段对话。对于话题跟进,智能体会同时获得根消息和之前的回复作为上下文;它下一次发送的消息会自动回到同一话题。
把话题回复分享到主消息流只会在发件箱中创建一份展示副本。它不会向本地收件箱添加消息,因此不会唤醒智能体,也不会为智能体创建新工作。
下一步
会话意外中断
Daemon 在归档已领取的对话前,会持久化回复义务。进程被强制结束后,下次启动 会检查是否已有回复;若没有,就发送中断通知。外部操作可能已部分完成,请先检查 历史记录,再决定是否重发指令。已领取消息仍在归档中,不会自动重放;未读取的消息 仍留在收件箱。恢复日志损坏时,启动会报错,不会悄悄丢弃记录。
备份和升级步骤见运行维护。
Agent Console
Agent Console 是 cryohub 提供的网页界面——一个手机优先、可安装的应用,用来阅读和操控 hub 所知的每一个 chamber。每个 chamber 都有一条容纳报告和指令的主消息流,并用专注的全屏话题视图处理后续追问;chamber 的控制项一步之遥。
它内嵌在 cryohub 二进制中,无需安装:启动 hub,打开它打印的 URL 即可。
cryohub start # http://127.0.0.1:8765
登录
cryohub start 默认以公开模式运行:每个 /api 路由都需要 bearer token,控制台会显示登录页。首次启动会创建 owner token 并打印出来——这一行就是你的登录凭据,请保存好:
Owner token (save it — or reprint later with `cryohub token owner`):
3f9c…
两种 token 可以打开控制台:
- Owner token。 由首次
cryohub start打印,之后随时可用cryohub token owner再次打印(幂等——始终是同一个密钥)。粘贴到 Access token 中。这就是你本人:对每个 chamber 拥有完全控制权。 - 邀请链接。 持有 owner token 的人铸造一条仅限某个 chamber 的链接发给你。打开链接就是登录——token 位于
#invite=片段中,被存储后会在任何其他代码运行之前从地址栏中抹去。
没有账户、密码或邮箱。token 即身份。
cryohub start --no-public 可以退出公开模式:没有登录环节,能访问 127.0.0.1 的人就能使用 hub。开放模式下分享与邀请链接无法工作。
Owner 视图与访客视图
| Owner | 邀请持有者 | |
|---|---|---|
| 项目列表 | 全部 chamber,含状态点、下次唤醒、待回答问题标记、已完成 / 已归档分组 | 仅被邀请的 chamber,平铺 |
| 对话 | 阅读、发送、上传文件、打开附件 | 相同,仅限被邀请的 chamber |
| ⋯ Chamber 控制(启动、停止、重启、重置、归档;Todos · Plan · Notes · Settings · Log 标签页) | 有 | 从不显示 |
| Invite(铸造链接、People with access、Remove) | 有 | 从不显示 |
| + 新建 chamber、Refresh chambers、Show completed & archived | 有 | 从不显示 |
这张表只是 UI 层面的决定,真正的边界在 hub:每个路由都按默认拒绝分类。访客直接调用 owner 路由——chamber 状态、todo、生命周期、同步、token 管理——无论应用画了什么都会得到 403;访客的实时事件流也从不携带日志行或其他 chamber 的消息。
创建 chamber
仅 owner 可见的 + 新建 chamber 面板会在一次操作中创建并启动 chamber。它使用 cryohub.toml 中主机级的 default_agent;如需更改,请先在控制台的 Settings 面板中修改。hub 会在创建任何目录之前检查该命令的可执行文件是否可用。如果脚手架创建成功、但 daemon 启动失败,新 chamber 仍会保留,控制台会显示启动错误,修复后可从 Chamber 控制中再次启动。
消息、话题与分享到主消息流
消息正文支持 Markdown,包括表格和围栏代码块,也支持单美元符号包围的行内 LaTeX 与双美元符号包围的块级 LaTeX。控制台在浏览器中渲染并净化这些内容。
需要针对某份报告集中追问时,可以在话题中回复。每次收到新的话题跟进,智能体都会同时获得话题根消息和回复历史;它的答复会自动回到同一话题。在当前对话得到回复前,其他话题和主消息流中的消息会继续等待。
点击 Reply in thread、回复数量或新话题活动链接,会打开全屏话题视图。原消息位于顶部,回复依次显示在下方,同一个消息输入框固定在底部。点击 Back to stream 或按 Escape 返回主消息流。打开话题期间,主消息流中的草稿和上传仍可继续使用;每个话题也会分别保留自己的文字草稿和已完成上传。
如果某条话题回复也应出现在 chamber 的主消息流中,请使用 Share to stream。此操作会在发件箱中创建一份用于展示的副本,不会向智能体发送新指令,也不会将它唤醒。
添加附件
可以点击回形针、把文件拖入编辑框,或从剪贴板粘贴文件。每条消息最多暂存 10 个文件,每个文件不得超过 25 MB。发送前可以看到图片预览、上传进度、移除和重试操作。消息可以只有附件,无需填写文字。
已发送的文件显示为下载卡片。文本文件可以直接预览;PDF 使用浏览器内置阅读器,不支持时可下载后打开。
已上传完成的文件引用会随草稿保存,并在重新加载后恢复。排队中或上传中的文件字节只存在于当前浏览器标签页中;如果上传完成前重新加载页面,需要重新添加这些文件。
邀请他人加入某个 chamber
- 用 owner token 登录,打开该 chamber,点击标题栏的 Invite。
- 可选地为对方命名(留空则依次为
guest-1、guest-2……;名字在整个 hub 内唯一),然后 Copy invite link。链接会被铸造、限定在这一个 chamber,并一步复制到剪贴板。 - 发给对方。链接只显示一次,hub 不会再次显示。链接丢了就再铸一条。
- 同一面板上的 People with access 列出所有能访问此 chamber 的有效链接。Remove 会在确认后吊销:链接立即失效,访客已打开的事件流结束,其下一次请求得到
401,并被送回登录页,提示 “Your session is no longer valid — please sign in again.”(若再次打开那条已吊销的链接,则提示 “This invite link is no longer valid.”)
分享需要公开模式——在开放的回环 hub 上,面板会直接说明这一点,而不是铸造一条谁也用不上的链接。
同样的 token 也可以从命令行管理:
cryohub token create --name alice --chambers qec-decoders # 只打印一次链接片段
cryohub token list
cryohub token revoke alice
选择 chamber 运行哪个智能体
两个下拉框,都只对 owner 可见:
- Settings → Default agent 是主机级默认值,保存在
cryohub.toml的default_agent中。它决定新建 chamber 使用哪个运行器——包括控制台的 + 新建 chamber 和同一台机器上的普通cryo init。修改它不会重写任何已存在的 chamber。 - ⋯ Chamber 控制 → Settings → Agent 是单个 chamber 自己的运行器,保存在该
chamber 的
cryo.toml的agent中。
两个列表都提供 pi、opencode、claude、codex 和 kimi,外加当前已保存的
值——像 pi --thinking high 这样手写的命令,或指向自定义运行器的路径,都会保持
可选,而不会被悄悄替换。其他想运行的命令请直接写进 cryo.toml。
保存任一下拉框时,hub 都会检查该命令的可执行文件在主机上是否可用。不可用的运行器会被拒绝,原设置保持不变。
守护进程在启动时读取 cryo.toml,因此修改正在运行的 chamber 的智能体要到下次
重启才生效;遇到这种情况控制台会提示。保存同时会重写 cryo.toml,该文件中的注释
不会被保留。
编辑 chamber 的计划
⋯ Chamber 控制 → Plan → Edit plan 会以 markdown 源码打开 plan.md 并写回。
仅 owner 可用。
无需重启任何东西:智能体被要求在每个会话开始时读取 plan.md,因此下一次唤醒就会
按新的计划工作。以最后一次写入为准——控制台没有冲突提示,因为 chamber 自己的智能体
被要求把运行状态保存在 NOTES.md 中;出于同样的原因,NOTES.md 在这里保持只读。
安装到手机或桌面
控制台是一个 PWA。在浏览器中打开后:
- Android / Chrome: ⋮ → 添加到主屏幕(或 安装应用)。
- iOS / Safari: 分享 → 添加到主屏幕。
- macOS: Chrome 安装,或 Safari 文件 → 添加到程序坞。
安装的应用绑定到提供它的那个 hub——一次安装对应一个 hub。原生 App 解除了这个限制,可以保存多份访问链接,并按 Owned 与 Joined 分类,参见安装 App。更新随 hub 到来:cargo install cryochamber 升级并 cryohub restart 之后,打开的应用会显示 Update available · Reload 提示条。
没有推送通知,这是有意为之:应用只在打开时同步。它是一个你主动查看的控制台,不是寻呼机。
公网部署(在外用手机访问)
cryohub 始终只绑定回环地址。要在外面用手机访问,需要在前面放一个终止 TLS 的反向代理。公开模式本来就是默认的,无需切换——只要确认你手里有 owner token。
cryohub start # 所有 /api 路由启用 bearer 鉴权;首次运行会打印 owner token
cryohub token owner # 也可以事后再打印一次——这就是你的登录凭据
文档采用 Caddy 作为代理。把下面内容复制到 /etc/caddy/Caddyfile,替换主机名(在 reload 之前它必须已有指向此主机的 A/AAAA 记录,否则无法签发证书),然后 systemctl reload caddy:
agents.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:8765
}
hub 会拒绝 Host 头既不是回环地址也不是已配置名称的请求——这正是防御 DNS 重绑定的机制——而 Caddy 默认会转发公网主机名,因此要在 cryohub.toml 中放行它:
public_hosts = ["agents.example.com"]
(另一种做法是在 reverse_proxy 块里加 header_up Host 127.0.0.1。)然后在手机上打开 https://agents.example.com,粘贴 owner token 或打开邀请链接,再添加到主屏幕。
在 --public 下控制台自身的页面仍无需鉴权——它们就是登录页。/api 下的一切都在 token 之后。
在 public 模式下,每个凭证(访客与 owner 一视同仁)的发送与上传都受限流:突发额度 5 次,之后每分钟 10 次;超出后 hub 返回 429,并带上 Retry-After 头。收件箱消息可能唤醒智能体,上传则会占用 owner 的磁盘,因此限流可以防止邀请链接推高账单或用文件塞满 chamber。分享到主消息流不会唤醒智能体。
从其他位置提供构建产物(console_dir)
使用控制台并不需要这一项。它用于开发,或运行一个比二进制内嵌版本更新、不同的控制台构建:
# ~/.config/cryo/cryohub.toml
console_dir = "/home/alice/src/cryochamber/console/dist"
路径必须是绝对路径(hub 会基于服务进程的工作目录规范化它,而工作目录由 launchd/systemd 决定)。make console-build 生成 console/dist/;cryohub restart 后生效。cryohub status 会打印当前生效的来源——Console: embedded 或 Console: <path> (present|missing)。
hub 对 / 和任何客户端路由返回 index.html,从 /assets/ 提供带不可变缓存的哈希资源,并且绝不允许请求指向控制台目录之外的文件。/api 不受影响。
设备上存储了什么
访问 token、hub 记录的你的名字、每个 chamber 的已读水位、文本草稿、已上传完成的附件引用,以及一小份最近消息缓存,都存放在该 hub 源(origin)的 localStorage 中。排队中和上传中的文件字节不会保存。退出登录会清除这些数据。消息正文在客户端渲染,并在进入 DOM 之前经过净化。
安装 App
Cryochamber App 是把 hub 在浏览器里提供的那个 Agent Console 装进原生窗口的版本。它存在的理由只有一个——浏览器做不到的事: 它能同时持有多份访问链接,把 chamber 分为 Owned 与 Joined,并且每个 hub 的请求都走操作系统的网络栈, 而不是页面自身的 origin。
hub 这边什么都不变。hub 提供的网页控制台还在原处——用浏览器打开
http://127.0.0.1:8765,或者把它添加到主屏幕当作 PWA 使用,得到的是绑定到那一个 hub
的同一套界面。当你的 hub 数量不再是「一个」时,App 才是那个选项。
v0.2.8 发布时尚未包含原生 App,没有安装包。在后续 GitHub release 提供安装包前, 请按源码构建说明构建。 发布工作流生成的文件名如下:
| 文件 | 适用于 |
|---|---|
cryochamber-vX.Y.Z-android-arm64.apk | 64 位 ARM Android 手机与平板 |
cryochamber-vX.Y.Z-macos-arm64.dmg | Apple Silicon 上的 macOS |
cryochamber-vX.Y.Z-macos-arm64.app.zip | 同一个 App 的 zip 包,如果你不想挂载磁盘映像 |
在 macOS 上请选 dmg。两个 macOS 文件装的是同一个 .app,打包前都经过一次完整的
codesign --deep -s - 重新封签;.app.zip 只是给不愿挂载磁盘映像的人准备的。
目前没有 Play Store、App Store、Windows 或 Intel Mac 构建。上面列出的就是全部。
Android
- 从 release 页面下载
cryochamber-vX.Y.Z-android-arm64.apk。 - 打开文件;Android 提示时,允许浏览器或文件管理器安装未知应用,然后返回并安装 APK。
- 填入 hub 地址和访问 token,或把管理员/邀请链接粘贴到 Admin or invite link。
cryochamber://链接会直接打开 App。普通网页邀请链接可通过 Android 的分享操作发送给 Cryochamber。
该 APK 支持 Android 7 及以上的 arm64 设备。它有正式签名,但通过 GitHub 而不是 Google Play 分发。
macOS
- 下载
cryochamber-vX.Y.Z-macos-arm64.dmg,打开它,把 Cryochamber 拖到 应用程序。 - 首次启动需要右键。 该构建使用 ad-hoc 签名,且未做公证(notarization), 所以双击只会得到*「无法打开,因为无法验证开发者」。在 应用程序 里右键(或 Control-点击)该 App → 打开 → 打开。macOS 会记住这个决定,之后就能正常启动了。 在 macOS 15(Sequoia)及以后的版本上,右键绕过的路子已经没有了——先让首次启动被拒绝, 然后到系统设置 → 隐私与安全性 → 仍要打开*中放行该 App。
- 填入 hub 地址和访问 token,或把管理员/邀请链接粘贴到 Admin or invite link。
仅支持 Apple Silicon。公证尚未完成,在完成之前本页会一直这样写着。
信任:App 在发送 token 之前会问什么
访问 token 就是密码。在把它发往某个地址之前,App 会显式地判定这个地址可以被信任到什么程度。 一共三种情况。
系统已信任其证书的 HTTPS。 什么都不问。这就是挂在反向代理后、持有真实证书的 hub (控制台指南里的 Caddy 配置),也是应当追求的情况。
明文 http://。 只要你输入的是明文地址,地址下方立刻出现警告,并且 Add chamber
按钮保持禁用,直到你勾选 「I understand traffic to this hub is unencrypted」
(我明白发往此 hub 的流量未加密)。字面含义是:token 和你发送的每一条消息,在设备与 hub
之间的任何一环上都是可读的。在自己机器上(http://127.0.0.1:8765)这个「任何一环」是空的,
勾选只是走个形式;在咖啡馆或会场的网络里,它是同一网络上的所有人。修改地址会取消勾选——
这份确认针对的是某一个主机,而不是这张表单。
系统不信任其证书的 HTTPS——自签名证书,或私有 CA。App 既不会默默接受,也不会默默拒绝。 它会探测该主机,然后弹出 Untrusted certificate(不受信任的证书)面板, 以冒号分组的大写十六进制显示证书的 SHA-256 指纹。请与 hub 运维者念给你听的值比对:
# 在 hub 主机上,针对代理所提供的证书
openssl x509 -fingerprint -sha256 -noout -in /path/to/cert.pem
# sha256 Fingerprint=88:44:DD:65:…
# 或者从任意位置,直接取自实时握手
openssl s_client -connect hub.example:8443 </dev/null 2>/dev/null \
| openssl x509 -fingerprint -sha256 -noout
面板正是采用这种分组方式,好让两者可以一组一组地对读,而不是把 64 个字符当成一整串去瞪。 如果一致,Add chamber anyway 会从此把那一张证书钉死(pin)在那一个 hub 上。 如果不一致,那么是别人在冒充这个 hub——Cancel 不会存下任何东西。
被钉死的 hub 之后若换了另一张证书,连接会直接失败,而不是悄悄信任新证书。当运维者正常更换证书时, 在 Settings → Chamber access 中移除该访问记录再重新添加,即可重新钉定。
同时保存多份 chamber 访问
Settings → Chamber access 列出 App 记住的每一份访问——标签、hub 地址、当前 token
是 Owner 还是 Guest、以及该 hub 的 cryohub 版本——底部是 Add chamber,每一行上是
Remove。即使两个 token 指向同一个 hub,也会同时保留;新加入的范围不会覆盖之前保存的 chamber。
主列表分为 Owned 和 Joined。如果同一个 hub 的管理员 token 与邀请 token 都能看到同一个 chamber,App 只在 Owned 中显示一次,并保留管理员控制。未读计数、草稿和已读水位按每份访问分开保存。
Owner 可以使用 Settings → Chambers → Copy admin link。App 会先警告,因为拿到该链接的人可以
管理所选 hub 上的全部 chamber。复制出的 cryochamber:// 链接会直接打开添加 chamber 表单。
各个 hub 独立失败。某个 hub 不再应答时,它那些行的标签片会显示 · unreachable 并变灰——该行仍然展示这个 hub 最后说过的话,而不是消失——与此同时其他每个 hub 照常推流、发送、更新。它恢复之后,那些行会自行复原;不需要重启,也不需要重新输入 token。
Hub 账号保存在 App 自己的私有数据目录里,而不是浏览器存储中,所以清空浏览器、
或 WebView 数据被回收,都不会让你丢掉 token。在 macOS 上该文件是
~/Library/Application Support/com.cryochamber.console/hubs.json。
它以明文保存 bearer token,仅靠该目录的文件权限保护——请像对待
~/.config/cryo/cryohub-tokens.json 那样对待它。
更新
没有应用内更新器,也没有更新通道。下载下一个 release 的构建,覆盖安装即可。
- macOS: 替换 应用程序 里的 Cryochamber。hub 存储位于 App 包之外,不受影响。 新下载的这一份可能需要再做一次右键打开的动作。
- Android: 直接覆盖安装新版 APK。各版本使用同一签名密钥,所以 Android 会保留 App 的 hub 存储。
hub 自身是单独升级的(cargo install cryochamber,然后 cryohub restart)。
如果某个 hub 比 App 旧,Settings → Chamber access 会在该 hub 那一行注明——
「hub is older — some features may be missing」。
CLI 参考
所有 cryochamber 二进制及其命令。cryo.toml 和 cryohub.toml 的字段见 配置。
每个二进制都接受 --version(打印版本并退出)和 --help。
操作员 CLI(cryo)
除非另有说明,请在 chamber 目录内运行这些命令。
| 类别 | 命令 | 作用 |
|---|---|---|
| 生命周期 | cryo init [--agent <cmd>] | 初始化目录:写入 cryo.toml、plan.md、NOTES.md 和 README.md。已有文件会被保留。未给出 --agent 时使用 cryohub.toml 中的主机级 default_agent(内置默认:pi)。 |
cryo start [--agent <cmd>] | 启动守护进程。读取 cryo.toml 并把覆盖项写入 timer.json。 | |
cryo start --max-session-duration 3600 | 为本次运行覆盖会话超时时间。 | |
cryo status | 显示守护进程是否在运行、当前会话编号以及下一次唤醒时间。 | |
cryo restart | 重启正在运行的守护进程。若它已安装为操作系统服务,则重启现有服务而不重写或移除它。 | |
cryo cancel | 停止守护进程并移除运行时状态。 | |
| 日志 | cryo watch [--all] [--viewpoint cryo|agent] | 实时跟踪日志。--all 从头显示日志。--viewpoint cryo(默认)跟踪结构化事件日志;--viewpoint agent 跟踪智能体原始输出(cryo-agent.log)。 |
cryo log | 打印完整会话日志。 | |
| 消息 | cryo send "<message>" [--from <name>] [--subject <text>] | 向智能体的收件箱发送消息;守护进程的收件箱监视器会唤醒智能体。--from 设置发送者(默认 human),--subject 设置主题(默认根据正文生成)。 |
cryo receive | 读取智能体发送到发件箱(outbox)的消息。 | |
| 维护 | cryo clean [--force] | 移除日志、状态、消息等运行时文件。 |
cryo ps [--kill-all] | 列出(或终止)本机上所有正在运行的 cryo 守护进程。可从任意目录运行。 |
Hub(cryohub)
| 命令 | 作用 |
|---|---|
cryohub start [--host <ip>] [--port <n>] [--default-agent <cmd>] | 安装一个重启后依然存活的服务。默认强制 bearer 鉴权,并在首次运行时打印 owner token(之后可用 cryohub token owner 再次打印)。提供的主机、端口和默认智能体会更新已保存的主机配置。 |
cryohub start --foreground | 在当前终端运行 hub,而不是安装服务。 |
cryohub stop | 卸载全局 hub 服务。 |
cryohub restart | 重启已安装的全局 hub 服务,无需重新安装。 |
cryohub status | 显示全局 hub 的 URL、模式(public (bearer auth) 或 open (loopback))、chamber 根目录、配置文件路径、日志路径、控制台来源(embedded,或 console_dir 覆盖路径及构建是否存在)和服务状态。同时列出旧版本遗留的、以当前目录为作用域的 hub 服务。 |
cryohub start --public | 对所有 /api 路由强制启用 bearer token 鉴权——这是默认行为。若尚无 owner token 则创建并打印。该值写入 cryohub.toml,因此之后的普通 cryohub start、重启或重新开机都保持鉴权。 |
cryohub start --no-public | 以无鉴权的开放模式运行(仅限回环地址)。开放模式下分享与邀请无法工作。必须显式指定:关闭鉴权绝不隐式发生,之后的普通 cryohub start 也会保持已保存的开放模式。 |
cryohub token owner | 打印 owner token,首次运行时创建。幂等——重复运行打印同一个密钥。 |
cryohub token create --name <名称> --chambers <id,...> | 创建一个限定到这些 chamber id 的具名邀请。打印 token 及其 #invite= 链接片段;这是密钥唯一一次显示的时机。 |
cryohub token list | 列出邀请及其作用域、创建时间和吊销状态。绝不打印 token 字符串。 |
cryohub token revoke <名称> | 按名称吊销邀请。立即生效,包括已经打开的 SSE 流。若没有同名的有效邀请则失败。 |
智能体 IPC(cryo-agent)
这些命令由被派生的 AI 智能体用来通过 Unix socket 与守护进程通信。它们不是操作员接口。
| 类别 | 命令 | 作用 |
|---|---|---|
| 休眠 | cryo-agent hibernate --summary "..." | 结束会话;还有更多工作要做。只要收件箱存在未读邮件,就会被拒绝(非零退出)——智能体必须先 receive、回复,再重试,因此会话绝不会在还有邮件等着它时结束。若没有任何待办 TODO 声明下次唤醒,同样会被拒绝。调用成功后最多可能阻塞智能体通过 --linger <秒数> 请求的回复窗口时长(省略 = 300,上限 86400;0 表示立即入睡)。 |
cryo-agent hibernate --complete | 结束会话;计划已完成。此外,只要有 TODO 到期就会被拒绝。它永远不会被回复窗口驻留。 | |
cryo-agent hibernate --exit 1 | 报告失败的会话。守护进程会把已消费的 TODO 标记为完成,并新增一个带编号的重试 TODO。失败报告永远不会被拒绝,也不会被驻留。 | |
| TODO | cryo-agent todo add "text" --at <TIME> | 通过 TODO 安排下一次唤醒。--at 接受相对偏移(+30 minutes)、ISO 8601 时间戳(2026-04-25T10:00;容忍秒和空格分隔符),或仅日期(2026-04-25,表示午夜)。 |
cryo-agent todo list | 列出所有 TODO 项。 | |
cryo-agent todo done <id> | 将某个 TODO 项标记为完成。 | |
cryo-agent todo remove <id> | 移除某个 TODO 项。 | |
| 消息 | cryo-agent send "message" | 向发件箱写入一条给人类的消息。领取话题后,守护进程会自动把消息发回同一话题。 |
cryo-agent send --stdin | 从 stdin 原样读取发件箱消息正文,包括末尾换行;适用于多行或对 shell 敏感的文字。 | |
cryo-agent send --question "msg" | 将该消息标记为等待人类回复的问题。 | |
cryo-agent receive | 领取一段待处理的人类对话:第一条待处理话题,或主消息流中未加入话题的消息。领取话题时会同时得到根消息和回复历史。Hub 附件链接会转换为本地 messages/attachments/... 路径。回复后才能领取另一段对话。 | |
cryo-agent dialog [--last N | --all | --since <iso>] | 渲染对话记录(默认:最近 20 条消息)。--last N 显示最近 N 条,--all 显示所有已归档消息,--since <iso> 显示某个 ISO 8601 时刻之后的消息;三者互斥。副作用是最多领取并归档一段待处理对话。新领取话题时,即使指定了范围限制,也会包含根消息和完整历史;之后的读取只显示当前话题,并正常应用指定范围。Hub 附件链接会转换为本地 messages/attachments/... 路径。 | |
| 时间 | cryo-agent time | 以 ISO 8601 格式打印当前本地时间。 |
cryo-agent time "+30 minutes" | 计算相对偏移。单位:minutes、hours、days、weeks。 | |
cryo-agent time "2026-04-25T10:00" | 校验并规范化 ISO 8601 时间戳。 |
Zulip 同步(cryo-zulip)
| 命令 | 作用 |
|---|---|
cryo-zulip init --config <zuliprc> --stream <name> [--topic <topic>] [--history] | 校验凭据、解析 stream,并写入 zulip-sync.json。 |
cryo-zulip sync [--interval N] | 启动后台同步守护进程。默认间隔来自 cryo.toml,否则回退为 5 秒。 |
cryo-zulip unsync | 停止同步守护进程。 |
cryo-zulip pull | 单次拉取。 |
cryo-zulip push | 单次推送。 |
cryo-zulip status | 显示同步配置。 |
配置
每个 chamber 都通过其目录下的 cryo.toml 文件进行配置。cryo init 会创建一个带合理默认值的配置。
cryo.toml
# cryo.toml — cryochamber 项目配置
agent = "pi" # 智能体命令 (pi, opencode, claude, codex, kimi, ...)
max_session_duration = 3600 # 会话超时秒数 (0 = 不超时)
watch_dirs = ["messages/inbox"] # 监听以实现响应式唤醒的目录 ([] 表示禁用)
zulip_poll_interval = 5 # Zulip 同步轮询间隔(秒)
# 注入到每个智能体会话的 Provider 环境变量(可选)。
[provider]
name = "anthropic" # 显示名称,在 `cryo status` 中展示
env = { ANTHROPIC_API_KEY = "sk-ant-..." } # 派生智能体时设置的环境变量
| 字段 | 默认值 | 说明 |
|---|---|---|
agent | "pi" | 要运行的智能体命令。使用 "opencode" 表示 OpenCode,"claude" 表示 Claude Code,"codex" 表示 Codex,"kimi" 表示 Kimi Code,或 PATH 上的任何可执行文件。除非 cryo init --agent 显式指定命令,新 chamber 使用主机级 default_agent。owner 也可以在 Agent Console 的 chamber 控制 → Settings → Agent 中修改:这会重写本文件(其中的注释以及 Cryochamber 不认识的键都不会保留),并在该 chamber 下次重启时生效。 |
max_session_duration | 3600 | 会话超时秒数。0 表示禁用超时。 |
watch_dirs | ["messages/inbox"] | 守护进程监听新文件的目录列表,用于响应式唤醒智能体。路径相对于 chamber 目录解释,除非是绝对路径。设为 [] 可完全禁用响应式唤醒。 |
zulip_poll_interval | 5 | cryo-zulip sync 轮询 Zulip 的间隔(秒)。cryo-zulip sync --interval N 可单次覆盖它。 |
**回复窗口不在此处配置。**休眠成功后会话为后续消息保持打开的时长由智能体在每次休眠时自行选择:
cryo-agent hibernate --linger <秒数>(省略 = 300 秒,上限 86400;0表示立即入睡)。休眠驻留期间会话计时暂停,且每一轮后续消息都会重新发放工作预算,因此较长的 linger 可能让同一会话远远超过max_session_duration。
[provider]
Cryochamber 只支持一个活动的 provider 配置。[provider] 表携带一个显示用 name 和一个 env 映射,包含注入到每个派生智能体会话的环境变量——智能体模型的 API 密钥就放在这里。
[provider]
name = "anthropic"
env = { ANTHROPIC_API_KEY = "sk-ant-...", OPENCODE_MODEL = "claude-sonnet-4-20250514" }
配置好之后,cryo status 会显示 provider 名称。
安全提示:
[provider].env下的值是机密。cryo init会写入一个忽略.cryo/的 chamber.gitignore,但cryo.toml本身不会被 gitignore——如果你提交或推送这个 chamber,请让 API 密钥远离版本控制。要么把cryo.toml加入你自己的.gitignore,要么不把密钥写进cryo.toml,而是在cryo start之前把它们导出到环境变量中。
遗留 [[providers]](已弃用)
旧配置使用 [[providers]] 数组。出于向后兼容它仍会被接受,但只会使用第一项——provider 轮换已被移除。加载使用 [[providers]] 的配置会打印弃用警告,下一次 save 会把它重写为规范的单一 [provider] 形式。请迁移到 [provider]。
见下文 cryohub.toml。
cryohub.toml
Cryohub 设置位于 $XDG_CONFIG_HOME/cryo/cryohub.toml;若未设置 XDG_CONFIG_HOME,则位于 ~/.config/cryo/cryohub.toml。默认的本地仪表盘 URL 是 http://127.0.0.1:8765。仪表盘的「新建 Chamber」按钮会在配置的 chamber_root 下创建 chamber,默认是 ~/.cryo/chambers。
host = "127.0.0.1"
port = 8765
chamber_root = "/Users/alice/.cryo/chambers"
default_agent = "pi"
public = false
owner_name = "human"
public_hosts = []
# console_dir = "/absolute/path/to/console/dist" # 可选覆盖,见下文
对于项目自有的 chamber 集合,把 chamber_root 设为项目路径,例如 /path/to/project/.cryo/chambers。
未知的键会被拒绝:像 console-dir 这样的拼写错误会让 cryohub start 报错并指出该键,而不是被静默忽略。
| 字段 | 默认值 | 说明 |
|---|---|---|
host | "127.0.0.1" | 全局仪表盘服务的绑定地址。 |
port | 8765 | 全局仪表盘服务的 TCP 端口。 |
chamber_root | ~/.cryo/chambers | 从仪表盘 UI 创建的 chamber 的默认位置。 |
default_agent | "pi" | 由控制台或普通 cryo init 创建新 chamber 时使用的主机级智能体命令。可在控制台的「设置」中修改、直接编辑此文件,或运行 cryohub start --default-agent <命令>。显式的 cryo init --agent <命令> 优先。现有 chamber 保留自己的 cryo.toml。 |
public | true | 是否对每个 /api 路由强制 bearer token 鉴权。默认开启;在此默认之前写下的、缺少该键的配置文件同样按 true 加载,而显式的 public = false 会保持开放模式。只有 cryohub start --no-public 会清除——普通的 cryohub start 保持这里保存的值。 |
owner_name | "human" | 公开模式下 owner 发送的消息所标记的发送者名字。客户端提供的 from 会被忽略。 |
public_hosts | [] | 在回环地址和 host 之外额外接受的 Host 头值。当反向代理转发公网主机名时需要设置。 |
console_dir | (未设置——使用内嵌版本) | 从此目录提供 Agent Console,而不是使用 cryohub 二进制中内嵌的构建。必须是指向 vite dist/ 的绝对路径。仅用于开发和自定义构建。 |
控制台修改 default_agent 后无需重启 hub。下一次创建 chamber 时会使用新命令;现有 chamber 不会被重写。与这里的其他键一样,手工编辑本文件要到下次 cryohub restart 才被读取。保存该设置、修改某个 chamber 的 agent、传入 cryohub start --default-agent 以及启动 chamber 时,都会检查命令的可执行文件是否可用。控制台的「新建 Chamber」会在一次操作中创建并启动 chamber。
提供 Agent Console
Agent Console 是 hub 的网页界面——没有其他仪表盘——并且它内嵌在二进制中:cryohub start 无需任何配置即可提供它。
hub 对 / 和任何客户端路由返回控制台的 index.html,从 /assets/ 提供带不可变缓存的哈希资源,并保持 /api 不受影响。控制台来源之外的任何内容都不可访问——../ 路径或指向覆盖目录之外的符号链接都会得到 404。即使在 --public 下,控制台自身的页面也不需要鉴权,因为它们就是登录页;每个 /api 路由都在 bearer token 之后。
只有在需要提供不同构建时才设置 console_dir(make console-build 会生成 console/dist/)。它必须是绝对路径:hub 会基于服务进程的工作目录规范化它,而工作目录由 launchd/systemd 决定。cryohub status 会报告当前生效的来源。如果覆盖目录中没有 index.html——或者二进制在构建时没有内嵌控制台且没有覆盖——hub 会对页面返回一个简短的设置页(HTTP 503),而不是空白的 404;API 全程正常工作。
反向代理之后
hub 会拒绝 Host 头既不是回环地址也不是已配置主机的请求——这正是阻止恶意页面通过 DNS 重绑定操控回环服务的机制。保留公网主机名的代理(Caddy 的默认行为)因此需要放行该名字:
public_hosts = ["agents.example.com"]
另一种做法是让代理改写它——在 Caddy 中,在 reverse_proxy 块内加 header_up Host 127.0.0.1。
从命令行覆盖配置
传给 cryo start 的旗标会覆盖本次会话的 cryo.toml。这些覆盖项存储在 timer.json(运行时状态)中,不会修改 cryo.toml。
cryo start --agent claude
cryo start --max-session-duration 3600
配置与状态
| 文件 | 用途 | 跨运行保留 |
|---|---|---|
cryo.toml | 项目配置。提交进 git。 | 是 |
timer.json | 运行时状态:会话编号、PID 锁、CLI 覆盖项。 | 否 |
运行维护与发布
备份和恢复
先停止外部聊天桥接和 hub,再在每个 chamber 中运行 cryo cancel。
若启用了原生 Zulip 同步,运行 cryo-zulip unsync。确认没有相关进程继续写入。
备份整个 chamber,包括配置、计划、TODO、状态、日志、消息、附件和 .cryo。
保留 .cryo/reply-obligation.json,排除运行时 socket .cryo/cryo.sock。
同时备份 host 的 cryo 配置目录和 chamber 注册表。备份含密钥,应限制权限并加密保存。
先恢复到独立目录。原实例保持停止;清除恢复的 timer.json 中的 pid 和
instance_id,删除旧 socket,保留会话状态、TODO 领取状态和回复日志。
检查配置、消息历史和凭据后再启动。确认中断通知和新消息回复正常,再恢复桥接服务。
不要让原实例与恢复实例同时连接同一外部服务。
升级前保存旧版本二进制和一致的数据快照。回滚时一起恢复二进制和匹配的数据。 原生 App 的设备密钥不可迁移,新设备应重新获取 hub token。 完整命令和目录说明见英文操作指南。
历史和发布验证
控制台首次读取最近 100 条消息,按需加载更早页面。游标使用不可变消息文件名; 归档不改变游标。旧版本手工命名的文件按文件名分页。服务端只读取所选页面的消息正文, 但仍扫描文件名和完整会话日志。20 个 chamber、每个 10,000 条消息是初始测试目标, 尚不是延迟承诺。
版本 tag 必须通过 Rust、控制台、Python、原生 shell 和依赖检查。发布先保持草稿,
原生产物构建通过后才发布 crate,最后公开 GitHub release。发布前还需在真实 macOS
和 Android 设备上完成 app/README.md 的安装包测试,记录版本、提交、校验和及结果。
面向用户的 macOS 版本必须使用 Developer ID 签名并完成 notarization。维护者需配置
APPLE_CERTIFICATE、APPLE_CERTIFICATE_PASSWORD、APPLE_SIGNING_IDENTITY、
APPLE_API_ISSUER、APPLE_API_KEY 和 APPLE_API_KEY_CONTENT。缺少凭据时发布失败,
不会降级为 ad-hoc 签名。本地开发构建仍可使用 ad-hoc 签名。
main 要求 PR 和必需检查通过,禁止强制推送和删除。依赖检查在 PR、发布和定时任务中运行;
网络失败不能视为通过。原生 Linux 的 GTK3/GLib 上游维护问题需在支持 Linux 安装包前解决。
维护者应在 2026-12-01 前复查,详情见英文操作指南。