Le terminal du futur
(jyn.dev)- Le texte souligne la complexité et les limites de l’architecture actuelle des terminaux et propose un concept de terminal de nouvelle génération qui réunit autrement l’entrée, la sortie et le contrôle des processus
- En prenant Jupyter Notebook comme modèle, il explore la possibilité de mettre en œuvre une interface interactive avec rendu d’images, relance des commandes, sortie modifiable et éditeur intégré
- À travers les exemples de Warp et iTerm2, il décrit concrètement l’intégration poussée entre shell et terminal (shell integration), la gestion des processus de longue durée et les fonctions de séparation/reprise de session
- En s’appuyant sur le suivi de flux de données (dataflow tracking) et la persistance (persistence), il imagine des fonctions étendues comme l’undo/redo des commandes, la relance automatique et le terminal collaboratif
- Il présente une stratégie de construction progressive faisant évoluer le système de CLI transactionnelle → sessions persistantes → RPC structurée → frontend de type Jupyter
Structure de base d’un terminal
- Un terminal se compose de quatre éléments : émulateur de terminal, terminal virtuel (PTY), shell et groupe de processus
- L’émulateur de terminal est le programme qui affiche une structure en grille à l’écran
- Le PTY est un état interne du noyau, chargé de transmettre les entrées au groupe de processus et de convertir les signaux
- Le shell joue le rôle d’une boucle d’événements qui lit et analyse l’entrée puis crée les processus
- Les processus interagissent avec les éléments ci-dessus via leurs entrées et sorties
- L’entrée n’est pas un simple texte : elle inclut des signaux, tandis que la sortie est composée de séquences d’échappement ANSI exprimant le formatage
Imaginer un meilleur terminal
- Le terminal actuel a de nombreuses limites fonctionnelles, ce qui réduit son extensibilité et son interactivité
- Jupyter Notebook offre des fonctions impossibles dans un émulateur VT100 traditionnel
- Rendu d’images en haute résolution
- Bouton « réexécuter depuis le début » qui remplace une sortie passée sans en ajouter une nouvelle
- « Vues » permettant de réécrire sur place le code source et la sortie (par exemple afficher du Markdown comme source ou comme HTML rendu)
- Éditeur intégré avec coloration syntaxique, onglets, panneaux et prise en charge de la souris
- Mais l’idée d’un notebook Jupyter utilisant le shell comme noyau se heurte à plusieurs problèmes
- Le shell reçoit les commandes d’un seul bloc, ce qui fait que la complétion par tabulation, la coloration syntaxique et les suggestions automatiques ne fonctionnent pas
- Problème de gestion des processus de longue durée : Jupyter exécute par défaut jusqu’à la fin de la cellule ; on peut annuler, mais pas suspendre, reprendre, interagir ni voir les processus en cours d’exécution
- Le bouton « réexécuter la cellule » peut créer des problèmes d’état sur la machine (surtout si la commande contient quelque chose comme
rm -rf) - L’annulation et la réexécution ne fonctionnent pas
Comment cela pourrait-il fonctionner ?
-
Intégration du shell (Shell Integration)
- Le terminal Warp met en place une intégration native entre le terminal et le shell
- Le terminal comprend le début et la fin de chaque commande, sa sortie et les entrées utilisateur
- L’implémentation s’appuie sur une fonction standard (DCS personnalisé)
- iTerm2 permet aussi une approche similaire avec les codes d’échappement OSC 133
- Navigation entre les commandes via un seul raccourci clavier
- Notifications à la fin d’une commande
- Affichage de la commande actuelle en « overlay » quand sa sortie sort de l’écran
- Le terminal Warp met en place une intégration native entre le terminal et le shell
-
Gestion des processus de longue durée
- Interagir :
- Interagir avec un processus de longue durée nécessite une communication bidirectionnelle
- Exemples de TUI :
top,gdb,vim - Jupyter est bien conçu pour des sorties interactives pouvant être modifiées et mises à jour
- Exemples de TUI :
- Fonction attendue du terminal : fournir en permanence une « cellule de saisie libre »
- Le processus interactif s’exécute en haut de la fenêtre, avec une cellule de saisie en bas
- Interagir avec un processus de longue durée nécessite une communication bidirectionnelle
- Suspendre :
- La « suspension » d’un processus est appelée job control
- On peut s’attendre à ce qu’un terminal moderne affiche en permanence et visuellement les processus suspendus ou en arrière-plan
- À la manière d’IntelliJ qui affiche « indexation en cours... » dans une barre de tâches en bas
- Se déconnecter : il existe trois approches pour séparer puis restaurer une session
- Tmux / Zellij / Screen : insertion d’un émulateur de terminal supplémentaire entre l’émulateur et le programme. Le serveur possède le PTY, rend la sortie et le client l’affiche dans le véritable émulateur de terminal. Le client peut se détacher, se reconnecter ou permettre plusieurs connexions simultanées. iTerm peut agir comme son propre client en contournant le client tmux et en communiquant directement avec le serveur
- Mosh : alternative à SSH. Permet de se reconnecter à une session terminal après une coupure réseau. Le serveur exécute une machine à états et rejoue côté client les différences incrémentales du viewport. Le multiplexage et le scrollback sont supposés être gérés par l’émulateur de terminal. Comme le client s’exécute réellement du côté réseau, l’édition locale de ligne est immédiate
- alden/shpool/dtach/abduco/diss : ne gèrent côté client/serveur que la séparation et la reprise de session, sans réseau ni scrollback, et sans émulateur de terminal intégré. Ils offrent un niveau de découplage plus élevé que tmux et mosh
- Interagir :
-
Réexécution et retour en arrière
- La solution repose sur le suivi des flux de données
- pluto.jl l’illustre aujourd’hui en se connectant au compilateur Julia
- Met à jour en temps réel les cellules dépendant des cellules précédentes
- Ne met pas à jour une cellule si ses dépendances n’ont pas changé
- Sorte de Jupyter proche d’un tableur, qui ne réexécute le code qu’en cas de besoin
- Généralisation via la persistance orthogonale (orthogonal persistence)
- Isoler les processus dans des sandboxes, tracer toutes les E/S et empêcher les comportements « trop étranges » tant qu’ils ne communiquent pas avec d’autres processus dans la sandbox
- On peut alors traiter un processus comme une fonction pure de ses entrées, ces entrées étant « l’ensemble du système de fichiers, toutes les variables d’environnement et toutes les propriétés du processus »
Fonctions dérivées
- Nécessite un frontend Jupyter :
- Runbooks (en pratique, constructibles uniquement avec Jupyter et des primitives PTY)
- Personnalisation du terminal avec du CSS standard, sans langage maison bizarre ni codes couleur ANSI
- Recherche de commandes par sortie ou horodatage : on peut chercher dans toute la sortie de la session courante ou dans l’historique de toutes les commandes, mais sans filtres intelligents et sans persistance de la sortie entre les sessions
- Nécessite l’intégration du shell :
- Horodatage et durée d’exécution de chaque commande
- Édition locale de ligne même au-delà des frontières réseau
- IntelliSense pour les commandes shell sans devoir appuyer sur Tab, avec rendu intégré au terminal
- Nécessite le suivi en sandbox :
- Toutes les fonctions du suivi en sandbox : terminal collaboratif, requête des fichiers modifiés par une commande, asciinema modifiable à l’exécution, suivi de systèmes de build
- Extension de la recherche intelligente pour interroger aussi l’état du disque au moment de l’exécution de la commande
- Extension de l’annulation/réexécution à un modèle de branches comparable à git (emacs undo-tree le prend déjà en charge), avec plusieurs « vues » de l’arbre de processus
- Grâce au modèle undo-tree et au sandboxing, il devient possible de donner à un LLM l’accès à un projet et d’en exécuter plusieurs en parallèle, sans qu’ils écrasent mutuellement leur état, tout en pouvant inspecter, modifier et enregistrer plus tard leur travail sous forme de runbook
- En production, un terminal qui inspecte uniquement l’état existant sans affecter l’état de la machine
Stratégie de construction par étapes
-
Étape 1 : sémantique transactionnelle (transactional semantics)
- Commencer la refonte du terminal par l’émulateur de terminal est une mauvaise approche
- Les utilisateurs sont attachés à leur émulateur ainsi qu’à sa configuration, son apparence et ses raccourcis clavier
- Le coût de changement d’émulateur est élevé
- Il vaut mieux commencer à la couche CLI
- Les programmes CLI sont faciles à installer et à exécuter, avec un coût de changement très faible
- On peut les utiliser ponctuellement sans changer tout le workflow
- Écrire une CLI mettant en œuvre une sémantique transactionnelle pour le terminal
- Interface du type
transaction [start|rollback|commit] - Tout ce qui est exécuté après
startpeut être annulé - Rien qu’avec cela, on peut déjà bâtir toute une activité
- Interface du type
- Commencer la refonte du terminal par l’émulateur de terminal est une mauvaise approche
-
Étape 2 : sessions persistantes (Persistent Sessions)
- Une fois la sémantique transactionnelle obtenue, séparer la persistance de tmux et de mosh
- Pour obtenir la persistance du PTY, il faut adopter un modèle client/serveur
- Le noyau suppose que les deux côtés du PTY seront toujours connectés
- Une mise en œuvre simple est possible via une commande comme alden ou une bibliothèque similaire, sans affecter l’émulateur de terminal ni les programmes exécutés dans la session PTY
- Pour obtenir le scrollback, le serveur stocke indéfiniment les entrées/sorties puis les rejoue lors de la reconnexion du client
- L’émulateur de terminal fournit un scrollback natif traité comme n’importe quelle autre sortie
- La relecture et la reprise sont possibles depuis n’importe quel point de départ
- Cela nécessite l’analyse des séquences d’échappement ANSI, mais reste faisable avec suffisamment de travail
- Pour une reprise réseau façon mosh, utiliser Eternal TCP (éventuellement construit sur QUIC pour gagner en efficacité)
- Séparer la persistance du PTY de celle de la connexion réseau
- Eternal TCP est une simple optimisation : on peut construire cela au-dessus d’un script bash qui exécute en boucle
ssh host eternal-pty attach
- À ce stade, comme avec tmux, plusieurs clients peuvent se connecter à une même session terminal, tandis que la gestion des fenêtres reste du ressort de l’émulateur
- Pour une gestion intégrée des fenêtres, l’émulateur pourrait utiliser un protocole comme tmux -CC à la manière d’iTerm
- Toutes les parties de cette étape peuvent être réalisées en parallèle, indépendamment de la sémantique transactionnelle, mais cela ne suffit pas encore pour bâtir l’activité
-
Étape 3 : RPC structurée
- Repose sur le modèle client/serveur
- Si un serveur s’interpose entre l’émulateur de terminal et le client, on peut implémenter des fonctions comme le taggage des E/S avec des métadonnées
- Il devient possible d’ajouter un horodatage à toutes les données
- De distinguer les entrées des sorties
- xterm.js fonctionne de manière similaire
- Combiné à l’intégration du shell, cela permet de distinguer au niveau des données l’invite du shell de la sortie du programme
- On obtient un journal structuré de la session terminal
- Relecture du journal comme un enregistrement à la manière d’asciinema
- Transformation de l’invite du shell sans réexécuter toutes les commandes
- Import dans Jupyter Notebook ou Atuin Desktop
- Sauvegarde de commandes pour les réexécuter plus tard sous forme de script
- Le terminal devient de la donnée
-
Étape 4 : frontend de type Jupyter
- C’est la première étape qui touche réellement à l’émulateur de terminal, et c’est volontairement la dernière
- Car c’est là que le coût de changement est le plus élevé
- Fournir une bonne UI en exploitant toutes les fonctions construites auparavant
- La CLI
transactionn’est alors plus nécessaire, sauf si l’on veut des transactions imbriquées- Toute la session terminal démarre par défaut comme une transaction
- Comme tous les éléments ont été réunis, toutes les fonctions dérivées mentionnées plus haut deviennent disponibles
- C’est la première étape qui touche réellement à l’émulateur de terminal, et c’est volontairement la dernière
Conclusion
- Cette architecture est audacieuse, ambitieuse et devrait demander jusqu’à environ 10 ans pour être entièrement construite
- Il faut avancer avec patience, étape par étape
- L’auteur espère que ce texte inspirera quelqu’un à commencer à la construire lui-même
1 commentaires
Commentaires sur Hacker News
En lisant tout le billet, j’ai d’abord eu l’impression d’une simple liste de souhaits façon NIH
alors qu’il existe déjà plusieurs alternatives capables de remplacer le terminal, qui ne sont même pas mentionnées.
Par exemple, Emacs est une VM basée sur Lisp, où il est facile de redéfinir des fonctions, et les commandes sont des fonctions documentées. La sortie est gérée via des buffers, et plusieurs fenêtres et frames peuvent être disposées en mosaïque. On peut conserver un usage CLI tel quel (
vterm,eat, etc.) ou passer à un flux de type REPL (shell-mode,eshell, etc.). Il gère aussi le graphique, même si ce n’est pas un contexte 2D completUn autre exemple est Acme, proche d’Emacs mais conçu comme un environnement textuel interactif où tout texte peut devenir une commande. Smalltalk suit une philosophie similaire, mais se rapproche davantage d’un IDE
J’utilise GPTel dans Emacs pour découper automatiquement de vieux PDF de manuels de latin, puis les convertir via OCR au format org-mode. Résultat : quand je sélectionne un mot, je peux lancer immédiatement une recherche dans le dictionnaire, et quand je sélectionne une phrase, un LLM en fait l’analyse grammaticale. Un éditeur de texte des années 1970 est ainsi devenu une plateforme d’apprentissage futuriste
Des plateformes comme Emacs, Jupyter ou VSCode sont puissantes, mais ce sont davantage des plateformes à personnaliser que de véritables applications finies.
S’il y a une vraie innovation, elle devrait être distribuée sous une forme facilement reproductible, comme un conteneur Docker ou un exécutable, plutôt que reposer sur une configuration complexe
Je me demande si le successeur du terminal doit nécessairement rester fondé sur le texte
Le terminal du futur pourrait être une API, avec des appels distants via OAuth. L’entrée et la sortie ne seraient alors plus forcément du texte CLI.
On pourrait plutôt passer à des entrées/sorties orientées objets, où commandes et structures de données seraient explorables via API.
Le terminal est un héritage des années 1970, et aujourd’hui on peut tout à fait imaginer de meilleures alternatives
Si on ajoute une sortie JSON, on peut construire des pipelines avec des outils comme
jq.Cette simplicité est un avantage, dans l’esprit de la philosophie « worse is better », qui lui a permis d’évoluer pendant des décennies
Si l’on échangeait des objets auto-descriptifs comme dans PowerShell, on pourrait obtenir une composition bien plus puissante
J’ai rassemblé des exemples à ce sujet dans mon billet de blog
On perd le flux intuitif fondé sur les commandes, et il faut mémoriser la structure des API.
Une autocomplétion basée sur l’IA et des fonctions d’exploration de structures d’objets pourraient compenser cette faiblesse
https://www.nushell.sh/
Mais pour qu’un terminal évolué basé sur le texte reste intéressant, il faut encore des propositions concrètes et imaginables
Si le terminal a survécu jusqu’à aujourd’hui, c’est grâce à sa compatibilité et à ses possibilités d’automatisation
Il est plus facile à script-er qu’une GUI, et tout y est reproductible et recherchable
À une époque, le basculement d’écran alt-screen dans Neovim m’agaçait, mais ce genre de détails UX compte aussi
Je suis tombé amoureux de l’informatique deux fois : la première en découvrant un ordinateur, la seconde en apprenant le terminal
Parmi les projets liés, on peut citer
J’ai mené une expérimentation similaire il y a 18 mois dans Windows Terminal
C’est documenté dans ce commentaire GitHub
Mais après avoir essayé Polyglot Notebooks, j’ai trouvé cela bien plus naturel, et j’ai basculé dessus
Remplacer le backend impératif par un kernel Jupyter et l’utiliser comme un document interactif de style notebook est beaucoup plus efficace
J’avais autrefois créé un projet appelé TopShell, un shell+terminal fondé sur la programmation fonctionnelle
https://github.com/topshell-language/topshell#readme
Il y a du potentiel, mais il reste encore beaucoup de travail avant d’en faire une alternative complète
Je cherchais un terminal capable d’afficher des images ou des vidéos
Ce serait bien d’avoir un terminal qui fonctionne tout simplement comme un navigateur.
Par exemple, lancer directement quelque chose d’interactif avec une commande comme
browser google.com/mapsfbi,omxplayer, etc.) que du terminal lui-mêmeLa proposition consiste à étendre le pseudo-terminal (PTY) en y ajoutant un canal hors bande basé sur JSON-RPC
Les séquences d’échappement existantes ont beaucoup de limites.
Cette approche permettrait une transition progressive et rétrocompatible.
On pourrait négocier les fonctionnalités comme avec LSP ou MCP, et le kernel n’aurait qu’à fournir le canal
Ainsi, les pipelines et redirections continuent de fonctionner tels quels, tout en conservant la sortie colorée