- README.md : vision, installation, commandes, aperçu fonctionnement - LICENSE : WTFPL v2 - docs/architecture.md : composants, flux de données, index des fichiers - docs/i3-integration.md : config i3bar, switch, focus, dépannage - .gitignore : exclure .direnv/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
102 lines
4.3 KiB
Markdown
102 lines
4.3 KiB
Markdown
# Architecture
|
|
|
|
## Vue d'ensemble
|
|
|
|
vmux suit une architecture **daemon + CLI** classique. Un daemon unique tourne en arrière-plan ; toutes les commandes `vmux` communiquent avec lui via une Unix socket.
|
|
|
|
```
|
|
Claude Code session
|
|
│ hooks (HTTP localhost:3119)
|
|
▼
|
|
┌─────────────┐
|
|
│ Daemon │◄── /proc scan (5s)
|
|
│ │◄── JSONL reader (~/.claude/projects/)
|
|
│ registry │◄── i3 IPC + X11 (workspace resolution)
|
|
└──────┬──────┘
|
|
│ Unix socket (~/.vmux/vmux.sock)
|
|
▼
|
|
vmux list / switch / label / focus / i3bar
|
|
```
|
|
|
|
## Composants
|
|
|
|
### Daemon (`daemon.go`)
|
|
|
|
- Écoute sur `~/.vmux/vmux.sock` (Unix socket)
|
|
- Lance un hook server HTTP sur `localhost:3119`
|
|
- Maintient un `SessionRegistry` en mémoire (map sessionID → SessionInfo)
|
|
- Poll `/proc` toutes les **5s** (ou **20s** si des hooks arrivent activement)
|
|
|
|
### Détection des processus (`proc.go`)
|
|
|
|
Scrute `/proc/*/cmdline` pour trouver les processus dont la commande contient `claude`. Pour chaque processus trouvé, lit :
|
|
- `/proc/<pid>/cwd` — répertoire de travail courant
|
|
- `/proc/<pid>/fd/0` — PTY associé (pour la résolution workspace)
|
|
|
|
### Lecture JSONL (`session.go`)
|
|
|
|
Claude Code écrit un fichier JSONL par session dans `~/.claude/projects/<encoded-cwd>/<uuid>.jsonl`. vmux associe un PID au bon fichier par correspondance du `cwd`, puis lit les messages pour extraire :
|
|
- `sessionId`, `gitBranch` — identité de la session
|
|
- `type: "assistant"` — dernier message Claude (pour le state et le preview)
|
|
|
|
### Détection d'état (`state.go`)
|
|
|
|
| État | Critère |
|
|
|---|---|
|
|
| `Working` | Dernier event hook = `PreToolUse` ou `PostToolUse` |
|
|
| `Needs Input` | Dernier event hook = `Notification` ou `Stop` |
|
|
| `Idle` | Aucun event récent, dernier message JSONL vieux de plus de 30s |
|
|
|
|
Les hooks Claude Code sont prioritaires sur la détection JSONL : ils arrivent en temps réel.
|
|
|
|
### Hooks Claude Code (`hook.go`)
|
|
|
|
Claude Code appelle `vmux hook` à chaque événement (via la config `~/.claude/settings.json`). Le binaire lit le JSON sur stdin et le transmet au daemon via la socket. Le daemon met à jour le registry et déclenche une notification si la session passe de `Working` à `Needs Input`.
|
|
|
|
### Résolution workspace i3 (`workspace.go`, `i3bridge.go`, `x11_resolver.go`)
|
|
|
|
1. `i3.GetTree()` — récupère l'arbre des fenêtres i3
|
|
2. Pour chaque fenêtre avec "Claude Code" dans le titre : lit son PID via `_NET_WM_PID` (X11)
|
|
3. Remonte la chaîne `/proc/<pid>/fd/0` → PTY → processus parent → PID Claude
|
|
4. Associe le PID Claude au numéro de workspace i3
|
|
|
|
Dégradation gracieuse : si i3 ou X11 est indisponible, les workspaces restent vides (pas de crash).
|
|
|
|
### i3bar (`i3bar.go`)
|
|
|
|
Implémente le [protocole i3bar](https://i3wm.org/docs/i3bar-protocol.html). Tourne en boucle infinie, interroge le daemon toutes les 2s, écrit du JSON sur stdout.
|
|
|
|
### Notifications (`notify.go`)
|
|
|
|
Appelle `notify-send` avec `--urgency=critical` quand une session passe de `Working` à `Needs Input`. Le mode focus (`vmux focus <minutes>`) supprime les notifications pendant la durée donnée.
|
|
|
|
## Fichiers
|
|
|
|
| Fichier | Rôle |
|
|
|---|---|
|
|
| `main.go` | Entrypoint, routing des commandes CLI |
|
|
| `daemon.go` | Daemon, registry, label store |
|
|
| `proc.go` | Scan /proc pour les processus claude |
|
|
| `session.go` | Lecture des fichiers JSONL Claude Code |
|
|
| `state.go` | Détection d'état (Working/NeedsInput/Idle) |
|
|
| `hook.go` | Réception et traitement des hooks Claude Code |
|
|
| `workspace.go` | Résolution workspace via i3 tree |
|
|
| `i3bridge.go` | Abstraction i3 IPC (testable) |
|
|
| `x11_resolver.go` | Lecture _NET_WM_PID via XGB |
|
|
| `i3bar.go` | Protocole i3bar |
|
|
| `notify.go` | Notifications desktop (notify-send) |
|
|
| `focus.go` | Timer de mode focus |
|
|
| `display.go` | Affichage `vmux list` |
|
|
| `client.go` | Client Unix socket |
|
|
| `protocol.go` | Types Request/Response partagés |
|
|
| `setup.go` | Injection des hooks dans settings.json |
|
|
| `types.go` | Types de données (Session, SessionState…) |
|
|
|
|
## Données persistées
|
|
|
|
| Chemin | Contenu |
|
|
|---|---|
|
|
| `~/.vmux/vmux.sock` | Unix socket du daemon |
|
|
| `~/.vmux/labels.json` | Labels assignés par l'utilisateur |
|
|
| `~/.claude/settings.json` | Hooks Claude Code (modifié par `vmux setup`) |
|