内容
<p align="center">
<a href="https://github.com/lyehe/porterminal">
<img src="assets/banner.jpg" alt="Porterminal - 任意地点控制你的电脑" width="600">
</a>
</p>
<p align="center">
<a href="https://pypi.org/project/ptn/"><img src="https://img.shields.io/pypi/v/ptn?style=flat-square&logo=pypi&logoColor=white&label=PyPI" alt="PyPI"></a>
<a href="https://pypi.org/project/ptn/"><img src="https://img.shields.io/pypi/pyversions/ptn?style=flat-square&logo=python&logoColor=white" alt="Python"></a>
<a href="https://pypi.org/project/ptn/"><img src="https://img.shields.io/pypi/dm/ptn?style=flat-square&label=Downloads" alt="Downloads"></a>
<a href="https://github.com/lyehe/porterminal/blob/master/LICENSE"><img src="https://img.shields.io/github/license/lyehe/porterminal?style=flat-square" alt="License"></a>
<a href="https://github.com/lyehe/porterminal/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/lyehe/porterminal/ci.yml?branch=master&style=flat-square&logo=github&label=CI" alt="CI"></a>
</p>
<p align="center">
<b>将电脑交给 AI 代理,实时在浏览器中观察它工作。</b><br>
一条命令,一个 URL。(也是您手机上的一个简洁终端。)
</p>
<p align="center">
<b>1.</b> <code>uvx ptn</code><br>
<b>2.</b> 将 URL 交给 AI 代理,或自行扫描二维码<br>
<b>3.</b> 在任意浏览器中观察它工作,随时接管<br>
</p>
<p align="center">
<img src="assets/demo.gif" alt="Porterminal demo" width="320">
</p>
> [!WARNING]
> **该 URL 对本电脑具有完全访问权限。** 您交给它的任何人(或 AI 代理)都可以获得一个真实的 shell,无需密码。这是整个功能的重点,但很容易意外地给予代理比您预期的更多权限。请像对待秘密一样保护该 URL,仅与您信任的人和代理共享,并在将其指向重要内容之前阅读 [安全](#安全)。
## 为什么
我想在任何地方都能控制我的集群。
**ngrok** 需要注册,免费版功能有限。 **Cloudflare Quick Tunnel** 使用方便,但直接在手机上使用较为困难。 **Termius** 需要复杂的设置:端口转发、防火墙规则、密钥管理…… 我还尝试了 **Claude Code web**,但它无法访问我的本地硬件和环境。同样,我也试用了 **Happy**,但它过于臃肿且更新缓慢。
因此,我创建了一个更简单的工具:**运行一条命令,扫描一个二维码,然后开始输入。**
然后,我意识到同样的技巧(一行命令,一个 URL)是给 AI 代理提供任意电脑上真实终端的最简单方法。不需要编写 MCP 服务器,不需要 SSH 密钥,不需要 Docker,也不需要配置文件。运行 `uvx ptn`,将 URL 交给代理,代理就可以在该机器上运行命令、读取屏幕并回答提示。并且由于它是一个网页终端,您可以在任何浏览器中打开同一个会话,实时观察它工作,或随时接管。
## 功能
- **将电脑交给代理,实时观察它工作** - 将 URL 交给 AI 代理,它将获得该机器上的真实终端(任意 MCP 客户端:Claude、Cursor 等)。在任意浏览器中打开同一个会话,实时观察它工作,随时接管。无需编写 MCP 服务器,无需密钥,无需 Docker。代理从 `/llms.txt` 和 `/.well-known/mcp.json` 中学习如何工作。参见 [代理访问(MCP)](#代理访问mcp)。
- **一行命令,即可访问** - `uvx ptn`,您(或代理)即可获得该机器上的真实终端。无需 SSH,无需端口转发,无需配置文件。Cloudflare 隧道 + 二维码。
- **在手机上实际可用** - 触摸优化,具备动量滚动、捏合缩放、滑动手势和修饰键(Ctrl、Alt)。
- **完整的终端应用程序** - vim、htop、less、tmux 均能正确运行,并具备适当的替代屏幕缓冲区处理。
- **持久的多标签页会话** - 会话在断开连接后仍保持。关闭浏览器,切换网络,重新连接其他设备,您的 shell 和正在运行的进程仍然存在。您和代理可以共享一个会话:观察它工作,或接管。
- **跨平台** - Windows(PowerShell、CMD、WSL),Linux/macOS(Bash、Zsh、Fish、Nushell 和任意 shell via `$SHELL`)。自动检测您的 shell。
- **默认私有** - 秘密隧道 URL 永远不会显示在屏幕上,因此可以安全地分享屏幕截图或二维码。按 `c` 将 URL 复制到剪贴板。
## 安装
| 方法 | 安装 | 更新 |
|--------|---------|--------|
| **uvx** (无需安装) | `uvx ptn` | `uvx --refresh ptn` |
| **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](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) (如果缺少则自动安装)。
## 使用
```bash
ptn # 在当前目录启动
ptn ~/projects/myapp # 在特定文件夹中启动
```
| 参数 | 描述 |
|------|-------------|
| `-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`** 将其复制到剪贴板,或扫描二维码连接。`Ctrl+C` 停止服务器。
## 代理访问(MCP)
同一个 URL 也适用于 AI 代理。Porterminal 在 **`<url>/mcp`** (可流式传输的 HTTP)处提供一个 Model Context Protocol(MCP)终端。将任何支持 MCP 的客户端(Claude、Cursor 等)指向它,代理将获得自己的持久 shell,显示为一个 🤖 标签页,您可以从手机上观察和接管。
将隧道 URL 交给代理。MCP 客户端可以从 **`<url>/.well-known/mcp.json>` (MCP `server.json` 描述文件)自动发现服务器,并且有一个人类/代理可读的 **`<url>/llms.txt>`,包含使用说明。两者都隐含地链接到页面,因此人类 UI 不会改变。示例客户端配置:
```json
{
"mcpServers": {
"porterminal": { "url": "https://<your-tunnel>.trycloudflare.com/mcp" }
}
}
```
工具:`run_command`(干净的输出 + 退出代码),`read_screen`,`send_keys`,`send_signal`(Ctrl-C / EOF)。
> **安全:** 与人类终端一样,唯一的保护是秘密隧道 URL:任何(或任何 AI)获得它的人都具有完全的非提升 shell 访问权限。如果您需要真正的身份验证,请使用其他工具。参见 [docs/agent-access.md](docs/agent-access.md)。
## 移动手势
| 手势 | 操作 |
|---------|--------|
| **点击** | 聚焦终端,清除选择 |
| **长按** | 开始文本选择 |
| **双击** | 选择单词 |
| **向左/向右滑动** | 箭头键(← →) |
| **滚动** | 动量滚动,物理效果 |
| **捏合** | 缩放文本(10-24px) |
**修饰键** (Ctrl、Alt、Shift):点击一次为粘性(一次按键),双击为锁定。
**组合模式** (▤ 按钮):切换一个文本输入字段,您可以在其中输入或口述,编辑您的文本,具备完整的移动编辑功能(自动纠正、建议、光标定位),然后发送到终端。对于较长的命令或语音输入非常有用。
## 配置
运行 `ptn --init` 以创建启动配置。它会自动从 `package.json`、`pyproject.toml` 或 `Makefile` 中发现项目脚本,并将它们添加为按钮:
```bash
ptn -i
# 已创建:.ptn/ptn.yaml
# 已发现 3 个项目脚本:build, dev, test
```
或手动创建 `ptn.yaml`:
```yaml
# 终端设置
terminal:
default_shell: nu # 默认 shell ID
shells: # 自定义 shell 定义
- id: nu
name: Nushell
command: nu
args: []
# 自定义按钮(出现在工具栏中)
# 行:1 = 默认行,2+ = 附加行
buttons:
- label: "claude"
send:
- "claude"
- 100 # 毫秒延迟
- "\r"
- label: "build"
send: "npm run build\r"
row: 2 # 第二行按钮
# 更新检查设置
update:
notify_on_startup: true # 显示更新通知
check_interval: 86400 # 检查之间的秒数(默认:24 小时)
# 安全设置
security:
require_password: true # 始终需要密码启动
password_hash: "" # 保存的密码哈希(使用 ptn -sp 设置)
max_auth_attempts: 5 # 最大身份验证失败次数,断开连接
```
按顺序搜索配置文件: `$PORTERMINAL_CONFIG_PATH`, `./ptn.yaml`, `./.ptn/ptn.yaml`, `~/.ptn/ptn.yaml`.
## 安全
**默认情况下没有密码。** 阻止任何人访问的唯一方法是他们无法猜测随机隧道 URL。任何(或任何 AI)获得它的人都具有完全的 shell 访问权限。不要暴露您不愿交给陌生人的任何内容,并为任何敏感内容设置密码:
**从 UI:** 打开设置(齿轮图标),使用安全部分设置/更改密码并切换密码要求。更改需要重启服务器。
**从 CLI:**
```bash
# 一次性密码(每个会话提示)
ptn -p
# 将密码保存到配置文件(无需提示)
ptn -sp
# 密码:****
# 确认密码:****
# 清除保存的密码(输入空密码)
ptn -sp
# 密码:[按 Enter]
# 设置或切换密码要求
ptn -tp on # 启用
ptn -tp off # 禁用
ptn -tp toggle # 切换当前状态
```
参见 [docs/security.md](docs/security.md) 获取详细信息。
## 故障排除
**连接失败?** Cloudflare 隧道有时会阻止连接。重启服务器(`Ctrl+C`,然后 `ptn`)以获取新的隧道 URL。
**检测不到 shell?** 设置您的 `$SHELL` 环境变量或在 `ptn.yaml` 中配置 shell。
## 贡献
**本项目不接受外部贡献** (拉取请求或代码更改),出于安全原因(参见 [CONTRIBUTING.md](CONTRIBUTING.md))。欢迎您分叉并在 [AGPL-3.0](LICENSE) 下运行您自己的副本。
从源代码运行:
```bash
git clone https://github.com/lyehe/porterminal
cd porterminal
uv sync
uv run ptn
```
## License
[AGPL-3.0](LICENSE)