
Túnel de terminal web/mcp rápido e simples para seu telefone e PC
Entregue um computador a um agente, com controle total, e observe.
Um comando, uma URL. (Também um terminal elegante para o seu próprio celular.)
1. uvx ptn
2. Entregue a URL a um agente de IA, ou escaneie o QR você mesmo
3. Observe-o funcionar em qualquer navegador e assuma o controle a qualquer momento
[!WARNING] Essa URL completa é acesso total a este computador. Ela contém um código de acesso aleatório por execução, e qualquer pessoa (ou agente de IA) a quem você a entregar obtém um shell real na sua máquina. Trate a URL e o código QR como um segredo, compartilhe-os apenas com pessoas e agentes em quem você confia, e leia Segurança antes de apontar o Porterminal para algo importante.
Preciso de algo perigosamente fácil para acessar um computador remotamente.
ngrok exige registro e o plano gratuito é ruim. Cloudflare Tunnel é um excelente encanamento, mas por si só oferece apenas um túnel, não um terminal amigável para celular. Tailscale é ótimo quando você controla as duas pontas, mas ainda assim significa unir dispositivos a uma rede privada. Termius exige configuração complicada: encaminhamento de portas, regras de firewall, gerenciamento de chaves...
Então construí algo mais simples: execute um comando, escaneie um QR, comece a digitar.
Então percebi: o mesmo truque (um comando, uma URL) é a maneira mais fácil de dar a um agente de IA um terminal real em qualquer computador. Sem servidor MCP para escrever, sem chaves SSH, sem Docker, sem configuração. Execute uvx ptn, entregue a URL, e o agente executa comandos, lê a tela e responde prompts nessa máquina. E como é um terminal web, você pode abrir a mesma sessão em qualquer navegador para observá-lo funcionar ao vivo, ou pegar o teclado e assumir o controle.
<url>/llms.txt e <url>/.well-known/mcp.json. Veja Acesso para agentes.uvx ptn e você (ou um agente) obtém um terminal real nesta máquina. Sem SSH, sem encaminhamento de portas, sem arquivos de configuração. Túnel Cloudflare + código QR.$SHELL). Detecta seus shells automaticamente.c para copiar as instruções do agente e a URL, ou u para copiar apenas a URL.Instalação em uma linha (uv + ptn):
| SO | Comando |
|---|---|
| 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 |
Requer Python 3.12+ e cloudflared (instalado automaticamente se estiver ausente).
ptn # Start in current directory
ptn ~/projects/myapp # Start in specific folder
Durante a execução: com um túnel ativo, a URL de conexão fica oculta na tela por privacidade. Pressione c para copiar as instruções do agente e a URL, incluindo /mcp, /api/agent/run e /llms.txt; pressione u para copiar apenas a URL; ou escaneie o QR para conectar. Ctrl+C interrompe o servidor.
A mesma URL também funciona para agentes de IA. Clientes com suporte a MCP podem usar <url>/mcp (Streamable HTTP) para ferramentas tipadas nativas. Agentes que não conseguem registrar um servidor MCP podem usar o fallback REST em <url>/api/agent/run com requisições HTTP comuns. Qualquer um dos caminhos cria um shell de agente persistente, exibido como uma aba 🤖 que você pode observar e assumir pelo celular.
Entregue ao agente a URL completa gerada, incluindo seu código de acesso. Clientes MCP podem descobrir automaticamente o servidor a partir de <url>/.well-known/mcp.json (o descritor server.json do MCP), e há um <url>/llms.txt legível por humanos/agentes com instruções de uso. A página base também inclui dicas visíveis para acessibilidade para agentes que controlam o navegador, enquanto a interface humana permanece compacta. Exemplo de configuração do cliente:
{
"mcpServers": {
"porterminal": { "url": "https://<your-tunnel>.trycloudflare.com/<access-code>/mcp" }
}
}
Ferramentas MCP: run_command (saída limpa + código de saída), read_screen, send_keys, send_signal (Ctrl-C / EOF).
Fallback 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}'
A resposta inclui um session_id; reutilize-o com <url>/api/agent/screen,
<url>/api/agent/keys, <url>/api/agent/signal e
DELETE <url>/api/agent/session.
Quando você abre o Porterminal no celular, o botão de copiar no canto superior direito copia o mesmo texto de compartilhamento pronto para agentes. Agentes somente navegador também têm um fallback na página base: um espelho Tela do terminal legível por DOM e uma Entrada do terminal claramente identificada.
Segurança:
<url>significa a URL completa gerada, incluindo seu código de acesso aleatório. O hostname do túnel sem o caminho não expõe nada, mas qualquer pessoa (ou agente) com a URL completa obtém acesso total ao shell, sem elevação. Veja docs/agent-access.md.
Teclas modificadoras (Ctrl, Alt, Shift): Toque uma vez para fixar (um pressionamento de tecla), toque duas vezes para travar.
Modo compose (botão ▤): Alterna um campo de entrada de texto onde você pode digitar ou ditar, editar seu texto com todos os recursos de edição móvel (correção automática, sugestões, posicionamento do cursor) e então enviar para o terminal. Útil para comandos mais longos ou entrada por voz.
Execute ptn --init para criar uma configuração inicial. Ele descobre automaticamente scripts de projeto em package.json, pyproject.toml ou Makefile e os adiciona como botões:
ptn -i
# Created: .ptn/ptn.yaml
# Discovered 3 project script(s): build, dev, test
Ou crie ptn.yaml manualmente:
# 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
A configuração é procurada nesta ordem: $PORTERMINAL_CONFIG_PATH, ./ptn.yaml, ./.ptn/ptn.yaml, ~/.ptn/ptn.yaml.
Cada execução cria um novo caminho aleatório de 128 bits, como
https://<tunnel>.trycloudflare.com/<access-code>/. Todas as rotas de navegador, WebSocket,
MCP, REST, health e estáticas exigem esse prefixo exato; o host sem o caminho
e caminhos errados retornam 404. Isso torna impraticável forçar por força bruta um
hostname de túnel descoberto.
A URL completa gerada ainda é uma credencial de portador: qualquer pessoa que a obtiver tem acesso ao shell. Reinicie o Porterminal para rotacionar o código se ele vazar. A senha opcional adiciona autenticação aos WebSockets do navegador, mas MCP e REST continuam confiando na URL completa para que os agentes possam usar o fluxo de um único link.
Um navegador lembra uma senha bem-sucedida em armazenamento de texto puro, com escopo restrito àquela URL completa de execução. Salvar uma senha para uma execução mais recente na mesma origem aposenta as entradas de senha anteriores do Porterminal; limpar ou rejeitar uma senha lembrada remove todas elas sem tocar em outros armazenamentos do navegador. Consequentemente, execuções simultâneas na mesma origem podem solicitar novamente, enquanto uma conexão já autenticada permanece conectada.
Pela interface: Abra Configurações (ícone de engrenagem) e use a seção Segurança para definir/alterar a senha e alternar a exigência de senha. As alterações exigem reinicialização do servidor.
Pela CLI:
# 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
Veja docs/security.md para detalhes.
A conexão falha? Use a URL completa gerada, incluindo seu código de acesso. Problemas com o túnel Cloudflare também podem ser resolvidos reiniciando o servidor (Ctrl+C, depois ptn) para obter um novo túnel e caminho de acesso.
uvx ptn ainda executa uma versão antiga? Uma instalação existente do uv tool
pode ter precedência. Execute uv tool upgrade ptn ou contorne as ferramentas instaladas com
uvx --isolated ptn@latest.
Shell não detectado? Defina sua variável de ambiente $SHELL ou configure shells no ptn.yaml.
Este projeto não aceita contribuições externas (pull requests ou alterações de código) por motivos de segurança (veja CONTRIBUTING.md). Você é bem-vindo para fazer um fork e executar sua própria cópia sob a AGPL-3.0.
Execute a partir do código-fonte:
git clone https://github.com/lyehe/porterminal
cd porterminal
uv sync --frozen
uv run --frozen ptn
| Método | Instalar | Atualizar |
|---|
| uvx (sem instalação) | 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 |
| Flag | Descrição |
|---|
-n, --no-tunnel | Somente rede local (sem túnel Cloudflare) |
-b, --background | Executar em segundo plano e retornar imediatamente |
-p, --password | Solicitar senha para proteger esta sessão |
-sp, --save-password | Salvar ou limpar senha na configuração |
-tp, --toggle-password | Definir a exigência de senha (ligar/desligar/alternar) |
-v, --verbose | Exibir logs detalhados de inicialização |
-i, --init | Criar .ptn/ptn.yaml com scripts de projeto descobertos automaticamente como botões |
-if, --init-from URL/PATH | Criar .ptn/ptn.yaml a partir de uma URL ou arquivo local |
-c, --compose | Ativar o modo compose por padrão |
-k, --keep-qr | Manter o código QR visível após a primeira conexão |
-u, --check-update | Verificar se há uma versão mais recente disponível |
-V, --version | Exibir versão |
| Gesto | Ação |
|---|
| Toque | Focar o terminal, limpar a seleção |
| Toque longo | Iniciar seleção de texto |
| Toque duplo | Selecionar palavra |
| Deslizar para esquerda/direita | Teclas de seta (← →) |
| Rolar | Rolagem por inércia com física |
| Pinça | Ampliar texto (10-24px) |