8 points par GN⁺ 2025-11-13 | 1 commentaires | Partager sur WhatsApp
  • 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
  • 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
      • 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
    • 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
  • 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 start peut être annulé
      • Rien qu’avec cela, on peut déjà bâtir toute une activité
  • É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 transaction n’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

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

 
GN⁺ 2025-11-13
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 complet
    Un 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

    • Emacs dispose de Org-mode et d’org-babel, ce qui lui permet de fonctionner comme un notebook Jupyter. Il peut même communiquer avec les kernels Jupyter
      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
    • J’aimerais en savoir plus sur Acme. C’est difficile à chercher.
      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
    • À mon avis, le point essentiel du billet est d’ouvrir le modèle de données du terminal. L’important, c’est qu’on puisse ensuite construire diverses fonctionnalités par-dessus
    • Ce qu’Emacs a d’unique, c’est son indépendance vis-à-vis de l’interface. Une application écrite en Elisp fonctionne à l’identique dans le terminal et en GUI. J’écrivais déjà du Elisp dans un terminal il y a 20 ans, et les utilisateurs GUI ne voyaient absolument aucune différence. Il n’existe pas d’autre plateforme comme celle-là
  • 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

    • En réalité, le terminal n’est pas centré sur le texte, mais sur un flux bidirectionnel de jetons. C’est cette simplicité qui rend possible la composition à la Unix.
      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
    • Je partage aussi la critique des limites des entrées/sorties standard du CLI. Le fait que les données et leur représentation soient une seule et même chose limite la composabilité.
      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
    • PowerShell est intéressant, mais il a l’inconvénient de devenir de plus en plus proche d’un langage de programmation.
      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
    • J’utilise aussi volontiers Nushell. C’est plus propre que PowerShell, et sans dépendance à Microsoft
      https://www.nushell.sh/
    • Il existe déjà des alternatives au terminal non fondées sur le texte.
      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

    • Arcan — propose un nouveau protocole pour les applications TUI
    • Shelter — un shell de système de fichiers branchable comme Git
    • Shelter nécessite des snapshots du système de fichiers, mais l’idée est vraiment excellente
    • À mon sens, un billet qui ne mentionne pas Arcan est incomplet. C’est déjà utilisable
      • Je n’en avais jamais entendu parler, mais c’est vraiment intéressant. Merci pour le lien
  • 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

    • Moi aussi, je cherchais un système de ce genre. Cela semble mieux adapté aux LLM et aux environnements de travail personnels
    • Intégrer le concept de notebook dans Windows Terminal est une idée vraiment excellente. J’aimerais voir davantage d’initiatives de ce type
  • 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/maps

    • Mais ce type de fonctionnalité relève plutôt d’un programme distinct (fbi, omxplayer, etc.) que du terminal lui-même
  • La 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

    • JSON est mal adapté à cet usage. Des formats binaires comme DER ou SDSER sont plus efficaces
    • Une approche moderne consiste à envoyer les messages destinés à l’utilisateur sur stderr, et le JSON exploitable par machine sur stdout
      Ainsi, les pipelines et redirections continuent de fonctionner tels quels, tout en conservant la sortie colorée