
Tunneling terminale web/mcp veloce e sporco per telefono e PC
Consegna un computer a un agente, pieno controllo, e guardalo.
Un comando, un URL. (Anche un terminale curato per il tuo telefono.)
1. uvx ptn
2. Passa l'URL a un agente AI, oppure scansiona tu il QR
3. Guardalo lavorare in qualsiasi browser e prendi il controllo quando vuoi
[!WARNING] Quell'URL completo è accesso totale a questo computer. Contiene un codice di accesso casuale generato a ogni avvio, e chiunque (o qualsiasi agente AI) a cui lo consegni ottiene una vera shell sulla tua macchina. Tratta l'URL e il codice QR come un segreto, condividili solo con persone e agenti di cui ti fidi, e leggi Sicurezza prima di puntare Porterminal verso qualcosa di importante.
Mi serviva qualcosa di pericolosamente semplice per accedere da remoto a un computer.
ngrok richiede registrazione e il piano gratuito fa schifo. Cloudflare Tunnel è un'ottima infrastruttura, ma da solo ti dà solo un tunnel, non un terminale adatto al telefono. Tailscale è ottimo quando controlli entrambe le estremità, ma significa comunque unire dispositivi a una rete privata. Termius richiede un setup complicato: port forwarding, regole firewall, gestione delle chiavi...
Così ho costruito qualcosa di più semplice: esegui un comando, scansiona un QR, inizia a digitare.
Poi è scattato: lo stesso trucco (un comando, un URL) è il modo più semplice per dare a un agente AI un vero terminale su qualsiasi computer. Nessun server MCP da scrivere, niente chiavi SSH, niente Docker, nessuna configurazione. Esegui uvx ptn, consegna l'URL, e l'agente esegue comandi, legge lo schermo e risponde ai prompt su quella macchina. E poiché è un terminale web, puoi aprire la stessa sessione in qualsiasi browser per guardarlo lavorare dal vivo, o impugnare la tastiera e prendere il controllo.
<url>/llms.txt e <url>/.well-known/mcp.json. Vedi Accesso agente.uvx ptn e tu (o un agente) ottenete un vero terminale su questa macchina. Niente SSH, niente port forwarding, nessun file di configurazione. Cloudflare tunnel + codice QR.$SHELL). Rileva automaticamente le tue shell.c per copiare le istruzioni per l'agente e l'URL, oppure u per copiare solo l'URL.Installazione con una riga (uv + ptn):
| OS | 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 |
Richiede Python 3.12+ e cloudflared (installato automaticamente se mancante).
ptn # Avvia nella directory corrente
ptn ~/projects/myapp # Avvia in una cartella specifica
Mentre è in esecuzione: con un tunnel attivo, l'URL di connessione è nascosto sullo schermo per motivi di privacy. Premi c per copiare le istruzioni per l'agente e l'URL, inclusi /mcp, /api/agent/run e /llms.txt; premi u per copiare solo l'URL; oppure scansiona il QR per connetterti. Ctrl+C ferma il server.
Lo stesso URL funziona anche per gli agenti AI. I client compatibili con MCP possono usare <url>/mcp (Streamable HTTP) per strumenti nativi tipizzati. Gli agenti che non possono registrare un server MCP possono usare il fallback REST su <url>/api/agent/run con normali richieste HTTP. Entrambi i percorsi creano una shell agente persistente, mostrata come una scheda 🤖 che puoi guardare e di cui puoi prendere il controllo dal telefono.
Consegna all'agente l'URL completo generato, incluso il suo codice di accesso. I client MCP possono scoprire automaticamente il server da <url>/.well-known/mcp.json (il descrittore server.json di MCP), e c'è un <url>/llms.txt leggibile da umani e agenti con le istruzioni d'uso. La pagina base include anche suggerimenti visibili all'accessibilità per gli agenti che guidano il browser, mentre l'interfaccia umana rimane compatta. Esempio di configurazione client:
{
"mcpServers": {
"porterminal": { "url": "https://<your-tunnel>.trycloudflare.com/<access-code>/mcp" }
}
}
Strumenti MCP: run_command (output pulito + codice di uscita), 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}'
La risposta include un session_id; riutilizzalo con <url>/api/agent/screen,
<url>/api/agent/keys, <url>/api/agent/signal e
DELETE <url>/api/agent/session.
Quando apri Porterminal sul telefono, il pulsante di copia in alto a destra copia lo stesso testo di condivisione pronto per l'agente. Anche gli agenti solo-browser ricevono un fallback sulla pagina base: un mirror Terminal screen leggibile dal DOM e un Terminal input chiaramente etichettato.
Sicurezza:
<url>indica l'URL completo generato, incluso il suo codice di accesso casuale. Il nome host del tunnel nudo non espone nulla, ma chiunque (o qualsiasi agente) con l'URL completo ottiene accesso shell completo e non elevato. Vedi docs/agent-access.md.
Tasti modificatori (Ctrl, Alt, Shift): tocco singolo per sticky (una sola pressione), doppio tocco per blocco.
Modalità compose (pulsante ▤): attiva un campo di input di testo dove puoi digitare o dettare, modificare il testo con tutte le funzionalità di modifica mobile (correzione automatica, suggerimenti, posizionamento del cursore), quindi inviarlo al terminale. Utile per comandi più lunghi o input vocale.
Esegui ptn --init per creare una configurazione iniziale. Rileva automaticamente gli script di progetto da package.json, pyproject.toml o Makefile e li aggiunge come pulsanti:
ptn -i
# Created: .ptn/ptn.yaml
# Discovered 3 project script(s): build, dev, test
Oppure crea 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
La configurazione viene cercata in questo ordine: $PORTERMINAL_CONFIG_PATH, ./ptn.yaml, ./.ptn/ptn.yaml, ~/.ptn/ptn.yaml.
Ogni avvio crea un nuovo percorso casuale a 128 bit come
https://<tunnel>.trycloudflare.com/<access-code>/. Tutte le route per browser,
WebSocket, MCP, REST, health e statiche richiedono quel prefisso esatto; il nome
host nudo e i percorsi sbagliati restituiscono 404. Questo rende impraticabile
il brute-forcing di un nome host di tunnel scoperto.
L'URL completo generato è comunque una credenziale bearer: chiunque lo ottiene ha accesso alla shell. Riavvia Porterminal per ruotare il codice se viene divulgato. La password opzionale aggiunge autenticazione ai WebSocket del browser, ma MCP e REST continuano a fidarsi dell'URL completo, così gli agenti possono usare il flusso a collegamento singolo.
Un browser ricorda una password riuscita in un archivio in chiaro limitato a quell'URL di avvio completo. Salvare una password per un avvio più recente sulla stessa origine ritira le vecchie voci password di Porterminal; cancellare o rifiutare una password ricordata le rimuove tutte senza toccare gli altri dati del browser. Di conseguenza, avvii concorrenti sulla stessa origine potrebbero richiedere di nuovo la password, mentre una connessione già autenticata rimane connessa.
Dall'interfaccia: apri Impostazioni (icona ingranaggio) e usa la sezione Sicurezza per impostare/cambiare la password e attivare/disattivare il requisito della password. Le modifiche richiedono il riavvio del server.
Da CLI:
# Password monouso (richiesta a ogni sessione)
ptn -p
# Salva la password nella configurazione (nessuna richiesta necessaria)
ptn -sp
# Password: ****
# Confirm password: ****
# Cancella la password salvata (inserisci password vuota)
ptn -sp
# Password: [press Enter]
# Imposta o alterna il requisito della password
ptn -tp # Toggle on/off
Vedi docs/security.md per i dettagli.
La connessione fallisce? Usa l'URL completo generato, incluso il suo codice di accesso. I problemi del tunnel Cloudflare possono anche essere risolti riavviando il server (Ctrl+C, poi ptn) per ottenere un tunnel e un percorso di accesso nuovi.
uvx ptn esegue ancora una versione precedente? Un'installazione uv tool
esistente può avere precedenza. Esegui uv tool upgrade ptn, oppure aggira gli
strumenti installati con uvx --isolated ptn@latest.
Shell non rilevata? Imposta la variabile d'ambiente $SHELL o configura le shell in ptn.yaml.
Questo progetto non accetta contributi esterni (pull request o modifiche al codice) per motivi di sicurezza (vedi CONTRIBUTING.md). Sei libero di fare fork ed eseguire la tua copia sotto AGPL-3.0.
Esecuzione dal sorgente:
git clone https://github.com/lyehe/porterminal
cd porterminal
uv sync --frozen
uv run --frozen ptn
| Metodo | Installazione | Aggiornamento |
|---|
| uvx (senza installazione) | 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 | Descrizione |
|---|
-n, --no-tunnel | Solo rete locale (senza tunnel Cloudflare) |
-b, --background | Esegui in background e termina subito |
-p, --password | Chiedi una password per proteggere questa sessione |
-sp, --save-password | Salva o cancella la password nella configurazione |
-tp, --toggle-password | Imposta il requisito della password (on/off/toggle) |
-v, --verbose | Mostra log di avvio dettagliati |
-i, --init | Crea .ptn/ptn.yaml con gli script di progetto rilevati automaticamente come pulsanti |
-if, --init-from URL/PATH | Crea .ptn/ptn.yaml da un URL o un file locale |
-c, --compose | Abilita la modalità compose di default |
-k, --keep-qr | Mantieni il codice QR visibile dopo la prima connessione |
-u, --check-update | Controlla se è disponibile una versione più recente |
-V, --version | Mostra la versione |
| Gesto | Azione |
|---|
| Tocco | Focalizza il terminale, cancella la selezione |
| Pressione lunga | Avvia la selezione del testo |
| Doppio tocco | Seleziona la parola |
| Swipe a sinistra/destra | Tasti freccia (← →) |
| Scorrimento | Scorrimento a slancio con fisica |
| Pizzico | Zoom del testo (10-24px) |