lazyshell

Utilisation

Lancez lazyshell dans un terminal. Tab bascule le focus entre le panneau des sessions et le panneau de sortie, / faisant la même chose de façon directionnelle ; ? ouvre à tout moment une aide listant chaque raccourci en vigueur, y compris ceux que vous avez remappés.

Les deux panneaux

À gauche, la liste des sessions : une ligne par session, avec son état. À droite, le panneau de sortie : l'écran vivant de la session sélectionnée. Sur un terminal étroit, la disposition passe en mode portrait et empile les deux panneaux au lieu de les juxtaposer (seuils réglables : portrait_max_width et portrait_min_height).

Chaque panneau affiche ses touches les plus utiles sur la ligne basse de son cadre. La liste se raccourcit à ce que la largeur permet, et celle du panneau de sortie s'adapte à ce qu'il est en train de faire : le retour au pass-through quand verrouillé, le verrouillage quand en pass-through, aucun indice de défilement quand une application plein écran tient la session.

Touches — panneau des sessions

ToucheAction
q / Ctrl+CQuitter lazyshell
TabChanger de panneau actif
Aller au panneau de sortie
?Afficher l'aide
j / Session suivante
k / Session précédente
nNouvelle session
NNouvelle session en demandant son nom (vide = nom automatique)
MNouvelle session dans un dossier choisi
cDupliquer la session sélectionnée
rRenommer la session sélectionnée
RRelancer une session sortie
x / dTuer la session sélectionnée
DSupprimer définitivement la session (retirée du panneau)
wExporter l'historique de la session vers un fichier
bMarquer / démarquer la session pour la diffusion
BSauter à la prochaine session d'agent bloquée
gAffecter la session à un groupe, choisi dans une liste ou tapé
GN'afficher que le groupe de la session ; à nouveau pour annuler
AMarquer / démarquer tout le groupe pour la diffusion
XTuer toutes les sessions du groupe
WRelancer les sessions terminées du groupe
/Filtrer la liste des sessions
zZoom : le panneau de sortie prend tout l'écran
[ / ]Onglet précédent / suivant du panneau de sortie
F12Afficher / masquer le panneau de debug (ne fait quelque chose qu'avec --debug)

Touches — panneau de sortie

Quand le panneau de sortie a le focus, ces touches s'appliquent à la place :

ToucheAction
Revenir à la liste des sessions (seulement quand verrouillé)
Ctrl+O (configurable)Verrouiller le panneau : sortir du pass-through pour défiler, chercher ou copier
Esc EscPareil, sans touche à apprendre : deux Échap d'affilée, en moins de 400 ms
i / EntréeReprendre la saisie : retour au pass-through (utile seulement une fois verrouillé)
PgUp / PgDnDéfiler d'un écran dans l'historique
Ctrl+U / Ctrl+DDéfiler d'un demi-écran
/Rechercher dans l'historique ; n / N pour l'occurrence suivante / précédente
vDémarrer (ou étendre) une sélection de lignes — mode copie
y ou un second vCopier la sélection (OSC 52, ou la commande de repli configurée)
{ / }Sauter au prompt précédent/suivant (nécessite l'intégration shell OSC 133)
YCopier la sortie de la dernière commande terminée (nécessite l'intégration shell OSC 133)
EscQuitter la recherche ou annuler la sélection en cours

Qui a le clavier

Le pass-through est l'état par défaut dès qu'une session est sélectionnée — rien à presser avant. Déplacer la sélection avec j / k, un clic ou la molette reporte l'état courant : atterrir sur une autre session en étant verrouillé vous y dépose verrouillé ; y atterrir déverrouillé vous y dépose prêt à taper. L'exception est une session dont l'état a été tranché — une session pour laquelle un fichier de projet a déclaré locked: (une command: déclarée démarre verrouillée par défaut), ou une session que vous avez verrouillée ou déverrouillée à la main : ce choix est mémorisé par session et restauré quand vous y revenez. Au-delà, lazyshell ne change le drapeau tout seul qu'aux deux moments où l'intention est sans ambiguïté :

Déplacer la sélection avec j / k est de la navigation, et ne donne jamais le clavier au shell. Rien ne se produit derrière une popup : une confirmation ou l'aide garde le focus qu'elle a.

Lire la liste des sessions

Chaque session tient sur une ligne : une gouttière de quatre colonnes, puis son nom, son état, son PID, et soit le titre de terminal que le shell a posé (en général la commande en cours), soit son répertoire de travail.

MarqueurSignification
!La session a sonné (bell) pendant que vous regardiez ailleurs. Effacé à la sélection.
#Une application plein écran (vim, htop, less) tient la session. Affiché [ALT] dans la barre d'état pour la session sélectionnée.
La session a produit de la sortie alors qu'elle n'était pas à l'écran. Effacé à la sélection.
+La session est marquée pour la diffusion — voir plus bas.
· État d'une session d'agent IA : au repos, en travail, bloquée (elle vous attend), terminée.
✗ <code>La dernière commande d'une session sans agent a échoué — voir l'intégration shell OSC 133. Jamais affiché en même temps que le marqueur d'état d'une session d'agent ci-dessus.
↻<compteur>Une session déclarant restart: a eu besoin d'au moins un redémarrage automatique. Effacé dès qu'un redémarrage tient assez longtemps pour être considéré comme sain à nouveau.

Tous ces marqueurs sont configurables, et un marqueur mis à "" disparaît — voir la référence.

Onglets du panneau de sortie

Le panneau de sortie porte trois onglets, changés avec [ / ] ou d'un clic sur la barre de titre :

terminal

L'écran vivant de la session : c'est l'onglet par défaut, et le seul où le pass-through existe.

ressources

Ce que la session consomme : pourcentage CPU, mémoire résidente, threads, I/O disque — avec une sparkline collée à chaque chiffre et un graphe braille de quatre lignes pour le CPU du process d'avant-plan. La portée mesurée est le shell plus le leader du groupe d'avant-plan, jamais tout l'arbre : ce que vous regardez, c'est claude ou vim, pas bash.

L'échantillonnage tourne en arrière-plan pour toutes les sessions, que l'onglet soit ouvert ou non (perf.refresh_interval_ms) : une courbe ne vaut d'être regardée que si elle remonte plus loin que l'instant où vous l'avez ouverte. Ce qu'un système ne sait pas répondre est marqué indisponible, jamais rapporté à zéro — sur macOS, le nombre de threads et l'I/O disque en font partie.

environnement

L'environnement au lancement de la session, trié et défilable. Par défaut, la valeur des variables dont le nom ressemble à un identifiant (TOKEN, SECRET, PASSWORD, AUTH, ..._KEY) est masquée : le panneau est aussi partageable qu'une capture d'écran de lui-même. env_tab.mask_secrets: false montre les vraies valeurs.

Quitter l'onglet terminal désarme le pass-through et le mode copie. L'offset de défilement, lui, n'est pas remis à zéro : un aller-retour vous ramène là où vous en étiez.

Limite connue. On ne peut pas cliquer un onglet depuis le pass-through : gocui consulte la gestion souris de la vue avant d'arriver à la barre d'onglets. Sortir du pass-through d'abord (Ctrl+O) est de toute façon le préalable.

Recherche et copie

/ dans le panneau de sortie cherche dans l'historique, n et N parcourent les occurrences, Esc sort. v démarre une sélection de lignes, y (ou un second v) la copie.

La copie passe par OSC 52, c'est-à-dire par le terminal hôte : elle fonctionne donc aussi à travers une connexion SSH. Il n'existe aucun moyen de détecter si un terminal comprend OSC 52, donc pour ceux qui ne le comprennent pas, clipboard.fallback_command est un interrupteur manuel : la commande est exécutée avec le texte sur son entrée standard.

Pendant qu'une application plein écran est aux commandes, le défilement dans l'historique — et donc le mode copie, qui sélectionne dans ce même historique — est désactivé : l'écran alterné n'alimente pas l'historique, et ces touches appartiennent à l'application.

Groupes

Une session appartient à un groupe, ou à aucun. Les sessions groupées sont affichées sous une ligne d'en-tête qui nomme le groupe, ce qui rend lisible une liste de huit sessions d'agents IA : on voit d'un coup d'œil lesquelles travaillent sur le même chantier.

Les en-têtes sont purement visuels — ni sélectionnables, ni cliquables, ni repliables, et j / k passent directement par-dessus. L'ordre est : les groupes déclarés par le fichier de projet, dans l'ordre où il les déclare, puis les groupes créés à chaud dans leur ordre de première apparition, puis les sessions sans groupe en dernier. Sans aucun groupe, il n'y a aucun en-tête : la liste est exactement celle, plate, qu'elle a toujours été.

Déclarez les groupes dans le fichier de projet, ou posez-en un à tout moment avec g, qui ouvre une liste : tous les groupes déjà utilisés, plus « sans groupe » et « + nouveau groupe… » pour un nom encore absent. Quatre touches agissent ensuite sur tout le groupe de la session sélectionnée : A y diffuse, X le tue, W relance celles de ses sessions qui se sont terminées, et G restreint la liste à lui. Une action de groupe atteint toujours tous ses membres, y compris ceux qu'un filtre masque — « tuer le groupe » veut dire le groupe, pas la partie visible à l'écran.

W saute les sessions encore en cours plutôt que de refuser d'agir : un groupe en partie terminé et en partie vivant est le cas normal. Contrairement au R d'une seule session, il ne vous donne pas le clavier ensuite. Les agents pilotent tout cela par le socket de contrôle.

Diffusion (broadcast)

Marquez deux sessions ou plus avec b, puis attachez-vous à l'une d'elles (i / Entrée) : chaque frappe part désormais vers toutes à la fois, pas seulement vers celle que vous regardez.

La barre d'état porte un avertissement ⚠ BROADCAST → N sessions tant que le mode est armé, devant tout ce qu'elle dirait autrement. C'est le seul état où une frappe anodine peut atteindre plusieurs shells dans votre dos, donc il reste visible quoi qu'il arrive.

Démarquer une session (b à nouveau) la sort du lot ; la diffusion s'arrête d'elle-même dès qu'il en reste moins de deux marquées.

Souris

Activée par défaut. Un clic sélectionne une session — c'est de la navigation, donc cela ne donne pas le clavier au shell ; un double-clic, si. La molette fait défiler le contenu du panneau de sortie, et jamais l'historique de commandes du shell : lazyshell traite la molette lui-même au lieu de laisser le terminal la transformer en flèches, ce qui, à une invite, rappellerait la commande précédente au lieu de défiler. Cliquer-glisser sélectionne des lignes, puis y copie — relâcher le bouton ne copie rien tout seul.

Un programme dans une session ne reçoit la souris qu'une fois qu'il l'a demandée (vim avec set mouse=a, htop) ; un shell ou une CLI d'agent IA ne la demande jamais, donc la molette continue de faire défiler l'historique. mouse.forward_to_app: false garde la souris pour lazyshell quoi qu'il arrive.

Le prix de la souris : Shift+↑ et Shift+↓ ne sont plus transmis à une session. gocui donne à ces touches et aux boutons de la souris les mêmes valeurs, donc les deux ne peuvent pas fonctionner ensemble — voir l'ADR 0003. mouse.enabled: false les récupère, au prix des gestes ci-dessus.

Intégration shell (OSC 133)

Un shell qui émet les marques standard OSC 133;A/B/C/D autour de chaque prompt et de chaque commande — zsh, fish et bash le supportent tous, en général derrière une ligne à ajouter au fichier de démarrage du shell (chercher « shell integration » ou « semantic prompt » dans la doc de votre shell/prompt) — débloque trois choses sans configuration supplémentaire :

Rien ici n'a besoin d'un hook câblé comme pour l'état des agents : un shell avec l'intégration activée émet ces marques tout seul, et un shell sans elle ne déclenche simplement jamais rien de tout ça — aucun marqueur à désactiver, aucune clé de config à éteindre, rien à détecter du tout. Seul le glyphe de la liste des sessions est configurable (markers.command_failed, voir la référence) ; le reste n'a ni glyphe ni touche à remapper en dehors des trois identifiants d'action (jump_prev_prompt, jump_next_prompt, copy_last_output) dans la map de raccourcis.

Les marques sont suivies par session, survivent à la troncature du scrollback (voir l'ADR 0008 pour le comment), et sont suspendues tant qu'une application plein écran tient la session — le même principe « ça signale, ça ne change jamais de mode tout seul » que la souris et le mode copie ci-dessus : rien de ce que tape vim ou htop n'est jamais pris pour un prompt ou une borne de commande du shell.

Mode debug

Une fois que lazyshell tient le terminal, il n'y a plus nulle part où écrire : stderr est inutilisable et la barre de statut fait une ligne. --debug est le moyen de voir ce que l'interface croit qu'il se passe.

lazyshell --debug

Il fait deux choses à la fois. Il écrit à la suite de ~/.config/lazyshell/debug.log — à côté de config.yml, en 0600, jamais tronqué, pour pouvoir comparer deux lancements — et il ouvre un petit panneau en haut à droite du panneau de sortie qui affiche les derniers évènements en direct. F12 le masque et le réaffiche ; le fichier continue d'être écrit dans les deux cas.

ÉtiquetteCe que c'est
KEYUne frappe telle que le panneau de sortie l'a reçue : son nom, les valeurs brutes key/ch/mod, ce que la normalisation en a fait quand les deux diffèrent, et le mode dans lequel elle a atterri
ACTUne action qui est partie — un raccourci clavier, un geste souris, ou une des branches que l'éditeur du panneau de sortie traite lui-même
EVTSession créée / tuée / terminée, transitions d'état d'un agent, changements de sélection et d'onglet, redimensionnements

Deux choses à savoir avant de lire un log. Les touches ne sont enregistrées que pour le panneau de sortie : gocui n'offre aucun hook clavier global, donc une touche pressée sur le panneau des sessions apparaît en ligne ACT si elle est liée, et pas du tout sinon. Et F12 n'atteint plus la session tant que lazyshell tourne, mode debug ou non — c'est un raccourci global ; remapper toggle_debug si quelque chose que vous lancez en a besoin.

Le fichier contient toutes les frappes tapées dans un shell, y compris à l'invite de mot de passe d'un programme qui ne coupe pas l'écho. C'est la raison du 0600 ; le supprimer une fois qu'on n'en a plus besoin.