把 AI 编码会话带到手机前,先划清主机权限边界:Relay 的自托管远程协作实践
AI 编码 Agent 跑在开发机上,人的注意力却不总在开发机旁边。长任务执行到需要确认、测试失败需要看日志、多个会话要交接时,最常见的补救是把终端暴露到公网,或把项目目录同步到第三方服务。前者扩大了 shell 与凭据的攻击面,后者又把源码和 Agent 上下文带出了原本受控的机器。
Relay 选择另一条路径:它是一个 MIT 许可的自托管远程控制台。Node.js 后端与项目、CLI 凭据一起留在你自己的电脑上;Flutter 客户端可以在手机、Web 和桌面端连接它。它当前以 Claude Code 与 Codex 为主要集成,OpenCode 与 Hermes 则标为实验性、由主机自行管理的集成。这里的重点不是“从手机运行一个 Agent”,而是把远程观察、会话延续和有限的文件/终端操作放进明确的身份与权限边界里。
先理解部署模型:客户端不等于新的执行环境
Relay 的结构很简单,但安全语义不能省略:客户端通过认证的 HTTP 与 SSE 连接后端;后端再调用本机的 Agent CLI,并在文件系统策略范围内读写项目。会话以 workdir + agent + session 为作用域,因此同一台机器可以并行维护不同项目、不同 Agent 的可恢复对话,而不是共享一个全局工作目录。
这意味着手机端看到的是控制面,而不是把 Agent 或代码“迁移”到手机。Agent 进程仍以运行后端的操作系统用户权限执行,Claude/Codex 的登录态也留在该主机上。官方文档特别提醒:Relay 不是沙箱。如果后端用户能读取生产密钥、能执行部署命令,远程发出的同类操作仍然拥有这些能力。不要因为 UI 多了一层,就误以为权限被自动收紧。
比较稳妥的做法是为 Relay 单独创建非 root 用户,只给它项目目录和必要的 CLI 凭据;把生产部署、云账号管理和个人 SSH 主目录与其分离。这样,即使某个远程凭据需要吊销,影响面也不会等同于整台开发机。
安装前先选网络路径,而不是先打开端口
项目为 Linux、macOS 和 Windows 提供不同的后端安装入口。Linux 主机上的官方安装命令是:
./backends/linux/setup.sh
安装向导会引导选择直连、命名 Cloudflare Tunnel 或临时 Quick Tunnel。无论选哪一种,公开访问前都应先启用 HTTPS;不要为了临时从手机查看任务,就把未认证的本地服务直接映射到公网。Linux 后端还需要 Node.js 18+、至少一个已登录的受支持 CLI,以及文档列出的 PM2 和原生工具;下载文件夹时 Unix 主机还需要 zip。
网络方案的取舍应由使用场景决定。只在可信内网使用时,最小化监听范围通常更重要;确实需要外网访问时,使用有身份验证和 TLS 终止的通道,再配合访问日志与撤销流程。把“能连上”当成部署完成,是远程开发工具最危险的验收标准之一。
设备凭据应按设备拆分,并准备撤销动作
安装完成后,Relay 会在 server/credentials/ 下生成 .relay.png 与 .relay.json,用于导入设备凭据。客户端支持扫描、导入文件或粘贴 JSON,再由用户输入口令完成导入。官方建议每台设备使用独立、可撤销的凭据;这是比“全家共享一个二维码”更值得坚持的操作习惯。
该设计并不是只把 token 放进一个配置文件。文档说明,凭据导出使用 PBKDF2-HMAC-SHA256 与 AES-256-GCM;每个 HTTP API 路由要求可撤销的 bearer token,失败尝试会被限速。终端连接不会把长期 token 放进 WebSocket URL,而是先换取短时、一次性的 WebSocket ticket。它们并不能取代系统更新、强口令或设备锁屏,但减少了令牌被 URL、代理日志或截图意外泄露的机会。
实际落地时可建立一张简单的设备清单:凭据对应谁、哪台设备、允许什么网络入口、最后使用时间,以及遗失设备后的撤销责任人。远程控制系统的安全性,经常不是败在加密算法,而是败在不知道哪一个旧手机还保有访问权。
文件和终端:允许路径比“全盘可见”更重要
Relay 提供项目文件浏览、上传下载、工作目录切换和可恢复 PTY,但这些能力应视为高权限操作。项目默认会拒绝若干 Relay、SSH、Claude 与 Codex 的已知机密路径,并可用 RELAY_FS_ROOTS 进一步限制文件 API 可触及的根目录。实践中不该只依赖默认拒绝列表:为每个后端实例明确设置允许的项目根目录,避免把整个 home 目录作为工作区。
例如,可在运行服务的环境中把访问面缩到两个实际项目路径:
export RELAY_FS_ROOTS="/srv/relay/projects/app-a:/srv/relay/projects/app-b"
这不是 Relay 的“沙箱开关”,而是一道文件 API 的边界。Agent 子进程、终端进程本身仍受后端 OS 用户权限约束。因此应同时检查服务账户的 Unix 权限、挂载的共享目录、SSH agent 转发,以及 CI/CD 凭据是否意外继承到该账户。尤其不要把生产 kubeconfig、云访问密钥与日常编码工作区放在同一个无差别可读的位置。
用会话范围管理协作,不要把多个任务塞进一个对话
Relay 的强项是持续会话和跨端查看:可以流式接收回复、取消当前轮次、搜索历史、导出 Markdown,并把同一 workdir + agent 下的对话命名和恢复。多 Agent Swarm 则允许共享记录、设置角色、分波次并行和有限的 @mention 交接。
但持续性也会放大上下文污染的风险。推荐把“排查线上告警”“实现一个功能”“清理依赖”分为独立会话;进入新任务时先复述允许修改的目录、禁止操作的资源与验收命令。远程端只负责观察和批准时,应避免开放交互式 shell;确实要使用 PTY 时,把它视为一次显式授权,而不是聊天窗口的自然延伸。
一个可操作的验收流程是:先在隔离项目中部署后端;用一台测试手机导入独立凭据;确认它只能访问 RELAY_FS_ROOTS 下的目录;启动一个无敏感凭据的 Agent 会话;最后撤销该设备凭据并验证旧客户端无法再调用 API。只有“接入、使用、撤销”三个步骤都演练过,远程协作才不只是方便的演示。
故障与运维:优先保住主机,再恢复体验
远程端出现“看得到但不能继续”的情况时,不要急着重装客户端或重新导入所有凭据。先在后端确认 Node 服务是否存活、CLI 是否仍处于已登录状态、所选 workdir 是否还在允许路径内;再从浏览器或另一台受控设备验证同一凭据。这样可以区分网络隧道故障、服务进程故障、主机 CLI 授权过期和文件策略拒绝,避免把权限问题误诊成聊天问题。
生产化部署还应把日志和升级纳入固定节奏:记录服务启动、凭据创建与撤销、隧道配置变更和失败认证;升级 Relay、Node.js 或 Agent CLI 前,先在非生产项目跑一次连接与撤销测试。README 也提示部分桌面打包和安全存储验证仍不如已演练的平台成熟,因此跨平台客户端不应自动获得与主力环境同等的信任等级。发生设备遗失或怀疑令牌泄露时,优先撤销对应设备凭据、检查后端访问记录,必要时轮换主机上的上游 CLI 登录态,而不是继续沿用可能暴露的长期访问路径。
Relay 适合希望把 Agent 工作保留在自有机器、又需要跨设备跟进长任务的团队或个人。它不适合用来绕过主机隔离、把个人开发机直接当生产跳板,或在没有网络、账户和目录治理的情况下开放终端。远程控制让等待更少,但不能替你决定什么权限本来就不该交给 Agent。