让 SSH 断联后的 opencode 继续跑:我用 Zellij 管理远程 AI agent
AI coding agent 的流行催生了一个新场景:开发者在远程服务器上跑 agent,本地终端只做操控。算力在远端、项目在远端、队友共享同一套环境。但这个模式有一个很少被讨论的前提:agent 依赖的终端必须是可靠的。
最近在远程服务器上用 opencode 写博客,我反复遇到这个问题:合上笔记本、SSH 闪断、或者终端崩溃——opencode 和 AI 之间的上下文就丢了。
后来发现这不是我一个人的情况:
- Claude Code 仓库里有人报告 session hang 后 AI 自己建议打
/clear,7 小时对话永久删除(#61220) - 也有人遇到 session 自动归档后无法从 UI 恢复(#61101),以及 resume 时配置被覆盖、丢失 1M token 上下文窗口(#61068)
- opencode 那边,有用户通过 Tailscale SSH 到 Mac mini 跑 agent,70k token 后 TUI 完全卡死(#20953)
这些问题的共同根源是同一个:agent 跑在终端里,但终端不是一个可靠的运行时。 我的解决思路是用终端复用器把 agent 的进程从终端会话中解耦出来。tmux 和 Zellij 都能做这件事,我用的是 Zellij。下面三个递进的场景,记录了我在不同使用阶段遇到的问题和对应的方法。
桌面端:合盖休眠导致上下文丢失
最开始我在本地直接跑 opencode。写到一半午休合上笔记本,回来发现 terminal 进程跟着休眠了,重新打开后 AI 不记得之前聊了什么。
这个问题在 HN 上也有不少讨论。有用户用 LXC 容器 + tmux 自动启动 Claude Code,然后"Close laptop. Come back later."(来源)。也有用户把 Mac mini 作为"always on"的终端,通过 Tailscale + ssh + tmux 保持 Claude Code 持久会话(来源)。这些方案的核心都一样:让 agent 跑在一个独立于终端之外的进程管理器里。
Zellij 的做法类似,但不需要额外配置:
zellij # 启动 Zellij
opencode # 在窗格里跑 agent
# Ctrl+o d 分离,或者直接关终端
zellij # 下次打开终端,回到之前的会话
Zellij 装完就可以用。opencode 在 Zellij 的窗格里运行,进程挂在 Zellij 的后台守护进程上,不是挂在终端上。关掉终端、合盖休眠、杀掉 terminal emulator——opencode 继续跑。
SSH 远程:网络不可靠导致 session 中断
桌面端问题解决后,我把 opencode 部署到了远程服务器,本地 SSH 连上去操作。这样合盖不影响,但 SSH 本身成了新的脆弱点。
前面提到的 opencode ticket(#20953)就是典型:用户从 Ubuntu 笔记本通过 Tailscale SSH 到 Mac mini,TUI 在 70k token 时卡死,agent 的工作流跟着断掉。HN 上也有用户反映 Claude Code 在 tmux 上闪烁严重(讨论),以及 mosh + tmux 的滚动回退与 Claude Code 的滚动冲突(讨论)。
Zellij 在 SSH 场景下的用法和桌面端差别不大:
ssh user@server # 连到远程
zellij # 启动 Zellij
opencode # 跑 agent
# SSH 断开 ...
ssh user@server # 重新 SSH
zellij attach # 恢复会话,opencode 还在跑
原理是 Zellij 的客户端-服务端架构。zellij 启动后在后台拉起一个独立的 server 进程,所有窗格里的进程挂在这个 server 上。终端窗口只是客户端,客户端断开 server 不受影响。Zellij 官方 FAQ 也确认,版本升级都不会丢会话(文档)。
跨终端:从桌面到手机的切换
持久化和网络可靠性解决后,第三个问题是设备切换。台式机跑着 opencode,路上想用手机看一眼进度,或者在不同电脑之间接续同一个 session。
HN 上有用户尝试在平板上用 Termux + tmux + Claude Code,但 Claude 偶尔会关掉 Termux 导致 session 丢失(讨论)。另一篇博客 Claude Code On-The-Go 介绍了用 Vultr VM + Tailscale + mosh + tmux 的完整方案,但工具链有四层,配置成本不低。
Zellij 内置了 Web 服务器,不需要额外搭建:
# 服务器上 zellij web 启动 Web 服务
# 手机浏览器打开 http://服务器IP:8082/my-session
浏览器里能看到完整的终端界面,支持触摸滚动和键盘输入。从 v0.44.0 开始,另一个终端也能通过 HTTPS 直接附着:
zellij attach https://server:8082/my-session
zellij watch my-session # 只读模式
我现在的工作方式:
- 办公台式机 SSH 到服务器 →
zellij→opencode开始写 - 合盖走人
- 开会时掏出手机看一眼进度
- 回家打开笔记本,
zellij attach回到同样的状态
和 tmux 的对比
tmux 也能做到持久化和远程 attach。Zellij 不是革命性的替代品,它只是把一些细节做得省事一些:
| tmux | Zellij | |
|---|---|---|
| 开箱体验 | 需要配置 .tmux.conf | 零配置可用 |
| 会话复活 | 需要第三方工具 | 内置,崩溃后恢复布局 |
| Web 客户端 | 自搭 WebSocket 代理 | 内置 zellij web |
| 远程附着 | 标准 SSH | SSH + HTTPS |
| 插件生态 | 丰富(shell 脚本) | 起步阶段(WASM) |
| 渲染兼容 | Claude Code 有闪烁报告 | 相对稳定 |
一个值得单独提的点是 Zellij 的会话复活(Session Resurrection)。每 1 秒序列化一次会话布局和运行中的命令到缓存。即使服务器重启,zellij attach <session> 也能恢复窗格布局,命令会显示"Press ENTER to run..."避免误操作(文档)。tmux 本身没有这个能力。
Agent of Empires(2.4k stars)在 README 里写道:终端复用器已经成为 AI agent 的默认基础设施。这句话我认同——用 tmux 还是 Zellij,取决于哪个更顺手。
总结
三个场景对应三个不同层级的可靠性需求:
- 桌面持久化:合盖不丢
- SSH 可靠性:网络闪断不影响
- 跨设备接续:从台式机到手机切换
核心思路是让 agent 跑在服务器上,而不是跑在终端里。Zellij 不是必需品——tmux 也能做到大部分。如果日常是远程跑 AI coding agent,Zellij 的优点是开箱即用,不用额外配置。
One more thing
不熟悉 Zellij 的配置的话,装 opencode,让 AI agent 帮忙搞定:
opencode "帮我配置 Zellij,我想要 session 持久化和 Web 远程访问,配置过程中有什么不懂的我会直接问你"
我之前写过一篇 Zellij 和 tmux 的对比,里面覆盖了常用配置。
参考
- Zellij 官方文档 — Session Resurrection
- Zellij 官方文档 — Web Client / Remote Attach
- Zellij 官方 FAQ — 会话跨版本持久化
- Zellij GitHub Issues #5174 — SSH 重连时的 bug 报告
- Zellij GitHub Issues #5185 — SSH 会话 socket 文件确认
- OpenCode GitHub Issues #20953 — TUI SSH 下卡死
- OpenCode GitHub Issues #7790 — 请求 SSH 远程连接
- Claude Code Issues #61220 — /clear 无确认删除会话
- Claude Code Issues #61101 — Session 自动归档无法恢复
- HN 讨论 — Claude Code session 丢失
- HN 讨论 — tmux + Claude Code + Tailscale 持久化方案
- HN 讨论 — LXC + tmux + Claude Code "Close laptop. Come back."
- Blog — Claude Code On-The-Go:tmux + mosh 移动方案
- HN 讨论 — tmux 上 Claude Code 闪烁问题
- HN 讨论 — mosh + tmux 滚动冲突