$ cat ~/map/pi-remote.md
pi-remote
手机遥控 pi:单个 Python 进程封装 pi --mode rpc,自托管、面向原生 Windows。
tools✓ 9月15日
事实速查
- GitHub Stars
- ★ 10
- Forks
- 0
- 许可证
- MIT
- npm / 月
- —
- 最后推送
- 2026年10月11日
安装
pip install -r requirements.txt,在仓库目录运行 python pi_web_bridge.py(static 文件夹须与脚本同在),然后在浏览器打开该机器的 8770 端口(走 Tailscale 时用 tailnet 主机名)## 速览
pi 编码代理的自托管遥控方案:一个 Python 桥接进程封装 pi --mode rpc,经 tailnet 向手机友好的网页端提供服务,为原生 Windows 而生,链路上没有中继也没有第三方。
## 要点
- $架构:浏览器经 WebSocket 连到 pi_web_bridge.py,后者拉起 pi --mode rpc 并独占其 stdin 与 stdout(JSONL 通信);agent 事件回流成页面消息,prompt、steer、abort 命令反向发出,prompt 与 steer 还可为支持视觉的模型附带图片。
- $存在理由:README 的对比表逐一指出 pi-web 只能在 WSL 运行、remote-pi 依赖中继、pi-remote-control 走托管中继、Telegram 桥接会让转录离开本机;这个桥接让一切留在自己的机器上,并为 Windows(启动文件夹、任务计划程序——用 NSSM 或 pywin32 装成真正的服务也有文档,但作者不推荐)、Linux(systemd user service)与 macOS(launchd)各写了开机自启方案。
- $推荐拓扑:一台常开 Linux 机器用 llama.cpp 经 HTTP 提供本地模型,代码所在的 Windows PC 运行 pi 与桥接,手机作为瘦客户端经 Tailscale 接入——全部塞进一台机器也可以,推理端点可以是任何 OpenAI 兼容服务。
- $安全模型:token 永远必需(未设 PI_WEB_TOKEN 时启动即生成一个;设为 off 则桥接降为只读,在服务端拒绝 prompt、shell 与打开项目,而不是仅禁用按钮);WebSocket 校验 Origin,页面带严格 CSP、nosniff 与 no-referrer,token 比较用常数时间——它仍是单用户工具,端口必须留在 tailnet 内。
- $权限:pi 自身不带权限提示,提示由 guardrails 扩展提供,而 RPC 通道上只有四种标准对话框(select、confirm、input、editor)能到达浏览器——用 ctx.ui.custom() 画界面的扩展只会拿到 undefined,桥接既看不到也无法应答;推荐安装 pi-guardrails 并关掉其 pathAccess 功能,因为该防护的提示正是用 ctx.ui.custom() 绘制,否则工作目录之外的文件访问会被静默拒绝。
- $项目即 PC 上的工作目录,pi 既有会话存于其中;转录经 pi 自身的 get_messages 重建,历史就是磁盘上的会话而非内存副本;移除会话只是把 jsonl 文件挪到旁边的 _trash 文件夹——pi 在 RPC 上没有删除操作。
- $其余:二十三个斜杠命令随输入过滤(/bash 完全绕过模型与 guardrails;/restart 借进程树之外的一次性计划任务重启桥接),Functions 页提供显示思考、回复建议、停止时摘要、本地通知与平滑生成五个开关,经 tailscale serve 获得 HTTPS 后可装成 PWA,fake_pi.py 测试替身让全套功能在无模型、无头 Chrome 下可验证。
## 常见问题
Q 浏览器能接管已经在终端里运行的 pi 会话吗?
不能——一个进程只有一个 stdin,桥接会自己拉起 pi --mode rpc。真正共享的是磁盘上的会话文件:终端里开的会话可以在浏览器里接着用,反过来也一样,同一时刻只有一个写入方。
Q 有了 token,把端口暴露到公网安全吗?
不安全。README 的警告写得很明白:这是单用户工具,任何能到达端口并持有 token 的人都能在你机器上执行命令——没有沙箱。端口务必留在 tailnet 内。
Q 为什么 pi-guardrails 的文件访问提示从来不见弹出?
该防护用 ctx.ui.custom() 画提示,而这个调用在 RPC 上不存在——返回 undefined 后被当作拒绝,工作目录之外的每次访问都被静默驳回。在 guardrails.json 里关掉这一项功能(pathAccess 设为 false)或把它的 mode 改成 allow 即可;命令拦截不受影响,因为它用的是 select。
## 参考链接
## 相关条目
## 教程
最后更新: 2026年9月15日