Imaginez un bureau. Au début, vous avez trois feuilles posées proprement. Une pour les règles du projet, une pour la config de l'agent, une pour les notes. Vous savez exactement où tout se trouve.
Six mois plus tard, ce bureau ressemble à une salle d'archives après un tremblement de terre. Des piles partout. Des feuilles qui réfèrent à d'autres feuilles que vous ne retrouvez plus. Des doublons. Des versions obsolètes. Et le pire : vous ne savez plus lesquelles sont encore à jour.
C'est exactement ce qui m'est arrivé avec Claude Code.
Avant de continuer de lire la suite de l'article, je vous invite à vous inscrire à ma newsletter, pour connaître en avant première les futurs sujets traités chaque semaine.
Le problème : la scalabilité invisible du Markdown
Dans Claude Code, tout est Markdown. Chaque agent a son fichier .md. Chaque skill, chaque rule, chaque commande. Le CLAUDE.md du projet. Les rules globales. Les rules locales. Les skills appris automatiquement.
Au début, c'est génial. Le Markdown est lisible, versionnable, simple. Trois fichiers, on s'y retrouve les yeux fermés.
Mais il y a un seuil. Et ce seuil, personne ne vous prévient quand vous le franchissez.
Voici mes chiffres réels :
| Ce qui a grandi | Nombre |
|---|---|
| Fichiers Markdown indexés | 1 327 |
| Éléments système (hooks, agents, tables...) | 451 |
| Références croisées MD ↔ éléments | 3 761 |
| Projets couverts | 14 |
Quand un hook change de signature, combien de fichiers MD le mentionnent ? Quand une table PostgreSQL gagne une colonne, quels CLAUDE.md réfèrent à son ancien schéma ? Quand un agent est renommé, quels rules files le citent encore sous l'ancien nom ?
Sans système, la réponse est : vous ne savez pas. Et c'est ça, la dette technique documentaire.
La métaphore du classeur vivant
La solution n'est pas de mieux ranger ses feuilles. C'est de remplacer le bureau par un classeur qui sait lui-même quand une feuille est obsolète.
J'ai construit un MD Registry : trois tables PostgreSQL qui forment un graphe de dépendances entre tous les éléments du système et tous les fichiers Markdown qui les documentent.
L'architecture en 30 secondes
system_registry (451 éléments)
|
| références (3 761 liens)
|
md_file_registry (1 327 fichiers)
Table 1 — system_registry : chaque hook, agent, skill, table SQL, vue, fonction, cron et rule possède une entrée avec un UUID unique, un hash SHA256 de son contenu, et un flag is_stale.
Table 2 — md_file_registry : chaque fichier Markdown est indexé avec son chemin, son projet d'appartenance, un hash de contenu, et un flag needs_regeneration.
Table 3 — md_element_references : le graphe. Chaque lien dit "ce fichier MD parle de cet élément système". 3 761 de ces liens, détectés automatiquement par analyse lexicale avec correspondance de mots entiers.
Le principe est simple : quand un élément change, son hash change. Son flag is_stale passe à true. Et tous les fichiers MD qui le réfèrent héritent du flag needs_regeneration.
Trois canaux de détection automatique
Un registre statique ne sert à rien. La valeur, c'est la détection en temps réel.
Canal 1 : Hook PostToolUse (temps réel)
À chaque fois que Claude Code modifie un fichier (Write ou Edit), un hook se déclenche en moins de 5 secondes. Il compare le hash du fichier modifié avec le hash stocké dans le registre. Si ça diverge : staleness propagée.
Canal 2 : Cron N1 T13 (toutes les minutes, en idle)
Pendant que je ne travaille pas, un processus inconscient (oui, mon système a un modèle cognitif à 4 niveaux, mais c'est un autre article) vérifie 20 éléments par run. Les plus anciennement vérifiés d'abord. En une heure d'idle, il couvre l'intégralité du registre.
Canal 3 : Bootstrap manuel (idempotent)
Un script qui re-scanne tout depuis zéro. Utile après une migration, un import massif, ou quand je doute de l'intégrité du système. Il utilise ON CONFLICT DO UPDATE — je peux le lancer 10 fois, le résultat sera le même.
Le hashing intelligent : chaque type a sa méthode
Tous les éléments ne se hashent pas de la même façon. Un script TypeScript n'est pas une table PostgreSQL.
| Type d'élément | Méthode de hash |
|---|---|
| Scripts (.ts, .js, .sh) | SHA256 du contenu fichier, tronqué à 16 caractères hex |
| Tables SQL | Hash de la structure : column_name:data_type:default via information_schema |
| Vues SQL | Hash de la définition via pg_get_viewdef() |
| Fonctions SQL | Hash de la définition via pg_get_functiondef() |
| Learned skills (sans fichier disque) | Hash de name:sections:last_updated |
| Hooks HTTP | Mapping endpoint vers fichier source (30 entrées maintenues manuellement) |
Le point clé : les éléments sans fichier physique (tables, vues, fonctions, skills RAG) sont hashés via leurs métadonnées en base. Pas de fichier sur disque ne signifie pas "pas de hash".
Le monitoring : voir l'état du système en un coup d'œil
Avoir un registre sans interface, c'est comme avoir un classeur rangé dans un coffre-fort. J'ai construit un dashboard dans mon outil de monitoring (rag-monitoring, SvelteKit) :
4 cartes résumées : Total éléments | Stale | Couverture hash | MD à régénérer
Table de synthèse : ventilation par type d'élément avec compteurs stale/ok
Filtres interactifs : par type, par statut (stale/ok/tous)
Section d'alerte : les fichiers MD qui nécessitent une régénération, en rouge
L'API derrière (/api/pilot/v2/md-registry) accepte des paramètres de filtrage — je peux interroger par type ou par statut en un appel.
Ce que les chiffres révèlent
Après 3 mois d'utilisation :
| Métrique | Valeur | Interprétation |
|---|---|---|
| Couverture hash | 100% (451/451) | Chaque élément est tracké |
| Éléments stale | 146 (32%) | 145 sont des learned skills — normal, ils évoluent souvent |
| Fichiers MD à régénérer | 1 seul | Le système fonctionne |
| Cross-références | 3 761 | Chaque MD sait de quoi il parle |
| Projets couverts | 14 | Centralisation cross-projets effective |
Le chiffre le plus parlant : 1 seul fichier à régénérer sur 1 327. Pas parce que rien ne change — les 146 éléments stale prouvent le contraire — mais parce que le système propage l'information de staleness en temps réel et permet de traiter les mises à jour avant qu'elles ne s'accumulent.
Les 5 leçons que j'aurais aimé connaître avant
1. Le hash SHA256 tronqué suffit. 16 caractères hex = 64 bits d'entropie. Pour de la détection de changement (pas de la cryptographie), c'est largement suffisant et ça économise du stockage.
2. Le TRUNCATE dans le scan de références est un choix délibéré. Mon script de cross-références fait un TRUNCATE avant chaque re-scan complet. Risque de perte temporaire ? Oui. Mais l'alternative (diff incrémental) est exponentiellement plus complexe pour un gain négligeable — le scan complet prend moins de 30 secondes.
3. Les hooks HTTP nécessitent un mapping manuel. 30 endpoints mappés vers leurs fichiers source. C'est le seul point de maintenance manuelle du système. J'aurais pu auto-détecter via les routes Express, mais le pragmatisme l'a emporté.
4. Les learned skills sont toujours "stale". Leur hash est recalculé à chaque bootstrap. C'est voulu : ils évoluent au fil des sessions. Les 145 learned skills stale ne sont pas un bug, c'est le système qui dit "ces éléments vivent".
5. L'idempotence du bootstrap est non-négociable. ON CONFLICT DO UPDATE sur chaque insertion. J'ai lancé ce script des dizaines de fois pendant le développement. Jamais de doublon, jamais de corruption. C'est la garantie qui permet d'itérer sans peur.
Pourquoi ça marche : le changement de paradigme
La plupart des développeurs gèrent leurs fichiers Markdown comme des documents indépendants. Chacun est écrit, relu, commité, oublié. Quand le code évolue, la doc ne suit pas.
Le MD Registry inverse cette logique : chaque fichier MD déclare ses dépendances, et le système sait en permanence lesquels sont obsolètes.
C'est la différence entre :
- "Je dois relire toute ma doc pour vérifier qu'elle est à jour" (O(n) humain)
- "Le système me dit que 1 fichier sur 1 327 a besoin d'attention" (O(1) machine)
Pour les architectures multi-agents où chaque composant est documenté en Markdown, ce n'est plus un nice-to-have. C'est une condition de survie.
Pour aller plus loin
Le MD Registry est une brique d'une architecture plus large que je construis autour de Claude Code : un système cognitif multi-niveaux avec conscience, inconscient, mémoire et voie efférente. Si le sujet vous intéresse, l'article précédent sur les agents éphémères explore un autre aspect de cette architecture.
Le code complet du bootstrap, des scripts d'analyse et de l'interface de monitoring est disponible dans le rapport technique détaillé.
Articles liés :
- RTK : l'outil qui m'a révélé combien mes commandes gaspillaient de tokens
- Monitoring RAG et conscience d'optimisation
- Fusion d'appels fonction : tokens, latence et oublis
Qui suis-je ?
Je suis Mathieu GRENIER, CTO d'Easystrat une startup de Montpellier, en France. Je manage une équipe d'une dizaine d'ingénieurs (Graphistes, IA, frontend, backend, devOps, AWS) en remote depuis le Japon.
J'ai aussi mon activité de freelance, où je conseille des entrepreneurs dans leurs projets d'application.
Avec mon expérience personnelle de plus de 15 ans en ESN, j'ai pu travailler pour un large panel d'entreprises de différentes tailles. Ma compréhension des problèmes métiers est une de mes grandes forces et permet à mes clients de pouvoir se projeter plus facilement.
L'essentiel de mon travail consiste à canaliser l'énergie des entrepreneurs sur l'essence même de leur projet.
La technologie, les méthodes, le management sont le cœur de mes compétences.
Vous pouvez me faire confiance sur ces points là.
Si vous voulez me parler d'un de vos projets, n'hésitez pas à m'envoyer un email avec vos disponibilités à : contact@mathieugrenier.fr
Tous les articles de ce blog sont écrits par moi, même si je peux m'aider de l'IA pour illustrer mes propos. Mais jamais je ne fournis d'articles 100 % IA
1 327 fichiers Markdown, 14 projets, zéro chaos : comment un registre centralisé a éliminé ma dette technique documentaire