























Expose your local terminal to a public IP for remote control from a browser.
把本地终端通过公网中继暴露给浏览器,让你离开电脑后仍能用手机操作本地的命令行工具(如 Claude Code、vim、tmux 等)。
手机浏览器 公网 VPS 本地电脑
┌──────────┐ ┌──────────┐ ┌──────────┐
│ xterm.js│ WSS │ │ WSS out │ │
│ Web UI │◄───────►│ Relay │◄───────────│ Agent │
└──────────┘ └──────────┘ └────┬─────┘
│
┌───────┴──────┐
│ tmux 会话们 │
└──────────────┘
关键设计:tmux 是终端的"持久化层",会话独立于任何网络连接。浏览器关了、网络抖了,会话不丢;只有 Agent 进程死了会话才消失。
brew install tmux,Linux:apt/dnf install tmux)curl -fsSL https://raw.githubusercontent.com/iannil/terminal-hole/main/scripts/install.sh | sh
装特定版本:
curl -fsSL https://raw.githubusercontent.com/iannil/terminal-hole/main/scripts/install.sh | sh -s -- --version v0.1.0
装到自定义路径:
curl -fsSL https://raw.githubusercontent.com/iannil/terminal-hole/main/scripts/install.sh | sh -s -- --install-dir /opt/bin
行为:
/usr/local/bin,普通用户装到 ~/.local/bin(并提示加 PATH)checksums.txt# 首次初始化配置(交互式,写入 ./config/config.yaml)
docker run --rm -it \
-v "$PWD/config:/etc/terminal-hole" \
ghcr.io/iannil/terminal-hole-relay:latest init --mode relay
# 启动 Relay
docker run -d --name terminal-hole-relay \
-p 443:443 -p 80:80 \
-v "$PWD/config:/etc/terminal-hole" \
-v "$PWD/state:/var/lib/terminal-hole" \
ghcr.io/iannil/terminal-hole-relay:latest
镜像 tag:v0.1.0(精确版本)、0.1(小版本滚动)、latest(最新)。
注意:
-v state 卷保留 ACME 证书缓存和 signer secret;丢了 → 浏览器 cookie 全失效,要重新登录git clone https://github.com/iannil/terminal-hole.git
cd terminal-hole
go build -o terminal-hole ./cmd/terminal-hole
需要 Go 1.25+。跑测试还需本机装 tmux。
# 交互式初始化(生成 /etc/terminal-hole/config.yaml)
sudo ./terminal-hole init --mode relay
# > 域名? tp.example.com
# > 管理员账号? alice
# > 管理员密码?
# 启动(前台;生产可用 systemd 包装)
sudo ./terminal-hole relay
Relay 会:
:443 上跑 HTTPS,用 Let's Encrypt 自动签证书:80 上跑 HTTP→HTTPS 重定向(可在 config 用 http_listen: "-" 禁用)wss://tp.example.com/agent-tunnel)signer.key,重启后浏览器 cookie 不失效DNS:先把域名 A/AAAA 记录指向 VPS,再启动 Relay(ACME 签证书时要验签)。
# 交互式初始化(生成 ~/.config/terminal-hole/config.yaml)
./terminal-hole init
# > 选择密码存储方式:
# 1) 明文存 config(0600 权限)
# 2) password_file(自己创建文件,config 引用路径)
# 3) TH_AGENT_PASSWORD 环境变量(config 不存密码)
# > 中继地址? https://tp.example.com
# > 账号? alice
# > [根据选择] 输入密码 / 文件路径
# 启动
./terminal-hole agent
Agent 启动后会:
0.0.0.0:7777 起本地 Web 终端(局域网设备也能访问,需账号密码)https://tp.example.com,输入账号密码登录claude、vim、htop 等命令,跟本地操作一致手机键盘:界面底部有特殊键面板(Esc / Tab / Ctrl / Alt / 方向键 / / / - / Enter / Backspace)。Ctrl/Alt 是修饰键,点一下高亮,下次输入组合生效。仅在触摸设备显示。
多端共享:tmux 原生支持多客户端 attach,手机和电脑可同时看同一个会话。
Agent 掉线自动恢复:浏览器订阅 /api/agent-status SSE,Agent 重连后自动刷新会话清单并重 attach 当前会话。
~/.config/terminal-hole/config.yaml)agent:
relay:
url: https://tp.example.com
username: alice
password: "secret" # 或 password_file / TH_AGENT_PASSWORD
local:
bind: 0.0.0.0:7777 # 默认值;改 127.0.0.1 可限制只 loopback 访问
shell: /bin/zsh # 默认从 $SHELL 推断
tmux_prefix: th- # Agent 管理的 tmux 会话前缀
/etc/terminal-hole/config.yaml)relay:
domain: tp.example.com
listen: ":443"
http_listen: ":80" # 设为 "-" 禁用 HTTP 重定向
acme_cache_dir: /var/lib/terminal-hole/certs
signer_secret_file: /var/lib/terminal-hole/signer.key
allowed_origins: # WS origin allowlist;空则走同源策略
- https://tp.example.com
# 自带证书模式(与 domain/ACME 二选一):
# cert_file: /path/fullchain.pem
# key_file: /path/privkey.pem
accounts:
- username: alice
password_hash: "$2a$10$..." # bcrypt,init 自动生成
配置优先级:CLI flags > 环境变量(TH_* 前缀)> config 文件 > 默认值
/api/login 5 次/IP/分钟,/agent-tunnel 10 次/IP/分钟,超限 429relay.allowed_origins 做纵深防御 CSRF已知限制(v1):
password_file 或 TH_AGENT_PASSWORD 替代)terminal-hole init [--mode agent|relay] [--config PATH] # 交互式生成 config
terminal-hole agent [--config PATH] [--bind ADDR] # 跑 Agent
terminal-hole relay [--config PATH] # 跑 Relay
terminal-hole version # 打印版本
terminal-hole help # 帮助
详见 docs/design.md(完整设计)和 docs/superpowers/plans/(实现计划)。
# 跑测试(需要本机装 tmux)
tmux kill-server 2>/dev/null; sleep 1
go test ./... -race
# 构建
go build -o terminal-hole ./cmd/terminal-hole
# 跑 vet
go vet ./...
项目结构:
cmd/terminal-hole/ 入口
internal/agent/ Agent(管理 tmux、本地 HTTP、隧道客户端)
internal/relay/ Relay(HTTPS、登录、限流、SSE、代理)
internal/tunnel/ yamux 多路复用隧道
internal/tmux/ tmux wrapper
internal/pty/ creack/pty 封装
internal/auth/ bcrypt + HMAC cookie + 中间件
internal/config/ AgentConfig YAML
internal/protocol/ WS 控制消息
internal/web/ 嵌入式静态资源 + 登录端点
internal/version/ ldflags 版本信息
internal/web/assets/ 前端源码(HTML/CSS/JS + vendor xterm.js)
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。