
Tunneling terminal web/mcp rapide et sale entre votre téléphone & votre pc
Confiez un ordinateur à un agent, avec un contrôle total, et observez-le.
Une commande, une URL. (Et aussi un terminal élégant pour votre propre téléphone.)
1. uvx ptn
2. Remettez l'URL à un agent IA, ou scannez le QR code vous-même
3. Regardez-le travailler dans n'importe quel navigateur, et reprenez la main à tout moment
[!WARNING] Cette URL complète donne un accès total à cet ordinateur. Elle contient un code d'accès aléatoire propre à chaque lancement, et toute personne (ou agent IA) à qui vous la confiez obtient un véritable shell sur votre machine. Traitez l'URL et le code QR comme un secret, ne les partagez qu'avec des personnes et des agents de confiance, et lisez Sécurité avant d'utiliser Porterminal sur un système important.
J'avais besoin de quelque chose de terriblement simple pour accéder à distance à un ordinateur.
ngrok exige une inscription et son offre gratuite est médiocre. Cloudflare Tunnel est une excellente infrastructure, mais à lui seul il ne fournit qu'un tunnel, pas un terminal adapté au mobile. Tailscale est très bien quand on contrôle les deux extrémités, mais il faut quand même joindre des appareils à un réseau privé. Termius nécessite une configuration compliquée : redirection de ports, règles de pare-feu, gestion des clés...
Alors j'ai construit quelque chose de plus simple : lancez une commande, scannez un QR, commencez à taper.
Puis ça a fait tilt : la même astuce (une commande, une URL) est le moyen le plus simple de donner à un agent IA un véritable terminal sur n'importe quel ordinateur. Pas de serveur MCP à écrire, pas de clés SSH, pas de Docker, pas de configuration. Lancez uvx ptn, transmettez l'URL, et l'agent exécute des commandes, lit l'écran et répond aux invites sur cette machine. Et comme c'est un terminal web, vous pouvez ouvrir la même session dans n'importe quel navigateur pour le regarder travailler en direct, ou attraper le clavier et reprendre la main.
<url>/llms.txt et <url>/.well-known/mcp.json. Voir Accès agent.uvx ptn et vous (ou un agent) obtenez un véritable terminal sur cette machine. Pas de SSH, pas de redirection de ports, pas de fichiers de configuration. Tunnel Cloudflare + code QR.$SHELL). Détecte automatiquement vos shells.c pour copier les instructions agent et l'URL, ou sur u pour copier l'URL uniquement.Installation en une ligne (uv + ptn) :
| Système | Commande |
|---|---|
| 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 |
Nécessite Python 3.12+ et cloudflared (installé automatiquement si absent).
ptn # Start in current directory
ptn ~/projects/myapp # Start in specific folder
Pendant l'exécution : avec un tunnel actif, l'URL de connexion est masquée à l'écran pour des raisons de confidentialité. Appuyez sur c pour copier les instructions agent et l'URL, y compris /mcp, /api/agent/run et /llms.txt ; appuyez sur u pour copier l'URL uniquement ; ou scannez le QR pour vous connecter. Ctrl+C arrête le serveur.
La même URL fonctionne aussi pour les agents IA. Les clients compatibles MCP peuvent utiliser <url>/mcp (HTTP Streamable) pour des outils typés natifs. Les agents qui ne peuvent pas enregistrer de serveur MCP peuvent utiliser le repli REST à <url>/api/agent/run avec des requêtes HTTP ordinaires. Chacun de ces chemins crée un shell agent persistant, affiché sous forme d'onglet 🤖 que vous pouvez regarder et dont vous pouvez reprendre la main depuis votre téléphone.
Remettez à l'agent l'URL complète générée, y compris son code d'accès. Les clients MCP peuvent découvrir automatiquement le serveur à partir de <url>/.well-known/mcp.json (le descripteur server.json MCP), et il existe un <url>/llms.txt lisible par les humains et les agents avec les instructions d'utilisation. La page de base inclut également des indices visibles pour l'accessibilité destinés aux agents qui pilotent le navigateur, tandis que l'interface humaine reste compacte. Exemple de configuration client :
{
"mcpServers": {
"porterminal": { "url": "https://<your-tunnel>.trycloudflare.com/<access-code>/mcp" }
}
}
Outils MCP : run_command (sortie propre + code de sortie), read_screen, send_keys, send_signal (Ctrl-C / EOF).
Repli 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 réponse contient un session_id ; réutilisez-le avec <url>/api/agent/screen,
<url>/api/agent/keys, <url>/api/agent/signal et
DELETE <url>/api/agent/session.
Lorsque vous ouvrez Porterminal sur votre téléphone, le bouton de copie en haut à droite copie le même texte de partage prêt pour les agents. Les agents limités au navigateur disposent aussi d'un repli sur la page de base : un miroir Écran du terminal lisible via le DOM et une Entrée du terminal clairement étiquetée.
Sécurité :
<url>désigne l'URL complète générée, y compris son code d'accès aléatoire. Le nom d'hôte nu du tunnel n'expose rien, mais toute personne (ou tout agent) disposant de l'URL complète obtient un accès shell complet et non élevé. Voir docs/agent-access.md.
Touches modificatrices (Ctrl, Alt, Maj) : un toucher simple pour l'accrochage (une frappe), un double toucher pour verrouiller.
Mode composition (bouton ▤) : active ou désactive un champ de saisie de texte où vous pouvez taper ou dicter, modifier votre texte avec toutes les fonctions d'édition mobile (correction automatique, suggestions, positionnement du curseur), puis l'envoyer au terminal. Utile pour les commandes longues ou la saisie vocale.
Exécutez ptn --init pour créer une configuration de départ. Elle détecte automatiquement les scripts de projet depuis package.json, pyproject.toml ou Makefile et les ajoute comme boutons :
ptn -i
# Created: .ptn/ptn.yaml
# Discovered 3 project script(s): build, dev, test
Ou créez ptn.yaml manuellement :
# 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 configuration est recherchée dans l'ordre : $PORTERMINAL_CONFIG_PATH, ./ptn.yaml, ./.ptn/ptn.yaml, ~/.ptn/ptn.yaml.
Chaque lancement crée un nouveau chemin aléatoire de 128 bits, comme
https://<tunnel>.trycloudflare.com/<access-code>/. Toutes les routes navigateur, WebSocket,
MCP, REST, de santé et statiques exigent ce préfixe exact ; le nom d'hôte nu
et les chemins incorrects renvoient une 404. Cela rend le brute-force d'un nom d'hôte de tunnel découvert peu pratique.
L'URL complète générée reste un identifiant de type bearer : quiconque l'obtient dispose d'un accès shell. Redémarrez Porterminal pour faire tourner le code s'il fuit. Le mot de passe facultatif ajoute une authentification aux WebSockets du navigateur, mais MCP et REST continuent de faire confiance à l'URL complète afin que les agents puissent utiliser le flux de travail à lien unique.
Un navigateur mémorise un mot de passe correct dans un stockage en clair limité à cette URL de lancement complète. L'enregistrement d'un mot de passe pour un lancement plus récent sur la même origine retire les anciennes entrées de mot de passe Porterminal ; le fait d'effacer ou de rejeter un mot de passe mémorisé les supprime toutes sans toucher au reste du stockage du navigateur. Par conséquent, des lancements simultanés sur la même origine peuvent redemander le mot de passe, tandis qu'une connexion déjà authentifiée reste connectée.
Depuis l'interface : ouvrez les Paramètres (icône d'engrenage) et utilisez la section Sécurité pour définir/modifier le mot de passe et activer/désactiver l'exigence de mot de passe. Les modifications nécessitent un redémarrage du serveur.
Depuis la 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
Voir docs/security.md pour plus de détails.
La connexion échoue ? Utilisez l'URL complète générée, y compris son code d'accès. Les problèmes de tunnel Cloudflare peuvent également être résolus en redémarrant le serveur (Ctrl+C, puis ptn) pour obtenir un nouveau tunnel et un nouveau chemin d'accès.
uvx ptn exécute toujours une version plus ancienne ? Une installation existante de uv tool
peut prendre le dessus. Exécutez uv tool upgrade ptn, ou contournez les outils installés avec
uvx --isolated ptn@latest.
Shell non détecté ? Définissez votre variable d'environnement $SHELL ou configurez les shells dans ptn.yaml.
Ce projet n'accepte pas de contributions externes (pull requests ou modifications de code) pour des raisons de sécurité (voir CONTRIBUTING.md). Vous êtes libre de forker et d'exécuter votre propre copie sous AGPL-3.0.
Exécution à partir des sources :
git clone https://github.com/lyehe/porterminal
cd porterminal
uv sync --frozen
uv run --frozen ptn
| Méthode | Installation | Mise à jour |
|---|
| uvx (sans installation) | 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 |
| Option | Description |
|---|
-n, --no-tunnel | Réseau local uniquement (sans tunnel Cloudflare) |
-b, --background | Exécuter en arrière-plan et revenir immédiatement |
-p, --password | Demander un mot de passe pour protéger cette session |
-sp, --save-password | Enregistrer ou effacer le mot de passe dans la configuration |
-tp, --toggle-password | Définir l'exigence de mot de passe (activer/désactiver/basculer) |
-v, --verbose | Afficher les journaux de démarrage détaillés |
-i, --init | Créer .ptn/ptn.yaml avec les scripts de projet auto-découverts comme boutons |
-if, --init-from URL/PATH | Créer .ptn/ptn.yaml à partir d'une URL ou d'un fichier local |
-c, --compose | Activer le mode composition par défaut |
-k, --keep-qr | Garder le code QR visible après la première connexion |
-u, --check-update | Vérifier si une version plus récente est disponible |
-V, --version | Afficher la version |
| Geste | Action |
|---|
| Toucher | Mettre le focus sur le terminal, effacer la sélection |
| Appui long | Démarrer la sélection de texte |
| Double toucher | Sélectionner un mot |
| Balayage gauche/droite | Touches fléchées (← →) |
| Défilement | Défilement à inertie avec physique |
| Pincement | Zoom du texte (10-24px) |