
porterminal v1.0.5
快速简陋的网页/MCP终端隧道,连接你的手机和电脑
把电脑交给智能体,完全掌控,然后看着它工作。
一条命令,一个 URL。(同时也是你自己手机上的一个炫酷终端。)
1. uvx ptn
2. 将 URL 交给 AI 智能体,或自己扫码
3. 在任何浏览器中观看它工作,并随时接管
[!WARNING] 那个完整 URL 就是这台电脑的完全访问权限。 它包含一个每次启动随机生成的访问码,任何你把它交给的人(或任何 AI 智能体)都能在你的机器上获得真正的 shell。请将 URL 和二维码视为机密,只分享给你信任的人和智能体,并在将 Porterminal 用于任何重要内容之前阅读安全。
为什么
我需要一种极其简单的方式来远程访问计算机。
ngrok 需要注册,而且免费版体验不佳。Cloudflare Tunnel 是出色的管道,但单独使用它只给你一条隧道,而不是一个适合手机的终端。Tailscale 当你两端都归自己所有时很棒,但仍然意味着要把设备加入私有网络。Termius 需要复杂的设置:端口转发、防火墙规则、密钥管理……
所以我构建了一个更简单的东西:运行一条命令,扫描二维码,开始输入。
然后我恍然大悟:同样的技巧(一条命令,一个 URL)也是给 AI 智能体在任何计算机上提供真正终端的最简单方式。无需编写 MCP 服务器,无需 SSH 密钥,无需 Docker,无需配置。运行 uvx ptn,递出 URL,智能体就在那台机器上运行命令、读取屏幕、回答问题。而且因为它是 Web 终端,你可以在任何浏览器中打开同一个会话实时观看它工作,或者抓起键盘接管。
功能
- 把电脑交给智能体,完全掌控,然后看着它工作 — 将 URL 给 AI 智能体,它就能通过 MCP 或纯 REST 在这台机器上获得真正的终端。在任何浏览器中打开同一个会话即可实时观看它工作,并且随时可以抓起键盘接管。无需密钥,无需 Docker。智能体通过
<url>/llms.txt和<url>/.well-known/mcp.json了解用法。参见智能体访问。 - 一条命令,即时访问 —
uvx ptn,你(或智能体)就能在这台机器上获得真正的终端。无需 SSH、无需端口转发、无需配置文件。Cloudflare 隧道 + 二维码。 - 在手机上真正可用 — 针对触控优化,支持动量滚动、双指缩放、滑动手势,以及修饰键(Ctrl、Alt)。
- 完整的终端应用支持 — vim、htop、less、tmux 均能正常工作,并正确处理备用屏幕缓冲区。
- 持久的多标签会话 — 会话在断开后依然保留。关闭浏览器、切换网络、从另一台设备重新连接,你的 shell 和正在运行的程序仍然在那里。你和智能体可以共享一个会话:看着它工作,或者接管。
- 跨平台 — Windows(PowerShell、CMD、WSL)、Linux/macOS(Bash、Zsh、Fish、Nushell,以及通过
$SHELL指定的任意 shell)。自动检测你的 shell。 - 默认难以猜测 — 每次启动都会添加一个独立的 128 位随机访问路径。仅隧道主机名和所有错误路径都返回 404。URL 在屏幕上隐藏,但二维码包含完整凭据,因此请对两者保密。按
c复制智能体说明和 URL,或按u仅复制 URL。
安装
| 方法 | 安装 | 更新 |
|---|---|---|
| uvx(无需安装) | uvx ptn | uvx ptn@latest |
| uv tool | uv tool install ptn | uv tool upgrade ptn |
| pipx | pipx install ptn | pipx upgrade ptn |
| pip | pip install ptn | pip install -U ptn |
一行安装(uv + ptn):
| 操作系统 | 命令 |
|---|---|
| Windows | powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/lyehe/porterminal/master/install.ps1 | iex" |
| macOS/Linux | curl -LsSf https://raw.githubusercontent.com/lyehe/porterminal/master/install.sh | sh |
需要 Python 3.12+ 和 cloudflared(如果缺失会自动安装)。
用法
ptn # Start in current directory
ptn ~/projects/myapp # Start in specific folder
| 参数 | 说明 |
|---|---|
-n, --no-tunnel | 仅本地网络(不建立 Cloudflare 隧道) |
-b, --background | 后台运行并立即返回 |
-p, --password | 提示输入密码以保护此会话 |
-sp, --save-password | 在配置中保存或清除密码 |
-tp, --toggle-password | 设置密码要求(开/关/切换) |
-v, --verbose | 显示详细启动日志 |
-i, --init | 创建 .ptn/ptn.yaml,将自动发现的项目脚本作为按钮 |
-if, --init-from URL/PATH | 从 URL 或本地文件创建 .ptn/ptn.yaml |
-c, --compose | 默认启用 compose 模式 |
-k, --keep-qr | 首次连接后保持二维码可见 |
-u, --check-update | 检查是否有新版本 |
-V, --version | 显示版本 |
运行期间: 隧道启用时,连接 URL 会出于隐私在屏幕上隐藏。按 c 复制智能体说明和 URL,包括 /mcp、/api/agent/run 和 /llms.txt;按 u 仅复制 URL;或扫描二维码进行连接。Ctrl+C 停止服务器。
Agent access (MCP + REST)
同一个 URL 也适用于 AI 智能体。支持 MCP 的客户端可以使用 <url>/mcp(Streamable HTTP)获得原生类型化工具。无法注册 MCP 服务器的智能体可以使用 <url>/api/agent/run 上的 REST 回退,通过普通 HTTP 请求。无论哪种方式都会创建一个持久的智能体 shell,显示为 🤖 标签页,你可以在手机上观看并接管。
将完整生成的 URL(包含其访问码)交给智能体。MCP 客户端可以从 <url>/.well-known/mcp.json(MCP server.json 描述符)自动发现服务器,另外还有一个人/智能体可读的 <url>/llms.txt,包含用法说明。基础页面还为浏览器驱动型智能体提供了无障碍可见的提示,而人类 UI 保持紧凑。示例客户端配置:
{
"mcpServers": {
"porterminal": { "url": "https://<your-tunnel>.trycloudflare.com/<access-code>/mcp" }
}
}
MCP 工具:run_command(干净输出 + 退出码)、read_screen、send_keys、send_signal(Ctrl-C / EOF)。
REST 回退:
curl -s -X POST https://<your-tunnel>.trycloudflare.com/<access-code>/api/agent/run \
-H "content-type: application/json" \
-d '{"command":"echo hello","timeout":30}'
响应中包含一个 session_id;可将其与 <url>/api/agent/screen、<url>/api/agent/keys、<url>/api/agent/signal 以及 DELETE <url>/api/agent/session 一起复用。
当你在手机上打开 Porterminal 时,右上角的复制按钮会复制同样的智能体分享文本。仅支持浏览器的智能体在基础页面上也有一个回退方案:一个可通过 DOM 读取的 终端屏幕 镜像,以及一个标记清晰的 终端输入。
安全:
<url>表示完整生成的 URL,包括其随机访问码。仅隧道主机名不暴露任何内容,但任何拥有完整 URL 的人(或智能体)都能获得完整的、未提升权限的 shell 访问。参见 docs/agent-access.md。
移动端手势
| 手势 | 操作 |
|---|---|
| 轻点 | 聚焦终端,清除选择 |
| 长按 | 开始文本选择 |
| 双击 | 选择单词 |
| 左右滑动 | 方向键(← →) |
| 滚动 | 带物理效果的动量滚动 |
| 双指缩放 | 缩放文本(10-24px) |
修饰键(Ctrl、Alt、Shift):点按一次为粘滞(单次按键),双击为锁定。
编写模式(▤ 按钮):切换出一个文本输入框,你可以输入或语音转文字,借助完整的移动端编辑功能(自动更正、建议、光标定位)编辑文本,然后发送到终端。适合较长的命令或语音输入。
配置
运行 ptn --init 创建一份入门配置。它会自动从 package.json、pyproject.toml 或 Makefile 中发现项目脚本,并将它们添加为按钮:
ptn -i
# Created: .ptn/ptn.yaml
# Discovered 3 project script(s): build, dev, test
或者手动创建 ptn.yaml:
# Terminal settings
terminal:
default_shell: nu # Default shell ID
shells: # Custom shell definitions
- id: nu
name: Nushell
command: nu
args: []
# Custom buttons (appear in toolbar)
# row: 1 = default row, 2+ = additional rows
buttons:
- label: "claude"
send:
- "claude"
- 100 # delay in ms
- "\r"
- label: "build"
send: "npm run build\r"
row: 2 # second button row
# Update checker settings
update:
notify_on_startup: true # Show update notification
check_interval: 86400 # Seconds between checks (default: 24h)
# Security settings
security:
require_password: true # Always require password at startup
password_hash: "" # Saved password hash (use ptn -sp to set)
max_auth_attempts: 5 # Max failed attempts before disconnect
配置文件的搜索顺序:$PORTERMINAL_CONFIG_PATH、./ptn.yaml、./.ptn/ptn.yaml、~/.ptn/ptn.yaml。
Security
每次启动都会创建一个新的 128 位随机路径,例如
https://<tunnel>.trycloudflare.com/<access-code>/。所有浏览器、WebSocket、
MCP、REST、健康检查和静态路由都必须使用该确切前缀;不带路径的主机
和错误路径返回 404。这使得暴力破解已发现的隧道主机名
不切实际。
完整生成的 URL 仍然是一种持有者凭据:任何获得它的人 都拥有 shell 访问权限。如果泄露,请重启 Porterminal 以轮换访问码。可选 密码为浏览器 WebSocket 添加了身份验证,但 MCP 和 REST 仍然信任完整 URL,因此智能体可以使用单链接工作流。
浏览器会在限定于该完整启动 URL 的明文存储中记住成功的密码。 在同一源上为更新的启动保存密码会使旧的 Porterminal 密码条目失效; 清除或拒绝已记住的密码会全部移除,且不影响其他浏览器存储。 因此, 同一源上的并发启动可能会再次提示,而已通过身份验证的连接仍保持连接。
从界面操作: 打开设置(齿轮图标),使用“Security”部分设置/更改密码并切换密码要求。更改需要重启服务器。
从命令行操作:
# One-time password (prompt each session)
ptn -p
# Save password to config (no prompt needed)
ptn -sp
# Password: ****
# Confirm password: ****
# Clear saved password (enter empty password)
ptn -sp
# Password: [press Enter]
# Set or toggle password requirement
ptn -tp # Toggle on/off
详见 docs/security.md。
故障排查
连接失败? 请使用完整生成的 URL,包括其访问码。Cloudflare 隧道问题也可以通过重启服务器(Ctrl+C,然后 ptn)来获得新的隧道和访问路径。
uvx ptn 仍然运行旧版本? 已安装的 uv tool 可能会优先。请运行 uv tool upgrade ptn,或使用 uvx --isolated ptn@latest 绕过已安装的工具。
未检测到 shell? 请设置 $SHELL 环境变量,或在 ptn.yaml 中配置 shell。
参与贡献
本项目不接受外部贡献(拉取请求或代码更改),出于安全原因(见 CONTRIBUTING.md)。欢迎你 fork 并根据 AGPL-3.0 运行自己的副本。
从源码运行:
git clone https://github.com/lyehe/porterminal
cd porterminal
uv sync --frozen
uv run --frozen ptn