Étude de cas : summoner
Architecture event-driven : orchestration multi-projet Claude Code
Summoner
Orchestrateur multi-projet Claude Code
Dashboard web pour gérer plusieurs projets Claude Code simultanément. Sessions persistantes avec --resume, task queue avec kanban, loop engine pour tâches récurrentes, golem engine pour agents autonomes, workflows multi-étapes, métriques de production et alertes proactives. Monorepo TypeScript avec backend Fastify 5 et frontend Lit 3.
summoner est un orchestrateur multi-projet pour Claude Code CLI, conçu pour gérer des sessions, des tâches et des workflows récurrents sur l'ensemble d'un lab de développement. Avec 342 sessions sur 48 projets trackés, c'est l'outil qui pilote les autres projets.
1. Contexte et objectifs
Problématique
Avec 48 projets utilisant Claude Code dans le lab (10 581 sessions totales), gérer les sessions manuellement devient un frein :
- Contexte perdu entre les sessions (
--resumesous-utilisé) - Pas de visibilité sur les coûts par projet
- Tâches récurrentes (audits, mises à jour) oubliées ou dupliquées
- Aucune orchestration cross-projet possible
- Pas de métriques sur la qualité et la productivité
Vision
Zéro token waste
claude --resume pour maintenir les contextes entre les sessions. Pas de re-briefing.
Factory mode
Task queue avec kanban, exécution automatique, métriques de throughput et lead time.
Agents autonomes
Golem engine : agents qui check-in périodiquement pour du travail proactif.
Observabilité
Coûts par projet, alertes de budget, recommandations proactives, health scoring.
2. Parcours utilisateur
Summoner est un dashboard web (port 7777) qui détecte automatiquement les projets présents dans ~/lab. Voici le parcours quotidien d'un développeur.
Vue projets : la base de tout
Au lancement, Summoner scanne ~/lab et affiche tous les projets détectés (via package.json, Cargo.toml, pyproject.toml, .git). Chaque projet montre :
- Son stack détecté (node, cargo, python)
- La branche git courante et l'état dirty/clean
- Le nombre d'agents Claude et de commandes configurées (.claude/)
- Un health score basé sur le taux de succès des sessions, le checklist score et l'historique
- Le coût cumulé en USD par projet
- Son archétype : experiment, utility, product ou platform
Sessions : travailler sur un projet
Deux modes pour ouvrir une session Claude sur un projet :
Session interactive
Shell persistant avec rendu terminal (xterm.js). On envoie des messages, Claude répond. La session reste ouverte pour plusieurs échanges. Highlight de syntaxe (11 langages), rendu markdown, extraction des tool calls, et visualisation des diffs git en temps réel.
Session oneshot
Exécution fire-and-forget : on donne un prompt, Claude l'exécute et la session se ferme. Utilisé par la task queue et le loop engine. Le résultat est stocké et consultable a posteriori.
Chaque session affiche en temps réel : le coût en USD, le nombre de tool calls par type (Read, Write, Bash, Agent), la durée, et le statut (running, stopped, error). La reprise est possible via --resume pour ne pas perdre le contexte.
Kanban : organiser le travail
Le tableau kanban est le centre de commande. Chaque projet a ses tâches réparties en 5 colonnes :
Le workflow concret :
- Créer une tâche dans le backlog (titre, priorité, labels, dépendances)
- Glisser vers "Todo" : la task queue la prend automatiquement quand un slot est libre
- Summoner spawne une session oneshot avec le prompt de la tâche → la carte passe en "In Progress"
- Le résultat apparaît en temps réel dans le chat panel
- À la fin → la tâche passe en "Done" (ou "Failed" avec possibilité de retry)
Loops : tâches récurrentes
Le loop engine automatise les tâches répétitives. Exemples concrets d'utilisation :
| Tâche récurrente | Intervalle | Description |
|---|---|---|
| Audit de sécurité | Toutes les 24h | Scan des dépendances, vérification des CVE, rapport |
| Lint & format | Toutes les 6h | Passe de linting sur le code modifié, auto-fix |
| Mise à jour des docs | Toutes les 12h | Synchronisation README / CHANGELOG avec le code |
| Health check CI | Toutes les 2h | Vérification que les pipelines passent, alerte sinon |
Chaque loop conserve son contexte (--resume) : le Claude qui fait l'audit à 8h sait ce qu'il a trouvé à 8h la veille.
Golems :agents autonomes
Un golem est un agent Claude qui travaille de manière proactive sur un projet. Contrairement aux loops (tâches prédéfinies), le golem décide lui-même ce qu'il faut faire :
Check-in
Toutes les 15 min, le golem reçoit le contexte projet : tâches en cours, health score, métriques, derniers commits.
Analyse
Il identifie les problèmes et propose des tâches : "Le coverage a baissé de 5%" ou "3 deps ont des CVE".
Validation
L'utilisateur approuve, modifie ou rejette les propositions. Le golem peut aussi poser des questions.
Exécution
Les tâches approuvées passent dans la task queue. Le golem suit leur avancement.
Chaque golem a un budget max (en USD et en nombre de tâches) et peut être pausé/repris à tout moment.
Workflows :orchestration multi-étapes
Pour les processus complexes qui enchaînent plusieurs actions. Exemple d'un workflow de release :
Les workflows peuvent être déclenchés manuellement, par cron, par webhook, ou automatiquement à la fin d'une session ou d'un git push.
Coûts et budget
Summoner agrège les coûts de toutes les sessions Claude par projet et par jour :
- Coût par session : affiché en temps réel pendant l'exécution
- Coût par projet : cumul avec historique et tendance
- Coût par tâche : permet de mesurer l'efficience ($ par tâche terminée)
- Alertes budget : alerte quand un projet dépasse $5/jour ou quand le total dépasse 2x la moyenne
- Quota quotidien : warning à 80%, block à 100%
Bootstrap :créer un nouveau projet
Summoner peut scaffolder un nouveau projet complet en 5 étapes :
- Initialize : manifest (package.json / Cargo.toml), git init, .gitignore adapté au langage
- Dependencies & tooling : package manager, linter (Biome/ESLint/Clippy), formatter
- Claude setup : CLAUDE.md structuré, répertoire .claude/, agents, commandes, mémoire
- Source control : git hooks (lefthook), CI/CD template
- Architecture docs : README, ARCHITECTURE.md, CHANGELOG
Chaque étape est un prompt Claude auto-suffisant avec checklist de validation. Support de TypeScript, Python, Rust, GDScript et JavaScript.
3. Architecture technique
Monorepo - 4 packages
summoner/
├── packages/
│ ├── core/ # 18 000+ LOC - Business logic
│ │ ├── store.ts # SQLite WAL, 3 700 LOC
│ │ ├── session-manager.ts # Claude CLI lifecycle, 1 400 LOC
│ │ ├── scanner.ts # Auto-detect ~/lab, 1 600 LOC
│ │ ├── task-queue.ts # Concurrency + deps, 500 LOC
│ │ ├── loop-engine.ts # Tâches récurrentes, 370 LOC
│ │ ├── golem-engine.ts # Agents autonomes, 670 LOC
│ │ ├── workflow-engine.ts # Multi-step orchestration, 750 LOC
│ │ ├── alert-engine.ts # Anomaly detection, 250 LOC
│ │ └── ...14 autres modules
│ │
│ ├── daemon/ # 3 600 LOC - Fastify 5 REST + WebSocket
│ │ └── server.ts # Routes, event broadcasting, lifecycle
│ │
│ ├── web/ # Lit 3 SPA - 20+ composants
│ │ ├── kanban-board.ts # Drag & drop tasks
│ │ ├── chat-panel.ts # Terminal viewer + syntax highlighting
│ │ ├── golem-panel.ts # Agent monitoring
│ │ └── factory-dashboard.ts # Production metrics
│ │
│ └── mcp/ # MCP server - Claude contrôle Summoner
│ └── index.ts # Tool calls bridge
│
├── summoner.db # SQLite (auto-created, WAL mode)
└── scripts/dev.ts # Blue-green dev orchestrator Stack technique
| Package | Tech | Rôle |
|---|---|---|
@summoner/core | TypeScript, SQLite, node-pty, Pino | Store, SessionManager, Scanner, TaskQueue, LoopEngine, GolemEngine, WorkflowEngine |
@summoner/daemon | Fastify 5, @fastify/websocket | API REST + WebSocket broadcast, orchestration de processus |
@summoner/web | Lit 3, Vite 6, xterm.js, highlight.js | SPA dashboard : kanban, chat, sessions, coûts |
@summoner/mcp | @modelcontextprotocol/sdk | Bridge MCP - Claude peut contrôler Summoner via tool calls |
Design decisions
SQLite WAL over PostgreSQL
Zéro config, léger, lectures/écritures concurrentes. Suffisant pour un orchestrateur mono-utilisateur avec ~50 projets.
Event-driven architecture
Tous les composants core émettent des événements. Le daemon les broadcast via WebSocket avec un ring buffer de 1 000 événements et numéro de séquence pour le reconnect sans resync complet.
node-pty pour les sessions
Full PTY emulation du CLI Claude. Stream-JSON parsing avec buffer 10 MB. Comptage automatique des tool calls (Read/Write/Bash/Agent).
MCP bridge
Claude Code peut contrôler Summoner :boucle agentic : un Claude qui orchestre d'autres Claude.
3. Engines :les moteurs de summoner
Session Manager
Gère le cycle de vie des processus Claude CLI :
Mode interactif
Shell persistant, queue de messages entre les tours. Réutilisable pour plusieurs prompts sur un même projet.
Mode oneshot
Spawn pour une tâche unique, attente de la fin, nettoyage. Utilisé par la task queue et le loop engine.
Circuit breaker
Auto-stop après 3 erreurs consécutives. Alerte de coût au seuil de $3. Timeout process hardcodé (30 min task, 10 min prompt).
Reconciliation
Au restart du daemon, les sessions orphelines sont marquées "stopped" et les sessions idle interactives sont ré-enregistrées.
Task Queue + Kanban
Exécution automatique des tâches avec gestion de concurrence :
- Concurrence : max 2 sessions simultanées (partagé avec LoopEngine)
- Tick : toutes les 5 secondes :détecte les sessions mortes, débloque les dépendances
- Colonnes kanban : backlog → todo → in_progress → review → done
- Model routing : Haiku pour la doc, Sonnet pour les audits/loops, auto-sélection du modèle le moins cher
- Circuit breaker par projet : 3 échecs consécutifs → cooldown de 5 min
Loop Engine
Tâches récurrentes sans réinitialisation de contexte :
// Exemple de configuration loop
{
intervalMs: 900_000, // Toutes les 15 minutes
maxRuns: 100, // Arrêt après 100 exécutions
enabled: true,
// → Le loop engine tick toutes les 10s
// → Jusqu'à 3 loop tasks concurrentes
// → Health check PID-based pour auto-unstick
} Golem Engine - Agents autonomes
Check-in périodique
Le golem reçoit un prompt enrichi avec le contexte projet (~5k tokens) : état des tâches, health score, métriques récentes.
Budget contrôlé
Config maxBudgetUsd et maxTasks. Le golem ne peut pas dépasser ses limites. Cost tracking par golem.
Interaction Q&A
Le golem peut poser des questions à l'utilisateur avant d'agir. Mécanisme question/réponse asynchrone.
Intégration Loop
Le golem utilise le LoopEngine pour ses check-ins périodiques + crée un epic pour tracker ses tâches.
Workflow Engine
Orchestration multi-étapes avec 8 types de steps :
| Step type | Description |
|---|---|
prompt | Envoie un prompt à une session Claude |
command | Exécute une commande shell |
checklist | Vérifie une liste d'items |
gate | Condition évaluée en JS (qualité, tests, build) |
parallel | Exécution de steps en parallèle |
approval | Attend une validation humaine |
webhook | Appel HTTP externe |
foreach | Fan-out sur les projets (par stack, label ou liste) |
Triggers : manual, cron, webhook, on_session_end, on_push.
4. Observabilité et alertes
Alert Engine
Cost spikes
Alerte si le coût du jour dépasse 2x la moyenne. Seuil par projet : >$5/jour.
Failure streaks
3+ échecs en 1 heure sur un même projet = alerte. Circuit breaker activé.
Stuck detection
Sessions sans message depuis 30 min, tâches in_progress depuis 30 min sans session active.
Quota warning
Alerte à 80% de la limite quotidienne. Déduplication sur fenêtre de 10 minutes.
Factory Metrics
Métriques de production pour mesurer l'efficacité du lab :
- Throughput : tâches completed/failed par jour
- Lead time : heures moyennes de queued → completed
- Cost efficiency : coût par tâche terminée
- Quality rate : % de sessions passant le quality gate
- Capacity estimate : backlog actuel, tasks/jour moyennes, jours restants
- Budget par projet : dépensé / budget / pourcentage
Recommendation Engine
Insights proactifs avec actions - tourne toutes les 60 secondes :
// Types de recommandations
cost_spike → "Coût anormal sur granit-golem : $12 aujourd'hui vs $3 en moyenne"
circuit_breaker → "3 échecs consécutifs sur un cas client multi-agent : session auto-stoppée"
stuck_task → "Tâche #42 bloquée depuis 45 min : action: retry ou stop"
loop_failures → "Loop 'daily-audit' échoue depuis 3 runs"
queue_backlog → "15 tâches en attente : capacité estimée : 3 jours"
quota_warning → "80% du budget quotidien atteint" 5. Utilisation de Claude Code
Configuration CLAUDE.md
CLAUDE.md ~80 lignes ## Stack
| Package | Tech | Rôle |
|---------|------|------|
| @summoner/core | TypeScript, SQLite, node-pty | Engine |
| @summoner/daemon | Fastify 5, WebSocket | API |
| @summoner/web | Lit 3, Vite 6, xterm.js | SPA |
## Conventions
- Monorepo npm workspaces
- TypeScript strict, ESM only
- Lit 3 avec decorators pour les web components
- SQLite WAL mode pour la persistence
- WebSocket pour le real-time
## Principes
1. Zéro token waste - claude --resume pour les contextes
2. Loop engine - Tâches récurrentes sans réinitialisation
3. Real-time - WebSocket broadcast de tous les événements
4. Auto-scan - Détection automatique des projets ~/lab
## Process lifecycle
- startOneshot() retourne avant que le spawn soit validé
- Timeouts: 30min task, 10min prompt, 5min command
- Toujours émettre session:end dans error ET close
- Event listeners: cleanup explicite (pas de on() sans remove) Méta-récursivité
6. Métriques et résultats
Analyse des 34 commits
Ratio fix/feat : 0.33
Interprétation : Ratio excellent pour un projet en développement actif. Les fixes sont essentiellement du hardening : gestion des sessions stuck, signal kills, busy flag reset. La majorité du travail est feature-driven avec des waves de livraison (wave 6 → 9 en une journée le 10 mars).
Volume de code
7. Problèmes rencontrés et solutions
Sessions stuck
Problème : Sessions Claude CLI qui ne répondent plus : processus zombie, PID encore vivant mais aucun output.
Solution : Ghost reaper toutes les 5 min, health check PID-based, circuit breaker à 3 erreurs.
Stream-JSON parsing
Problème : Le CLI Claude sort du JSON ligne par ligne, mais les lignes peuvent être coupées entre les reads du PTY.
Solution : Line buffer de 10 MB avec reconstruction, strip-ansi pour nettoyer les codes ANSI avant le parse.
Concurrence sessions
Problème : Trop de sessions simultanées saturent la machine :mémoire et CPU.
Solution : Plafond de concurrence partagé entre task queue + loop engine + sessions manuelles. Max 2 par défaut.
Event listener leaks
Problème : EventEmitter listeners accumulés sans cleanup :memory leak après beaucoup de sessions.
Solution : Convention CLAUDE.md : jamais de on() sans removeListener(). Cleanup explicite obligatoire.
8. Enseignements clés
Event-driven = scalable
L'architecture événementielle découple le core du transport. Ajouter un nouveau consumer (MCP, CLI, API) ne touche pas le core.
SQLite WAL suffit
Pour un orchestrateur mono-utilisateur, SQLite en WAL mode offre les performances nécessaires sans la complexité de PostgreSQL.
Claude Code construit du Claude Code tooling
La méta-récursivité fonctionne : Claude est efficace pour construire des outils qui orchestrent d'autres instances de lui-même.
Process lifecycle = le vrai challenge
L'orchestration de processus CLI est plus complexe que l'UI. La gestion des zombies, timeouts, et signal kills représente la majorité des fixes.