codexpilot-desktop
v0.1.0
Published
CodexPilot desktop daemon for controlling Codex and Claude Code from iPhone.
Readme
CodexPilot — M0
iPhone 远程控制桌面上的 claude / codex / shell。
M0 范围:局域网 + Relay 公网连接 + Cloudflare 公网连接(临时 Quick Tunnel / 固定 Named Tunnel)+ PTY 双向流 + 二维码配对 + 暗/亮 + 中英双语。
RemoteCoding/
├── mac/ Go 写的 daemon / relay(命令行工具,启动后打印二维码)
│ ├── cmd/codexpilotd/ 入口
│ ├── cmd/codexpilot-relay/ Relay 服务端入口
│ ├── internal/server/ HTTP + WebSocket
│ ├── internal/relayclient/ 桌面端主动连接 Relay
│ ├── internal/relayhub/ Relay WebSocket 转发服务
│ ├── internal/ptybridge/ creack/pty 包装
│ ├── internal/discovery/ Bonjour _codexpilot._tcp
│ ├── internal/qr/ 终端二维码渲染
│ ├── internal/pair/ 一次性配对令牌
│ ├── install.sh 一键安装脚本
│ └── Makefile
└── ios/ SwiftUI App
├── project.yml XcodeGen 配置
├── Sources/
│ ├── App/ 入口、外观偏好
│ ├── Theme/ 设计令牌(颜色/字体/间距)
│ ├── Models/ PairedDevice / DeviceStore
│ ├── Networking/ LANBrowser / PTYSession
│ └── Views/ RootView / DeviceList / Scanner / Terminal / Settings
└── Resources/
├── Assets.xcassets 双外观色卡
├── en.lproj
└── zh-Hans.lprojMac 端 — 一键安装
正式用户路径是 npm 一键安装:
npm install -g codexpilot-desktop这条命令会安装/配置:
@openai/codex,并把codex链接到~/.codexpilot/bin/codex@anthropic-ai/claude-code,并把claude链接到~/.codexpilot/bin/claudecodexpilotd桌面端 daemon,默认安装到~/.codexpilot/bin/codexpilotd- 用户级 LaunchAgent:
app.codexpilot.daemon - 默认 Relay 公网连接:
https://relay.pandasroom.top
常用维护命令:
codexpilot doctor
codexpilot print-pairing
codexpilot install
codexpilot uninstall安装器内置 macOS arm64/x64 预编译 daemon,不需要用户安装 Go 或 Homebrew。已有 Node/npm 的机器通常 30 秒到 2 分钟完成;主要耗时来自下载 @openai/codex 和 @anthropic-ai/claude-code。
Apple Silicon 用户需要使用原生 arm64 Node。x64 Node/Rosetta 会被安装器拒绝,因为 Claude Code 官方 x64 native 包需要 AVX,Rosetta 不支持。
本地开发仍可直接运行脚本:
cd mac
bash install.sh脚本会:
- 检测 Go,没装就
brew install go go build出codexpilotd- 安装到
INSTALL_DIR,本地默认/usr/local/bin,npm 安装默认~/.codexpilot/bin - 安装用户级 LaunchAgent,让 daemon 在后台常驻运行
- 如果配置了 Relay,则连接 Relay 并打印公网二维码;否则自动启动 Cloudflare Quick Tunnel,并打印 5G 可用的公网二维码
使用托管 Relay(推荐正式产品路径):
cd mac
CODEXPILOT_RELAY_URL=https://relay.pandasroom.top bash install.shRelay 模式下,桌面端会主动连接 relay.pandasroom.top,用户电脑不需要安装 cloudflared,也不需要配置 Cloudflare Tunnel。
之后随时重新打印当前二维码:
codexpilotd -print-pairing调试时也可以手动前台启动:
codexpilotd # 默认 7681 端口 + 自动选取局域网 IP + 启动公网临时隧道
codexpilotd -port 7681 # 指定端口
codexpilotd -relay-url https://relay.pandasroom.top # 主动连接 Relay
codexpilotd -public=false # 只启用局域网,不启动 Cloudflare
codexpilotd -no-qr # 不渲染 QR(CI / 调试)后台日志在:
~/.codexpilot/codexpilotd.log二维码内容是个 codexpilot://pair?... URL。固定域名模式下,一个二维码会同时包含 LAN endpoint 和公网 endpoint;iOS 会优先尝试局域网,失败后自动切到公网。
Relay 公网连接(推荐)
Relay 模式把公网入口从“每台用户电脑一个 Cloudflare Tunnel”改成“桌面端主动连产品方 Relay”。
iPhone -> https/wss://relay.pandasroom.top/v1/...
Relay -> 已连接的桌面端 WebSocket
Desktop -> http/ws://127.0.0.1:<port>/v1/...桌面端启动:
codexpilotd -relay-url https://relay.pandasroom.topRelay 会用配对 token 把 iPhone 请求路由到对应桌面端。iPhone 仍然调用原来的 /v1/health、/v1/codex/sessions、/v1/pty,所以现有 App 不需要先重写协议。
当前配对体验仍然是“用户只扫码一次”。区别在于:
- iPhone App 扫码后会静默生成本机设备密钥,并自动调用
/v1/pair/register完成可信设备注册。 - 注册完成后,后续
/v1/codex/*和/v1/pty请求除了带 token 之外,还必须带设备 ID、时间戳、随机 nonce 和签名。 - 一旦某台设备完成首个可信注册,只有持有该设备私钥的 App 安装实例才能继续访问;单独拿到二维码里的 token 已经不够。
本地验证 Relay:
cd mac
make build-all
./codexpilot-relay -addr 127.0.0.1:9000
codexpilotd -relay-url http://127.0.0.1:9000
curl http://127.0.0.1:9000/health服务器部署时建议用 Caddy 反向代理:
relay.pandasroom.top {
reverse_proxy 127.0.0.1:9000
}公网只开放 80/443,Relay 进程只监听本机 127.0.0.1:9000。
当前 Relay 仍使用 token 做路由,但业务接口已经切到“token + 设备签名”双层校验。正式 App Store 多用户版本仍建议继续加入端到端加密、短期配对会话、可信设备恢复、设备撤销和 APNs 任务完成通知。
5G / 公网连接
无需自己的域名。安装脚本会安装并启动 cloudflared,daemon 会创建一个 Cloudflare Quick Tunnel 临时域名,例如:
https://xxxxx.trycloudflare.com终端会显示一个二维码:
Smart QR:同时包含 LAN 和公网地址,iPhone 会自动选择当前可用路线。
Cloudflare Quick Tunnel 的域名是临时的;daemon 停止或隧道重建后,需要重新扫描新的 Public QR。daemon 会定期检查公网健康状态,发现临时隧道失效后会自动申请新域名,并在终端重新打印新的 Public QR。
M0 的 token 会保存在
~/.codexpilot/pairing-token,但公网临时域名会随 Cloudflare Quick Tunnel 重建而变化。M1 会接 Noise IK + 一次性 token。
使用自己的 Cloudflare 域名(pandasroom.top)
如果域名已经托管在 Cloudflare,可以配置固定公网地址,不再使用 trycloudflare.com 临时域名:
cd mac
bash setup_cloudflare_named_tunnel.sh pandasroom.top默认会创建并使用:
https://codexpilot.pandasroom.top脚本会:
- 检查/安装
cloudflared - 引导登录 Cloudflare(只需第一次)
- 创建或复用 Named Tunnel
- 给
codexpilot.pandasroom.top创建 DNS 路由 - 安装
cloudflared用户级后台服务 - 重新安装 CodexPilot daemon,并写入固定公网域名
- 打印唯一可长期使用的 Smart QR
自定义子域名:
CODEXPILOT_PUBLIC_HOST=mac-mini.pandasroom.top bash setup_cloudflare_named_tunnel.sh pandasroom.top固定域名模式下,Mac 重启或终端退出后不需要重新扫码;只要后台服务正常,iPhone 会继续连接同一个域名。
iOS 端 — 生成 Xcode 工程
需要一次性安装 XcodeGen:
brew install xcodegen生成 + 打开工程:
cd ios
xcodegen generate
open CodexPilot.xcodeproj首次构建 Xcode 会自动拉 SwiftTerm 这个 SwiftPM 依赖。
权限:
- 相机(扫二维码)
- 本地网络(连 Mac 上的 daemon)
两者在 Resources/Info.plist 已经配好用途文案。
暗 / 亮
App顶层preferredColorScheme跟随用户偏好(设置 → 外观)- 所有颜色都来自
Resources/Assets.xcassets,每色双值,深色模式默认 OLED 纯黑 - 字体:UI 用系统默认,所有代码 / 状态字段全部
monospaced
i18n
- 字符串集中在
Resources/{en,zh-Hans}.lproj/Localizable.strings - 增加新语言只需新建一个
<lang>.lproj/Localizable.strings,并在project.yml的CFBundleLocalizations里加一项
协议(M0)
WebSocket:ws://<host>:<port>/v1/pty?token=<base64url>&cmd=<base64url> 或 wss://<trycloudflare-host>/v1/pty?token=<base64url>&cmd=<base64url>
| 方向 | 帧类型 | 含义 |
|---|---|---|
| iOS → Mac | binary | stdin 字节,原样写到 PTY |
| Mac → iOS | binary | stdout 字节,原样喂给 SwiftTerm |
| iOS → Mac | text | {"type":"resize","cols":120,"rows":40} |
| Mac → iOS | text | {"type":"hello",…} 或 {"type":"exit","code":N} |
Mac 每 25 秒发一次 WS Ping,给 NAT 和 Cloudflare Edge 留心跳余地。
允许的 cmd[0](白名单):claude / codex / bash / zsh / sh / fish。
交互式 Codex/Claude Code 不在 daemon 内部复刻子命令,而是用 PTY 原样运行真实 CLI,所以 codex ... 和 claude ... 的全部 flags、子命令、登录流程、TUI 和键盘交互都由官方 CLI 自己处理。
非交互式任务 API:
GET /v1/cli/tools:检查codex/claude是否在 daemon PATH 中可用,并返回版本或错误。POST /v1/cli/tasks:按完整 argv 异步运行codex或claude,例如{"argv":["claude","-p","summarize this repo"],"cwd":"/Users/me/project"}。GET /v1/cli/tasks/<id>:查询任务输出和状态。
下一步(M1 预告,本次不实现)
- Noise IK 端到端加密 + 一次性配对 token
- 会话历史(直接读
~/.claude/projects/*.jsonl) - Cloudflare Tunnel 固定域名 + Access 登录保护
- APNs 任务完成通知
- Git 抽屉 + diff
