HAPI 远程编程,多项目随时切换,并行多项目远程开发
需求是这样的:有时你有多个项目,想在远程编程时切换,但并不希望流程太复杂(比如在离开家之前,必须把所有可能用到的项目都先开启并配置好)。
最近我给 hapi 提了一个 Pull Request https://github.com/tiann/hapi/pull/526 ,可以在需要的时候随时开启远程编程。
当然这也一个限制:需要指定一个根目录。在该根目录下的所有文件夹,你都可以随时随地按需开启 Coding Agent 进行编程。
下面有两个方法:
方法一:如果你之前没有接触过 hapi,可以参考此方法。 方法二:如果你看过我的上一篇文章,并配置了自己的 Cloudflare Tunnel,可以看方法二。
更多的介绍可以参考文章后面。
方法 1
步骤1:
指定你想公开的一个文件夹(该文件夹用于存放各种各样的仓库) 你可以在任何时刻,随时在该文件夹下的任何一个仓库开始编程
hapi runner start --workspace-root=~/focus
步骤 2
hapi hub --relay
然后访问这个对应的 URL 就可以远程编程了
方法 2
如果你之前参考了之前的文章,想配置一个自己的 Cloudflare Tunnel,可以用这个已经配置好的 Cloudflare Tunnel,你可以参考这个步骤:
步骤1:
指定你想公开的一个文件夹(该文件夹用于存放各种各样的仓库) 你可以在任何时刻,随时在该文件夹下的任何一个仓库开始编程
hapi runner start --workspace-root=~/focus
步骤2
hapi server
步骤3
cloudflared tunnel run hapi
在这里浏览自己域名的 Cloudflare Tunnel 就可以这样看,可以选定任何一个文件夹点击右下角的 Start Session 开始远程编程。
背景
hapi 是一个本地优先(local-first)的 Claude Code / Codex / Cursor Agent / Gemini / OpenCode 远程控制框架。它的工作方式是:在你的工作机上跑一个 runner,把会话注册到 hub,然后通过 Web、PWA 或 Telegram Mini App 远程查看和操作。
之前在 /sessions/new 启动一个新会话时,"工作目录"这一项只有一个文本输入框,需要你手动键入完整路径(最近用过的几条会以 chips 形式出现,但仅此而已)。这意味着两件不太顺手的事:
要从手机或浏览器上启动会话,得记得目录的绝对路径; 没办法在 Web 端浏览工作机的目录结构,决定"今天进哪个仓库"。
PR #526 给 Web UI 加了一个工作区浏览器(Workspace Browser),并配套加了一个 --workspace-root 开关,把"可浏览的范围"明确收敛到你指定的那个根目录里。这个特性已经合入 v0.17.2,下面讲一下怎么用。
升级到 >=v0.17.2
https://hapi.run/docs/guide/quick-start
npm install -g @twsxtd/hapi --registry=https://registry.npmjs.org
快速上手:开启工作区浏览
特性是显式 opt-in 的。换句话说,不加 --workspace-root 就跟以前一样,加了才会出现新的 /browse 页面以及相关入口。
# 用 ~/code 作为工作区根目录
hapi runner start --workspace-root ~/code
# 也支持 = 形式
hapi runner start --workspace-root=~/code
# 也支持绝对路径
hapi runner start --workspace-root /Users/you/code
~ 和 ~/foo 在 shell 没有展开的情况下也会被自己展开,所以从配置文件、systemd unit 之类的地方传过来不用担心。
Web UI 的几个新入口
打开 Web 端,你会看到三个变化。
1. /sessions 顶部多了一个文件夹图标
会话侧栏的顶部加了一个文件夹小图标,点它跳转到 /browse。这是新功能最直接的入口。
2. /browse 页面:带 git 标记的目录树
/browse 页面会自动落到 --workspace-root 指定的目录,左侧是面包屑(最多回退到 root,再往上是禁止的),中间是这个目录下的子目录列表。每个条目都会做一次 git 仓库探测:如果一个目录下有 .git,列表里会带一个小标记,点进去后页面底部还会出现一个 "Start Session" 按钮,点它会跳到 /sessions/new 并自动把目录字段填好。
如果你的 root 下有十几个仓库,这个页面基本上就是个"项目清单"。
安全边界
工作区浏览的核心约束是"不能跑出 root 的范围"。这件事是在后端 RPC 层做的,前端再怎么造请求都绕不过:
list-directory拒绝任何不在 root 范围内的路径,返回 {success: false, error: "Path is outside workspace root"}。spawn-session同样校验 cwd —— 即使有人手搓 fetch,也无法在 root 之外起会话。 - 符号链接的 lexical bypass 已修
。早期实现只做字符串前缀判断,意味着如果 root 是 /safe、底下有一个软链/safe/out -> /etc,按字符串看/safe/out/passwd是"在 root 里",但 realpath 是/etc/passwd。Review 阶段把这个洞补上了:构造时对 root 做一次 realpath,每个进来的路径也走 realpath(spawn 目标如果还不存在,向上找最近一个存在的父目录解软链)再做包含判断。 v0.17.2 上线后又补了一条防御:没配 root 的机器, list-directoryRPC 直接拒绝。Web UI 本来就把 Browse 入口藏起来了,但后端不该假设前端永远靠谱。
小结
--workspace-root 不是一个会改变 hapi 默认行为的大改动,而是一个显式开关 + 一个新的 Web 页面。它适合两类场景:
你在工作机上有一个固定的 ~/code/~/work,常常需要从手机上挑一个仓库就开干;你把工作机暴露给了别人(团队共享、远程协作),希望明确声明"只有这棵子树是可访问的"。
如果都不是 —— 完全可以忽略这个特性,hapi 老的命令一字未变。
PR:tiann/hapi#526
Release:v0.17.2