Architecture
Vue d’ensemble du flux
Par défaut (local tmux + tunnel) :
Code
Browser (phone)
|
| HTTPS
v
Cloudflare Quick Tunnel
|
| HTTP/WS
v
Local Termbridge server
|
| PTY
v
Tmux session
Mode bac à sable direct (Daytona, sans tunnel) :
Code
Browser (phone)
|
| HTTPS
v
Daytona preview link
|
| HTTP/WS
v
Termbridge server (sandbox)
|
| PTY
v
Tmux session (sandbox)
Lorsque --no-tunnel est défini, Termbridge ignore Cloudflare et utilise le URL public que vous avez fourni.
Composants
Processus CLI
- Démarre le serveur HTTP qui sert les ressources UI.
- Démarre le serveur WebSocket pour les entrées-sorties du terminal.
- Crée une ou plusieurs sessions tmux (ou des pseudo-terminaux Daytona).
- Émet des jetons à usage unique.
- Démarre et surveille le tunnel lorsqu’il est activé (Cloudflare actuellement).
- En mode bac à sable direct, lance Termbridge dans le bac à sable et attend le URL de partage.
Backend du terminal
- Backend tmux : utilise
node-ptypour se connecter à tmux et gérer les frappes réelles et la sortie. - Backend Daytona : utilise les pseudo-terminaux Daytona dans un bac à sable.
- Définit
TERM=xterm-256coloretCOLORTERM=truecolorpour la prise en charge complète des couleurs. - Pour tmux, désactive la barre d’état tmux afin de garder UI propre.
Registre des terminaux
- Suit les sessions de terminal disponibles.
- Fournit une liste pour UI et valide les identifiants des terminaux sélectionnés.
Authentification et session
- Le jeton à usage unique est affiché sous forme de URL et encodé dans un code QR.
GET /__tb/s/:tokenéchange le jeton et crée une session par cookie.- Les connexions WebSocket nécessitent un cookie de session valide et un jeton CSRF.
- Le jeton CSRF est récupéré via
GET /__tb/api/csrfet transmis dans le paramètre de requête WebSocket.
Mode proxy
Lorsque --proxy <port> est transmis :
- Toutes les routes termbridge sont sous le préfixe
/__tb/. - Les requêtes autres que
/__tb/sont transmises au proxy de l’application cible. - UI expose les vues Terminal/Aperçu via le sélecteur de vues.
- La vue Aperçu charge un iframe pointant vers
/. - Les connexions WebSocket pour HMR sont transmises à la cible.
Sécurité
- Protection CSRF : les mises à niveau WebSocket exigent un jeton CSRF pour prévenir le détournement intersites.
- Limites d’entrée : corps HTTP de 64KB, message WebSocket de 1MB, entrée du terminal de 64KB par message.
- Limitation du débit : limites par IP pour l’échange des jetons et les connexions WebSocket.
Points de terminaison API
Toutes les routes sont sous le préfixe /__tb/ pour éviter les conflits avec les applications utilisant le proxy :
GET /__tb/healthz- vérification de l’étatGET /__tb/s/:token- échange du jeton → cookie → redirectionGET /__tb/api/terminals- lister les terminauxGET /__tb/api/csrf- obtenir le jeton CSRF pour WebSocketGET /__tb/api/config- obtenir la configuration (proxyPort, devProxyUrl)POST /__tb/api/terminals- créer une nouvelle session tmuxGET /__tb/app/*- solution de repli pour SPAWS /__tb/ws/terminal/:terminalId?csrf=<token>- flux des entrées-sorties du terminal
Lorsque le mode proxy est activé :
GET /- redirige vers l’application utilisant le proxy (ou/__tb/appsi désactivé)* /*- transmis au proxy de l’application cible
Protocole WebSocket
Client → serveur :
JSON
{ "type": "input", "data": "ls -la" }
{ "type": "resize", "cols": 120, "rows": 32 }
{ "type": "control", "key": "ctrl_c" }
Serveur → client :
JSON
{ "type": "output", "data": "..." }
{ "type": "status", "state": "connected" }
Pile UI
- Vite + TanStack Router
- xterm.js + extension Fit + moteur de rendu WebGL
- Mise en page conçue d’abord pour les mobiles, avec une barre de saisie fixe
- Reconnexion automatique avec délai exponentiel (jusqu’à 10 tentatives)
- Indicateur d’état de connexion