{"id":"34ecfe79-6e31-4fc9-9116-3a4aeb8cbae9","slug":"wikichat","kind":"mcp","name":"Wikichat","summary":"Collaboration projets & agents pour Claude Code — local, sans clé API, dormant à 0% CPU.","owner":"nic01asFr","repoUrl":"https://github.com/nic01asFr/Wikichat","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-04-20T11:59:03.000Z","addedAt":"2026-10-21T08:44:04.437Z","logoUrl":"https://avatars.githubusercontent.com/u/83064733?u=f3746ee853632dca4f6275bf0f5409cc37f0d336&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","memory-knowledge"],"tags":["agent-orchestration","claude-code","developer-tools","knowledge-management","local-first","mit-license","multi-agent","nodejs"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T20:26:16.317Z","sample":false,"url":"https://conduits.dev/tools/wikichat","language":"JavaScript","transports":["stdio"],"install":{"npm":"wikichat"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# WikiChat\n\n**Présentation produit :** [nic01asfr.github.io/Wikichat](https://nic01asfr.github.io/Wikichat/) — ce README reste la doc technique.\n\n**La mémoire et le système nerveux de ta machine de développement.**\n\nUn service local qui sait ce que tu as fait dans tes autres projets, relie les sessions Claude Code que tu ouvres séparément, et continue de travailler quand tu fermes le laptop. Tout tourne en local, sur ton abonnement Claude — aucune clé API.\n\n---\n\n## À quoi ça ressemble\n\n**Ta session interroge ce que tu as déjà résolu ailleurs.**\n\n```\n> search_knowledge(\"rendu 3D sur fond de carte\")\n\n🔍 2 résultats (20 fichiers de connaissance parcourus)\n\n  1. Axe MapLibre + Three.js — pattern transverse        (score 20)\n     À lire si un agent touche au rendu cartographique 3D…\n     🟢 FIXÉ — pattern en production dans 5 projets, à NE PAS re-dériver\n     Référence : editeur-volumes.html:200-330\n\n  2. Axe rendu terrain — protocole MNT                   (score 14)\n```\n\nCes axes ne sont pas écrits à la main. Ils sont compilés à partir de tes clôtures de projet, avec une convention de fiabilité — ce qui est fixé, ce qui reste à valider, ce qu'il ne faut surtout pas refaire.\n\n**Tu appelles un agent qui n'est pas lancé. Il répond.**\n\n```\n> send_message(\"@Reviewer tu peux relire l'inbox ?\", expects_reply=true)\n\n  📤 Envoyé sur #proj-api\n  ⚠️ Reviewer est hors ligne\n\n  🔔 réveil déclenché — session reprise dans son dépôt\n\n  21 s plus tard :\n  📩 Reviewer : « Inbox passée au crible. Ton lot 1 tient.\n                  Le trou est ailleurs, et il est plus grave… »\n```\n\nAucun agent ne veillait. Le message l'a fait exister, dans son propre dépôt, avec son historique.\n\n**Un commit arrive. Personne ne surveillait.**\n\n```\n  [détecteur JS]  3 commits sur my-api      ← 0 token\n  [#insights]     [event:commits project:my-api]\n  [trigger]       motif reconnu → agent de revue lancé\n  [agent]         revue déposée dans .wikichat/artifacts/, sortie\n```\n\nLe détecteur ne coûte rien tant qu'il ne trouve rien. C'est ce qui permet une surveillance permanente sans veilleur permanent.\n\n---\n\n## Le problème\n\nTu ouvres Claude Code sur un projet. La session sait tout de ce projet et **rien** du reste : ni ce que tu as construit dans les douze autres repos de ta machine, ni ce qu'une autre session est en train de faire dans la fenêtre d'à côté, ni les décisions que tu avais prises il y a trois mois sur exactement ce problème-là.\n\nChaque session repart de zéro, chaque session est seule, et tout ce qu'elle apprend meurt avec elle.\n\nWikiChat répond à ces trois manques.\n\n## Ce que ça apporte\n\n**Une mémoire qui traverse les projets.** Avant d'implémenter un pattern déjà résolu ailleurs, ta session interroge `search_knowledge` — une base transverse construite au fil de tes clôtures de projet, pas alimentée à la main. Quand tu clôtures (`close_project`), un agent lit l'état du projet et ses artefacts, produit une synthèse structurée, et la capitalise pour les projets suivants.\n\n**Des sessions qui se parlent.** Chaque session s'enregistre sous un nom. À partir de là : canaux, messages directs, artefacts partagés, tâches réparties. Deux fenêtres ouvertes se coordonnent sans que tu joues les messagers.\n\n**Une surveillance qui ne coûte rien.** Le service détecte en JavaScript ce qui se passe sur ta machine — commits, branches, `CLAUDE.md` modifié, dépendances, artefacts déposés, tâches expirées — et n'allume un agent que quand un événement le justifie. Pas de veilleur qui consomme en attendant.\n\n**Du travail délégué.** Depuis une session, tu spawnes des agents Claude Code headless sur des tâches bornées. Ils s'exécutent, écrivent dans `.wikichat/artifacts/`, et sortent.\n\n**Zéro coût au repos.** Installé comme service, WikiChat démarre au logon et reste dormant à 0 % CPU. Il s'éveille quand une session Claude Code s'enregistre, se rendort cinq minutes après la dernière.\n\n## Sur ton abonnement, pas sur l'API\n\nC'est la décision qui structure tout le reste, et elle mérite d'être explicite.\n\nLes agents que WikiChat lance **sont** des sessions Claude Code : il exécute `claude -p` dans le dépôt visé. Il n'y a **aucune clé API à fournir**, rien à provisionner, rien à surveiller côté facturation.\n\nTrois conséquences concrètes :\n\n**Un agent délégué vaut ta session.** Il lit le `CLAUDE.md` du projet, hérite de tes serveurs MCP, de tes skills, de tes permissions. Quand un agent a besoin de GitHub, il utilise *ton* outillage MCP — c'est pourquoi WikiChat ne va jamais chercher une source externe lui-même : il oriente, l'agent exécute. Une orchestration bâtie sur l'API redescendrait à une boucle d'appels sans ce contexte.\n\n**Le coût n'est pas au token.** Une surveillance permanente facturée à l'appel devient vite déraisonnable ; c'est même la mesure qui a fait retirer les daemons résidents de ce projet — 28,4 M tokens d'entrée pour trois actes utiles en trois mois. Sur un abonnement, ce qui compte est le nombre de tours et de sessions, pas une addition. Les garde-fous bornent donc ces grandeurs-là : sessions concurrentes (`WIKICHAT_MAX_SESSIONS`), quotas par appelant, profondeur de spawn, plafonds par trigger, et **durée d'un daemon** (`WIKICHAT_DAEMON_MAX_MS`).\n\nUne précision mesurée, parce qu'elle contredit une intuition : `--max-turns` n'existe ni en Claude Code 2.1.86 ni en 2.1.237, et le CLI l'ignore **en silence** ; `--max-budget-usd` existe mais ne borne rien sur abonnement, où le coût remonté vaut zéro. Déléguer un plafond au CLI ne borne donc rien. Le temps mural est la seule grandeur mesurable de ce côté-ci, et c'est celle qu'on applique.\n\n**Rien ne sort de la machine.** Le service écoute sur `127.0.0.1`, l'état vit dans tes dépôts, et aucun secret n'a besoin d'exister pour que ça tourne.\n\n**Ce que ça implique aussi**, et qu'il faut savoir avant de s'y engager : Claude Code doit être installé et connecté, et les agents consomment ton quota d'abonnement comme le ferait ton propre travail. Un déclencheur mal réglé ne te coûtera pas d'argent, mais il peut consommer ta capacité — d'où les plafonds ci-dessus, actifs par défaut.\n\n## Quand ça ne sert à rien\n\nUn seul projet, une seule session, rien à retenir d'un mois sur l'autre : WikiChat n'apporte qu'une couche de complexité. Son intérêt commence avec plusieurs projets qui se ressemblent, plusieurs sessions simultanées, ou du travail répétitif qui gagnerait à tourner sans toi.\n\n---\n\n## Installation\n\n```bash\ngit clone https://github.com/nic01asFr/Wikichat.git\ncd Wikichat\nnpm install\n```\n\n**Service de fond (recommandé)** — auto-start au logon, dormant au repos :\n\n```bash\nnode scripts/install-service.mjs      # Windows / macOS / Linux\nnode scripts/uninstall-service.mjs    # désinstaller\n```\n\n**Ou en avant-plan** :\n\n```bash\nnpm start\n```\n\n**Couche Claude Code** — installée toute seule au premier démarrage, rien à faire. Le serveur pose dans `~/.claude/` une skill que Claude active dès qu'il détecte WikiChat, les commandes `/wikichat-init`, `/sk <query>`, `/close-project`, `/wikichat-status`, et le hook de fin de tour qui remet à chaque agent le courrier qui lui est adressé. C'est ce dernier qui rend la coordination naturelle : sans lui, il faudrait interroger sa boîte à la main.\n\nL'installation est idempotente et ne touche jamais à ce que tu as écrit — elle ajoute son bloc entre deux marqueurs, conserve les autres hooks `Stop` déjà présents, et se contente de rafraîchir son propre bloc aux démarrages suivants.\n\nPour la poser dans un projet plutôt que globalement :\n\n```bash\nnpm run install-overlay -- --project # → .claude/ du repo courant\n```\n\n**Brancher Claude Code / Cursor** — pont stdio (identité stable) :\n\nDans `~/.cursor/mcp.json` ou `.mcp.json` du projet :\n\n```json\n{\n  \"mcpServers\": {\n    \"wikichat\": {\n      \"command\": \"node\",\n      \"args\": [\"<chemin-absolu>/wikichat/scripts/wikichat-mcp-stdio.mjs\"]\n    }\n  }\n}\n```\n\nLe pont calcule un jeton et l’injecte dans l’URL SSE. Les clients qui ignorent `headersHelper` (Cursor, Claude VS Code) ne redeviennent plus anonymes à chaque reconnexion.\n\n**Profil d’accès.** Avec `\"env\": { \"WIKICHAT_PROFIL\": \"code\", \"WIKICHAT_PROJET\": \"<slug>\" }`, le serveur n’expose à la conversation que les 26 outils du profil `code`, bornés à ce projet ; `WIKICHAT_PROFIL=assistant` donne tout. Sans profil, tous les outils (journalisé). Détail : `docs/atelier-coherence.md` §12.\n\nAlternative SSE brute (moins fiable sans variables d’environnement) :\n\n```bash\nclaude mcp add wikichat --transport sse --url http://localhost:3777/sse\n```\n## Au quotidien\n\nTrois réflexes, largement automatiques une fois l'overlay installé :\n\n| Moment | Commande | Effet |\n|---|---|---|\n| Début de session | `/wikichat-init` | S'enregistre, déclare le projet, récupère un briefing filtré |\n| Avant de construire du déjà-vu | `/sk <sujet>` | Cherche dans la connaissance transverse |\n| Fin de projet | `/close-project` | Capitalise pour les projets suivants |\n\nEntre les deux, tu travailles normalement. `poll()` relève ta boîte quand tu en as besoin — le curseur est tenu côté serveur.\n\n---\n\n## Architecture\n\nEntrée : `server.mjs`. Environ 11 000 lignes au total.\n\n```\nsrc/state.mjs        — état en mémoire (sessions, canaux, messages, projets)\nsrc/tools.mjs        — les 53 outils MCP\nsrc/persistence.mjs  — I/O atomique\nsrc/events.mjs       — bus d'événements : détecteurs → triggers\nsrc/triggers.mjs     — moteur de triggers (cron, mention, channel_match, file_watch, webhook, lifecycle)\nsrc/routines.mjs     — workflows nommés multi-étapes, idempotents\nsrc/sampler.mjs      — spawn d'agents (headless, daemon, interactif)\nsrc/snapshot.mjs     — détection de changements par projet\nsrc/scanner.mjs      — découverte de projets sur la machine\nsrc/registry.mjs     — registre central ~/.wikichat/registry.json\nsrc/identity.mjs     — mémoires persistantes par agent (remember/recall)\nsrc/dormant.mjs      — gate d'éveil/sommeil\nsrc/resilience.mjs   — watchdog, heartbeat, détection stale\nsrc/pilote.mjs       — agents planifiés + file d'approbation (UI /pilote)\nsrc/injector.mjs     — overlay .wikichat/ dans les projets\nsrc/notifier.mjs     — long-poll pour poll_messages\nsrc/jobs/            — cartographie, clustering\n```\n\n**Transport** : Express 5 + SSE via `@modelcontextprotocol/sdk`. Les agents se connectent à `/sse`, envoient du JSON-RPC sur `/messages`.\n\n### Le modèle événementiel\n\nC'est le cœur du fonctionnement, et ce qui distingue WikiChat d'un orchestrateur classique :\n\n```\ndétecteur JavaScript  →  #insights  →  prédicat regex  →  spawn headless\n      (0 token)                          (0 token)         (à la demande)\n```\n\nLes détecteurs tournent en JS et ne coûtent rien tant qu'ils ne trouvent rien. Quand ils trouvent, ils publient un événement au format `[event:type project:x] résumé` sur le canal `#insights`. Les triggers `channel_match` écoutent ce canal et spawnent l'agent approprié.\n\nTypes d'événements émis : `commits`, `branch`, `uncommitted`, `git-init`, `claude-md`, `deps`, `version`, `files`, `new-project`, `artifact`, `queue`, `stale`, `task-expired`.\n\n### L'identité, une fois pour toutes\n\nUn agent se déclare **une seule fois par conversation** :\n\n```js\nregister(name: \"Backend-Dev\", role: \"développeur\")\n```\n\nEt c'est tout. Plus jamais — ni après une reconnexion, ni après avoir fermé puis rouvert la conversation, ni après un redémarrage du service ou de la machine.\n\nDeux mécanismes indépendants l'assurent :\n\n**Le jeton.** Un `headersHelper` émet à chaque connexion un jeton dérivé de l'identifiant de conversation, par hachage salé d'un secret local. Il est donc *calculé*, jamais stocké : rien à perdre, rien à purger, et deux conversations distinctes ont forcément deux jetons distincts — deux agents d'un même dépôt ne se confondent pas.\n\n**La conversation.** Si aucune liaison de jeton ne répond, l'identifiant de conversation suffit : le hook de fin de tour consigne `nom → conversation`, et le serveur s'en sert à l'envers à la connexion. Un agent déclaré une fois se retrouve même avec un jeton qui n'a jamais servi.\n\nSans jeton — une configuration qui pointe l'URL nue — l'identité ne survit à aucune reconnexion, et l'agent redevient anonyme sans que rien ne le lui dise. C'est arrivé : deux agents ont continué à s'écrire par pseudonymes une heure durant alors qu'aucun ne portait plus le sien. `send_message` et `poll` le signalent désormais quand ça compte.\n\nLe même principe vaut pour joindre quelqu'un. Un agent nommé mentionné dans un message qui attend une réponse est relancé s'il est hors ligne — par **un seul** trigger générique, valable pour toutes les identités présentes et à venir. Il reprend sa session Claude Code quand son transcript est encore exploitable, et reçoit dans son prompt le message qui l'a appelé.\n\nUn agent qui est, lui, en session reçoit son courrier sans rien demander : un hook de fin de tour lui remet ce qui lui est adressé. S'il préfère être prévenu **pendant** son travail, il pose un guetteur en tâche de fond — un processus qui dort sur une connexion HTTP et ne consomme rien tant que rien n'arrive :\n\n```\nBash(command=\"node scripts/wikichat-attendre-courrier.mjs\", run_in_background=true)\n```\n\nTrois champs pilotent la conversation, et ils ne sont pas décoratifs : `expects_reply` garde le lien ouvert, `status=\"standby\"` avec `eta_seconds` fait patienter l'interlocuteur jusqu'à l'échéance annoncée au lieu de raccrocher, `status=\"done\"` referme.\n\nPour brancher un agent sur un événement, un `register_trigger` suffit :\n\n```js\nregister_trigger({\n  type: \"channel_match\",\n  config: { channel: \"insights\", pattern: \"\\\\[event:commits\\\\b\" },\n  action_type: \"spawn_session\",\n  action_params: { mode: \"headless\", name: \"ReviewAgent-{ts}\", prompt: \"…\" },\n  cooldown_s: 600, max_per_day: 12,\n})\n```\n\n## Où vivent les données\n\n**Le contenu vit dans les projets ; WikiChat ne fait que pointer.**\n\n| Emplacement | Contenu |\n|---|---|\n| `<projet>/.wikichat/artifacts/` | Artefacts produits par les agents |\n| `<projet>/.wikichat/project-state.json` | Tâches, décisions, blockers, clôture |\n| `<projet>/.wikichat/queue/` | Actions hors ligne, récupérées au boot |\n| `~/.wikichat/registry.json` | Index des projets de la machine |\n| `~/.wikichat/knowledge/` | Connaissance transverse compilée |\n| `~/.wikichat/ideas/` | Idées, un fichier par idée |\n| `~/.wikichat/memories.json`, `messages.json`, `channels.json`, `fils.json`, `sessions/`, `projects/`, `agents/`, `spawn_registry.json` | État du service. Depuis le lot W2, plus rien ne dépend du dossier de lancement ; les anciennes données y sont reprises au démarrage (`src/migration.mjs`) |\n| `~/.wikichat/audits.json`, `clusters/`, `cartography/` | Santé des dépôts, proximités, cartes |\n\nUn `git add .wikichat/` dans chaque projet sauvegarde sa connaissance avec son code. Tu changes de machine, l'état suit.\n\n### Consulter sa mémoire à distance (optionnel)\n\nToute cette mémoire vit sur une seule machine. Un pipeline en trois briques la rend consultable ailleurs — depuis un téléphone, un autre poste — sans exposer la machine ni ses secrets :\n\n```\nexport sanitisé  →  dépôt git privé  →  serveur MCP lecture seule\n   (whitelist)        (idempotent)         (snapshot déjà propre)\n```\n\n**Export** — balaye les sources de mémoire, filtre le bruit, et n'émet qu'une liste blanche de champs. Un scan anti-secret tourne sur le résultat : jetons de processus, clés, identifiants sont retirés avant écriture. L'export refuse de produire un snapshot où il détecte un secret.\n\n**Publication** — ne committe que si le hash du manifest a changé, et retire les fichiers orphelins quand un projet disparaît. Quand rien n'a bougé, c'est un no-op.\n\n**Consultation** — un serveur MCP hébergeable, strictement lisible : il ne connaît que le snapshot déjà sanitisé, ne spawne rien, n'écrit rien. Son jeton se lit depuis un fichier plutôt que d'apparaître dans le script de démarrage.\n\nLa boucle est bidirectionnelle : une idée capturée à distance atterrit dans `inbox/` du dépôt, et le passage suivant l'intègre en local. Une capture externe devient toujours une **idée taguée**, jamais une mutation directe d'état projet — le local reste l'autorité.\n\n```bash\nnpm run memory:sync -- --repo <clone-local>          # un passage manuel\nnpm run memory:refresh -- --repo <clone-local>       # battement toutes les 15 min\nnpm run memory:refresh -- --uninstall                # retirer le battement\n```\n\n## Outils MCP (53)\n\n| Catégorie | Outils |\n|---|---|\n| Identité | `register`, `set_status`, `get_briefing`, `remember`, `recall`, `forget` |\n| Messagerie | `send_message`, `read_messages`, `poll`, `poll_messages`, `share_artifact` |\n| Canaux | `list_sessions`, `list_channels`, `create_channel` |\n| Coordination | `declare_capabilities`, `declare_delay`, `claim_task`, `release_task` |\n| Projets | `declare_project`, `list_projects`, `set_project_meta`, `add_project_note`, `close_project`, `scan_projects`, `purge_registry`, `audit_project`, `audit_all_projects` |\n| Suivi de projet et fils | `project_state`, `list_threads` |\n| Agents projet | `list_project_agents`, `respawn_project_agents` |\n| Connaissance | `search_knowledge` |\n| Idées | `add_idea`, `get_idea`, `list_ideas`, `update_idea`, `harmonize_ideas` |\n| Spawning | `spawn_session`, `contact_agent`, `list_spawned`, `kill_spawn`, `poll_ticket` |\n| Routines | `register_routine`, `list_routines`, `run_routine`, `delete_routine` |\n| Triggers | `register_trigger`, `list_triggers`, `fire_trigger`, `set_trigger_enabled`, `delete_trigger` |\n| Jobs | `run_cartography`, `run_clustering` |\n\nLes jobs déterministes (`run_cartography`, `run_clustering`, `harmonize_ideas`, `audit_all_projects`, `scan_changes`, `absorb_closures`, `capitaliser_faits`) s'appellent aussi sans agent : étape `job` d'une routine, action `job` d'un trigger (`src/jobs/index.mjs`). Un trigger créé par un agent (`register_trigger`) naît désactivé et se plafonne à 24 actions par jour par défaut ; la personne l'active depuis le Pilote.\n\n**Capitalisation des conversations (W8)** : `capitaliser_faits` fiche toutes les 15 min les conversations de l'Atelier au repos (faits extraits par le code, depuis le transcript filtré que fournit l'Atelier) dans `~/.wikichat/knowledge/conversations/<projet>/<id>.md`, que `search_knowledge` retrouve (en profil `code` : les fiches de son projet seulement). `capitaliser_nuit` (trigger `memoire-nuit`, né désactivé) en tire le sens la nuit, 20 conversations de 30 000 jetons au plus, par des lancements de l'Atelier. Détail : `docs/atelier-coherence.md` §14.\n\n## Ressources MCP (6)\n\n| URI | Contenu |\n|---|---|\n| `wikichat://briefing` | briefing de la session : mentions, nouveautés, projets actifs |\n| `wikichat://principal` | identité et statut de l'agent principal |\n| `wikichat://identity/{name}` | instantané et mémoires d'un agent |\n| `wikichat://decisions` | 50 dernières décisions de #decisions |\n| `wikichat://kb/{topic}` | une fiche de connaissance (même lecteur que `search_knowledge`) |\n| `wikichat://role/{name}` | définition d'un rôle (`~/.wikichat/roles/`, sinon `docs/roles/`) |\n\n## Modes de spawn\n\n| Mode | Comportement |\n|---|---|\n| `headless` *(défaut)* | `claude -p` one-shot, mode de permission `acceptEdits` par défaut (paramètre `permission_mode` ; `bypassPermissions` seulement déclaré par une routine ou un déclencheur). Connexion wikichat par `--mcp-config` temporaire hors du projet. Exécute, écrit dans `.wikichat/artifacts/`, sort. |\n| `daemon` | Agent persistant en boucle de poll. Coûteux : une veille relit tout son historique à chaque tour, le coût croît de façon quadratique. Préférer un trigger. Relance plafonnée à 5. |\n| `interactive` | Ouvre un terminal avec `claude`. |\n\nLes agents nommés reprennent leur session précédente (`--resume`) quand leur transcript existe et pèse moins que `WIKICHAT_MAX_RESUME_MB` (5 Mo par défaut) ; au-delà, démarrage frais.\n\n## API REST\n\n| Endpoint | Rôle |\n|---|---|\n| `POST /api/chat`, `GET /api/messages`, `GET /api/inbox` | Messagerie |\n| `POST /api/spawn/headless`, `POST /api/spawn/daemon`, `GET /api/agents` | Spawn |\n| `POST /api/sample` | Prompt direct à une session vivante |\n| `GET /api/projects`, `/api/projects/:slug`, `/api/projects/scan` | Projets |\n| `GET /api/knowledge` (`?q=` pour chercher), `/api/knowledge/:sujet`, `/api/knowledge/:projet/:nom` | Connaissance : index, recherche, fiche |\n| `GET /api/cartographie` | Graphe des projets pour la carte de l'Atelier (contrat : `docs/cartographie-contrat.md`) |\n| `GET /api/memoire/rappel`, `/api/memoire/fiches`, `/api/memoire/fiches/:id`, `/api/memoire/personne`, `/api/memoire/personne.md`, `/api/memoire/etat` | Mémoire : rappel des conversations, fiches, mémoire de la personne (§14 de `docs/atelier-coherence.md`) |\n| `POST /api/memoire/personne`, `PATCH`/`DELETE /api/memoire/personne/:id`, `POST /api/memoire/capitaliser` | Écritures de la mémoire : clé du lanceur de l'Atelier (`X-Atelier-Lanceur`) seulement |\n| `GET /`, `/status`, `/api/health` | Santé |\n| `POST /api/triggers/webhook/:id` | Déclencher un trigger webhook |\n| `GET /pilote` + `/pilote/api/*` | Agents planifiés et file d'approbation |\n\n## Comportements automatiques\n\n- **Dormant gate** — les triggers qui lancent un agent ne firent que si une session nommée est enregistrée ; ceux qui n'exécutent que du code (jobs, messages) tournent toujours (décision J-c). Sans agent ouvert, le service est passif. Les crons tombés pendant le sommeil sont rejoués une fois au réveil : sans ce rattrapage, une routine programmée la nuit — précisément à l'heure où personne n'est là — ne s'exécuterait jamais.\n- **Idle gate** — les intervalles sautent leur corps si aucune activité depuis 5 minutes. 0 % CPU au repos.\n- **Watchdog** (60 s) — détection des sessions inactives au-delà de 20 minutes.\n- **Queue et artefacts** (2 min) — récupère ce que les agents ont écrit localement pendant que MCP était injoignable.\n- **Cleanup** (5 min) — TTL des tâches, GC des DM, rotation des snapshots, détection de changements par lots.\n- **Arrêt propre** — SIGINT/SIGTERM flushe l'état, arrête les daemons, ferme les watchers.\n\n## Variables d'environnement\n\n| Variable | Défaut | Rôle |\n|---|---|---|\n| `PORT` | `3777` | Port HTTP/SSE |\n| `HOST` | `127.0.0.1` | Adresse d'écoute |\n| `MAX_MESSAGES` | `2000` | Messages gardés en mémoire |\n| `WIKICHAT_MAX_SESSIONS` | `30` | Budget de spawn concurrent |\n| `WIKICHAT_DAEMON_MAX_MS` | `1800000` | Durée max d'un daemon — la seule borne qui tienne (voir ci-dessous) |\n| `WIKICHAT_DAEMON_MAX_TURNS` | `50` | Tours max, si le CLI le reconnaît (ignoré en 2.1.86 et 2.1.237) |\n| `WIKICHAT_MAX_SPAWN_DEPTH` | `3` | Profondeur de spawn maximale |\n| `WIKICHAT_MAX_RESUME_MB` | `5` | Plafond de transcript repris via `--resume` |\n| `WIKICHAT_PRINCIPAL_GATE` | `any-named` | `any-named` / `strict` / `0` |\n| `WIKICHAT_DORMANT_GRACE_MS` | `300000` | Délai avant mise en sommeil |\n| `WIKICHAT_DORMANT_DISABLED` | (off) | `1` sur toute instance **servant des agents autonomes** — la porte dormante suppose que « personne n'est là » = « rien à faire », ce qui est faux dès qu'une routine doit tourner la nuit |\n| `WIKICHAT_AUTONOMOUS_TEAM` | (off) | `1` provisionne les triggers de la team |\n| `WIKICHAT_TRIGGERS_DISABLED` | (off) | `1` désarme le moteur de triggers |\n| `WIKICHAT_NO_OVERLAY_INSTALL` | (off) | `1` empêche l'installation auto de l'overlay |\n| `WIKICHAT_HOOK_WAIT_MS` | `45000` | Attente du hook quand la conversation est en cours |\n| `WIKICHAT_HOOK_MAX_RELAYS` | `12` | Relances consécutives sans intervention humaine |\n| `WIKICHAT_HOOK_MAX_WAIT_MS` | `300000` | Plafond d'attente sur un `eta_seconds` annoncé |\n| `WIKICHAT_WATCH_MAX_MS` | `1800000` | Durée de vie d'un guetteur de boîte |\n\n## Tests\n\n```bash\nnpm start &   # le serveur doit tourner\nnpm test\n```\n\n30 assertions, chacune correspondant à un défaut qui a existé. Le motif récurrent de ce projet est le mécanisme écrit mais pas branché : la syntaxe est valide, le serveur démarre, et rien ne se passe. `node --check` ne l'attrape pas.\n\nLa suite est réentrante — espace de noms fixe, purge de ce qu'elle a créé — et vérifiée sur une installation neuve autant que sur une machine rodée. Deux défauts n'apparaissaient que sur la première : la porte dormante exigeait un projet au registre, vide par construction sur un poste neuf, et le scan de projets ne cherchait qu'à un chemin Windows codé en dur.\n\n**Non éprouvé** : macOS et Linux. Le code ne contient plus de chemin spécifique à Windows, mais personne n'y a lancé le serveur.\n\n## Licence\n\n[MIT](./LICENSE)\n"}