Files
vmux/.planning/research/PITFALLS.md
2026-03-23 11:25:05 +01:00

17 KiB

Pitfalls Research

Domain: Session monitoring / terminal state detection / i3 IPC integration Researched: 2026-03-23 Confidence: MEDIUM-HIGH

Critical Pitfalls

Pitfall 1: Session state inference from JSONL is fragile and undocumented

What goes wrong: La structure des fichiers JSONL de Claude Code (~/.claude/projects/<encoded-cwd>/*.jsonl) n'est pas une API stable. Le format change entre versions sans avertissement. Les champs (tool_use, tool_result, role, content.type) peuvent etre renommes, restructures ou supprimes. Pire : un tool_use sans tool_result correspondant peut signifier "en cours" ou "plante", sans moyen de distinguer les deux.

Why it happens: Les fichiers JSONL sont un detail d'implementation de Claude Code, pas un contrat d'API. Les outils communautaires (claude-sessions-monitor, clog, claude-JSONL-browser) parsent tous ce format, mais aucun n'a de garantie de stabilite.

How to avoid:

  • Abstraire le parsing JSONL derriere une interface. Un seul module session/parser.go qui convertit le JSONL en structures internes. Un changement de format = un seul fichier a modifier.
  • Detecter l'etat "attend input" via la combinaison : dernier message est role: "assistant" + pas de tool_use en cours + le process Claude tourne encore. Ne pas se fier a un seul signal.
  • Ajouter un fallback process-based : si le JSONL est ambigu, verifier via ps si le process Claude ecrit encore (check du mtime du fichier JSONL).

Warning signs:

  • Les tests de parsing echouent apres une mise a jour de Claude Code.
  • L'etat affiche ("travaille") ne correspond pas a la realite observee dans le terminal.

Phase to address: Phase 1 (detection des sessions). Concevoir l'abstraction des le depart.


Pitfall 2: Les fichiers JSONL geants font exploser la memoire

What goes wrong: Les sessions longues produisent des fichiers JSONL de plusieurs Go (cas documente : 3.8 Go). Charger ou scanner ces fichiers en entier pour determiner l'etat courant consomme toute la RAM disponible. Claude Code lui-meme souffre de ce probleme (issue #22365).

Why it happens: Les JSONL grossissent sans limite a cause des progress ticks dupliques, sorties de commandes volumineuses et accumulation de metadata de sous-agents. Un monitoring naif qui lit tout le fichier a chaque poll va reproduire le meme probleme que Claude Code.

How to avoid:

  • Ne JAMAIS charger un JSONL en entier. Lire uniquement les N dernieres lignes (tail-like) pour determiner l'etat courant. En Go : io.SeekEnd puis remonter jusqu'a trouver suffisamment de lignes.
  • Seuil d'alerte : ignorer ou traiter differemment les fichiers > 50 Mo.
  • Utiliser sessions-index.json comme source primaire de metadata (timestamps, branches, resumes) au lieu de parser chaque JSONL.

Warning signs:

  • La consommation memoire de vmux grimpe avec le temps.
  • Le temps de rafraichissement se degrade apres quelques heures.

Phase to address: Phase 1. Implementer le tail-read des le premier prototype, pas en optimisation tardive.


Pitfall 3: i3 IPC event subscription race conditions et deadlocks

What goes wrong: Deux problemes documentes avec l'IPC i3 :

  1. Deadlock si les events ne sont pas consommes : i3 queue les messages sortants avec un timeout de 10 secondes. Si le client ne lit pas les events assez vite, la connexion est terminee. Avec la lib Go officielle (go.i3wm.org/i3/v4), le EventReceiver DOIT etre lu en boucle via Next() sinon i3 deadlock quand le buffer Unix socket se remplit.
  2. Race conditions entre events et requetes : des que l'on subscribe a un event, l'ordre de traitement des requetes n'est plus garanti. Un event workspace peut arriver avant la reponse a GET_WORKSPACES.

Why it happens: L'IPC i3 utilise des sockets Unix sans backpressure. Le protocole n'est pas versionne et change a chaque release. La lib Go gere le retry automatique (10s) mais l'EventReceiver n'est PAS thread-safe.

How to avoid:

  • Dedier une goroutine exclusivement a la consommation d'events (recv.Next() en boucle). Ne jamais bloquer cette goroutine.
  • Separer les sockets : un pour les requetes (get_workspaces, get_tree), un pour les subscriptions d'events. La lib Go le gere, mais il faut comprendre que Subscribe() cree une connexion separee.
  • Utiliser i3.Restart() au lieu de RunCommand("restart") (sinon retry infini).
  • Gerer le cas ou i3 redemarrage : tous les etats IPC sont reinitialises, toutes les subscriptions perdues sauf une socket.

Warning signs:

  • vmux se fige apres un certain temps.
  • Les events workspace ne sont plus recus apres un i3 restart ou i3 reload.

Phase to address: Phase 2 (integration i3). Test specifique : laisser vmux tourner, faire i3 reload, verifier que les events reprennent.


Pitfall 4: Detection de process Claude Code non fiable par nom de process

What goes wrong: Claude Code peut s'installer via npm (process Node.js) ou via l'installeur natif (binaire claude). Selon la methode, ps aux | grep claude donne des resultats differents. Avec npm, le process apparait comme node parmi des dizaines d'autres processes Node.js. Le nom change entre versions.

Why it happens: Il n'y a pas d'identifiant stable pour un process Claude Code. Pas de PID file, pas de socket nommee, pas de dbus service. L'outil est concu pour etre interactif dans un terminal, pas pour etre observe de l'exterieur.

How to avoid:

  • Strategie primaire : lister les fichiers dans ~/.claude/projects/ et correler avec les processes actifs via /proc/[pid]/cwd pour trouver les correspondances.
  • Chercher le process par ses arguments de ligne de commande (/proc/[pid]/cmdline) plutot que par son nom.
  • Croiser avec le mtime des fichiers JSONL : si le fichier est ecrit recemment (< 5s), la session est probablement active.
  • Fallback : scanner les fenetres i3 dont le titre contient "claude" ou un pattern reconnaissable.

Warning signs:

  • Des sessions sont detectees comme "idle" alors qu'elles travaillent.
  • Apres une mise a jour de Claude Code, la detection casse silencieusement.

Phase to address: Phase 1 (detection). Implementer au moins deux signaux independants (fichier + process) pour la detection d'etat.


Pitfall 5: fsnotify/inotify ne garantit pas la correction pour le watch recursif

What goes wrong: Le monitoring des fichiers JSONL via inotify (Go fsnotify) a des failles fondamentales :

  1. Buffer overflow : les events sont delivres via un buffer de taille fixe, sans mecanisme de backpressure. Des events peuvent etre perdus silencieusement.
  2. Race TOCTTOU : entre la reception d'un event de creation et l'ouverture du fichier, le fichier peut avoir ete supprime/renomme.
  3. Pas d'ordering garanti entre watchers multiples : si on watch ~/.claude/projects/ et ses sous-repertoires, l'ordre des events entre watchers differents n'est pas lineaire.

Why it happens: C'est une limitation fondamentale de l'API inotify Linux (documentee en detail par Andy Wingo). La perte d'events est "built-in" au design.

How to avoid:

  • Utiliser inotify comme signal de "quelque chose a change", pas comme source de verite. Toujours re-scanner l'etat apres un event.
  • Ajouter un poll periodique (toutes les 2-3 secondes) en complement de inotify. L'inotify sert a reduire la latence, le poll sert de filet de securite.
  • Ne PAS tenter un watch recursif complexe. Watcher uniquement le repertoire racine ~/.claude/projects/ et les fichiers JSONL specifiques deja identifies.
  • Attention aux limites systeme : chaque watch consomme un file descriptor. Verifier fs.inotify.max_user_watches.

Warning signs:

  • Des sessions apparaissent/disparaissent avec du retard ou pas du tout.
  • Le nombre de watchers augmente sans limite.

Phase to address: Phase 1. Choisir l'architecture "inotify + poll" des le depart. Ne pas partir sur du inotify pur en pensant migrer plus tard.


Pitfall 6: Associer un process Claude a un workspace i3 est plus dur qu'il n'y parait

What goes wrong: La correspondance "session Claude Code <-> workspace i3" semble triviale (meme repertoire de travail) mais echoue dans plusieurs cas :

  • Un terminal peut etre deplace d'un workspace a un autre sans que le cwd change.
  • Plusieurs terminaux dans le meme workspace peuvent pointer vers des projets differents.
  • Le window title du terminal ne contient pas forcement le chemin du projet.
  • Apres un i3 reload, les metadata des conteneurs sont preservees mais les connexions IPC sont perdues.

Why it happens: i3 gere des fenetres (containers), pas des sessions applicatives. Il n'y a pas de lien natif entre un workspace i3 et un repertoire de travail. La correspondance doit etre construite manuellement.

How to avoid:

  • Approche recommandee : utiliser l'arbre i3 (get_tree) pour lister les fenetres, croiser le PID de la fenetre (window_properties.instance ou _NET_WM_PID) avec /proc/[pid]/cwd pour trouver le repertoire de travail.
  • Alternative : exploiter les conventions de nommage de Pierre (worktrees = branches = noms de workspace). Matcher le nom du workspace avec le nom de la branche git detectee dans la session.
  • Event window::move pour detecter les deplacements de fenetres entre workspaces.
  • Bug i3 connu (fixe en 2018) : pas d'event window::focus quand on switch depuis un workspace vide. Verifier la version d'i3.

Warning signs:

  • vmux affiche "workspace 3" pour une session qui est maintenant sur le workspace 5.
  • Le switch vers un workspace n'amene pas a la bonne fenetre Claude.

Phase to address: Phase 2 (integration i3). Tester systematiquement les cas de deplacement de fenetres.


Technical Debt Patterns

Shortcut Immediate Benefit Long-term Cost When Acceptable
Parser JSONL couple au format actuel Rapide a implementer Casse a chaque mise a jour Claude Code Jamais, abstraire des le depart
Polling seul (sans inotify) Simple, correct Latence 2-3s sur la detection d'etat MVP Phase 1 uniquement
Lecture complete du JSONL Code simple, pas de seek OOM sur sessions longues Jamais
Hardcoder le nom de process "claude" Detection rapide Casse si installation npm ou changement de binaire Jamais
Stocker l'association workspace en cache sans invalider Moins de requetes i3 Desynchronisation apres deplacement de fenetre OK si invalide sur event window::move

Integration Gotchas

Integration Common Mistake Correct Approach
i3 IPC events Ne pas consommer les events assez vite Goroutine dediee, jamais de traitement bloquant dans la boucle d'events
i3 RunCommand("restart") Appeler via RunCommand (retry infini) Utiliser i3.Restart() de la lib Go
i3 get_tree Parcourir l'arbre entier a chaque refresh Cacher le resultat, invalider sur events window::new, window::close, window::move
Claude JSONL Parser le fichier entier Tail-read des N dernieres lignes
sessions-index.json Ignorer ce fichier et parser chaque JSONL L'utiliser comme index primaire pour les metadonnees
/proc/[pid]/cwd Ne pas gerer les erreurs de permission Les process d'autres utilisateurs retournent EACCES, gerer gracieusement

Performance Traps

Trap Symptoms Prevention When It Breaks
Scan complet de ~/.claude/projects/ a chaque tick CPU spike periodique Index incrementiel via inotify + rescan periodique > 20 projets avec historique
Lecture entiere des JSONL pour l'etat RAM qui grimpe, freeze Tail-read (derniers 4 Ko) Fichiers > 50 Mo
get_tree a chaque rafraichissement Latence perceptible Cache + invalidation par events > 30 fenetres ouvertes
Polling agressif (< 500ms) CPU constant a 5-10% Poll 2-3s + inotify pour la reactivite Toujours, meme avec peu de sessions
Ouverture de N watchers inotify File descriptors epuises Watcher sur le repertoire parent, pas par fichier > 50 sessions/projets

Security Mistakes

Mistake Risk Prevention
Lire les JSONL d'un autre utilisateur via /proc Violation de vie privee, fuite de tokens API vmux ne monitore QUE les sessions de l'utilisateur courant ($HOME)
Afficher le contenu des messages Claude en clair Exposition de code/secrets dans le preview Tronquer, pas de secrets, afficher seulement le dernier message assistant
Executer des commandes i3 basees sur du contenu JSONL non sanitize Injection de commandes i3 Ne jamais interpoler du contenu JSONL dans des commandes i3

UX Pitfalls

Pitfall User Impact Better Approach
Afficher "idle" quand la session charge (JSONL pas encore ecrit) L'utilisateur ignore une session qui demarre Etat "starting" base sur l'age du process vs le dernier write JSONL
Notification a chaque changement d'etat, meme rapide Spam de notifications quand Claude enchaine les tool_use Debounce : notifier seulement apres 3s dans l'etat "attend input"
Forcer le focus i3 automatiquement Interrompt le travail en cours Notifier + keybind pour switcher volontairement
Ne pas montrer depuis combien de temps la session attend Pas de priorisation possible Afficher le temps d'attente relatif ("il y a 2 min")
Preview trop long ou trop technique L'utilisateur ne comprend pas ce que la session fait Extraire le dernier message "humain" (pas tool_result), tronquer a 1-2 lignes

"Looks Done But Isn't" Checklist

  • Detection de sessions : Fonctionne avec l'installeur natif ET npm. Tester les deux.
  • Etat "travaille" : Verifier que le process ecrit encore (mtime), pas seulement que le dernier message est tool_use.
  • i3 integration : Tester apres i3 reload et i3 restart. Les subscriptions survivent-elles ?
  • Gros fichiers : Tester avec un JSONL de > 100 Mo. vmux reste-il reactif ?
  • Multi-ecran : Le workspace est sur l'ecran 2, le switch via vmux amene bien a l'ecran 2, pas l'ecran 1.
  • Session fantome : Le process Claude a crash mais le JSONL n'a pas de message de fin. vmux detecte-t-il "mort" ?
  • Nouveau projet : Un nouveau repertoire apparait dans ~/.claude/projects/ pendant que vmux tourne. Detecte ?
  • Latence notification : Le delai entre "Claude attend" et la notification vmux est < 5 secondes.

Recovery Strategies

Pitfall Recovery Cost Recovery Steps
Format JSONL change apres update Claude LOW (si abstrait) Mettre a jour le module parser, re-deployer
Deadlock i3 IPC LOW Reconnexion auto via la lib Go (retry 10s)
OOM sur gros JSONL MEDIUM Kill vmux, implementer le tail-read, relancer
Desync workspace mapping LOW Forcer un rescan complet de l'arbre i3 (bouton/keybind refresh)
inotify events perdus LOW Le poll periodique rattrape automatiquement
Detection process cassee MEDIUM Ajouter un nouveau signal de detection (ex: window title) en complement

Pitfall-to-Phase Mapping

Pitfall Prevention Phase Verification
JSONL parsing fragile Phase 1 (detection) Interface abstraite, tests avec des JSONL reels
JSONL memoire Phase 1 (detection) Benchmark avec fichier > 100 Mo, memoire < 50 Mo
i3 IPC deadlock Phase 2 (i3 integration) Test de charge : 100 events/s pendant 60s
i3 reconnexion Phase 2 (i3 integration) i3 reload pendant que vmux tourne
Detection process Phase 1 (detection) Tester avec install native + npm, process mort
inotify fiabilite Phase 1 (detection) Creer/supprimer des fichiers rapidement, verifier que vmux suit
Mapping workspace Phase 2 (i3 integration) Deplacer une fenetre, verifier la mise a jour
Notifications spam Phase 3 (notifications) Session qui enchaine tool_use : 0 notification jusqu'a idle stable
UX preview Phase 3 (UI) Tester avec des sessions reelles, verifier la lisibilite

Sources


Pitfalls research for: vmux - Claude Code session monitoring with i3 integration Researched: 2026-03-23