cd /news/large-language-models/60-jours-avec-claude-code-sur-un-erp… · home topics large-language-models article
[ARTICLE · art-49025] src=dev.to ↗ pub= topic=large-language-models verified=true sentiment=· neutral

60 jours avec Claude Code sur un ERP en production : le bilan honnête, sans hype, chiffres bruts

A developer who spent 60 days using Claude Code on a production ERP project reports 984 commits, 131,628 lines of TypeScript/TSX/JS/JSX, 276 Supabase migrations, and 74 architecture decisions. The project involved 58 active days, 44 documented sessions, and 9 versions of an AI piloting doctrine, with the developer emphasizing honest measurement over hype.

read12 min views1 publishedJul 7, 2026

Mardi soir, fin de journée, l'open space s'est vidé sauf Étienne. Étienne tient soixante pour cent de la maison et travaille la semaine dans un fonds qui rachète des éditeurs de logiciels, et il regarde les ERP toute l'année comme d'autres regardent des bilans. Il s'est posé sur le bord de mon bureau, une bouteille d'eau métallique à la main, et il a dit ce qu'il dit toujours quand il sent qu'on est en train de se raconter une histoire. « Sur quoi c'est calé ? »

J'allais lui répondre par un récit. Soixante jours de production solo sur Rembrandt avec Claude Code, l'apprentissage de la doctrine, les rétractations en cours de route, les incidents qui ont durci les règles. La forme déclarative était prête. Mais Étienne ne demande pas un récit, il demande l'inventaire matériel. Alors j'ai ouvert un terminal et j'ai laissé wc -l

parler. Cet article est ce que j'aurais dû lui donner sans qu'il ait à me le demander, le bilan chiffré sec, ce qui a marché, ce qui n'a pas marché, ce que je ferais autrement. Pas une success story, pas un cautionary tale. Juste l'audit que personne ne fait sur DEV.to parce qu'on est tous occupés à publier les bouts qui brillent.

Ce qui est en jeu derrière la question d'Étienne, c'est moins la performance d'un dispositif que la possibilité d'en faire la mesure honnête. Soixante jours de pratique avec un assistant IA sur un projet en production constituent à ce stade un objet rare. La plupart des publications qui tournent sur le sujet sont soit des démonstrations brèves sorties d'un hackathon, soit des annonces marketing d'éditeurs. Le retour terrain à soixante jours, livré avec ses chiffres et ses rétractations, n'existe pratiquement pas. C'est ce manque que je me propose de combler ici, sans plus de pédagogie qu'il n'en faut.

Soixante jours calendaires entre la première session et aujourd'hui. Cinquante-huit jours actifs sur ces soixante, ce qui veut dire deux journées sans commit et explique pourquoi le reste de ma vie a tenu de justesse. Sur cette fenêtre, le repo a accumulé neuf cent quatre-vingt-quatre commits signés de ma main, ce qui en moyenne fait seize commits par jour ouvré, sur des journées qui ne sont pas que du code, qui sont aussi de la compta, des téléphones de parents, des arbitrages d'équipe et des nuits où je relis du SQL pendant que tout dort.

Le filesystem dit aujourd'hui cent trente et un mille six cent vingt-huit lignes de TypeScript, TSX, JS, JSX, hors node_modules

, hors .next

, hors .claude

, mesuré par un find

que je peux relancer devant qui veut. Pour donner une échelle, j'avais signé en mars un pack à cinq chiffres chez un éditeur ERP commercial européen dont l'annexe technique facturait le développement custom au nombre de lignes produites. Le pack est en négociation de remboursement.

Sur cette masse de code vivent soixante-quatorze décisions d'architecture écrites, deux cent soixante-seize migrations Supabase, dix-huit règles projet dans .claude/rules/

, quarante-quatre sessions documentées dans docs/sessions/

, et, dans un dossier séparé, soixante-sept brouillons d'articles DEV.to dont vingt-quatre publiés, ce que vous lisez en ce moment. La doctrine de pilotage IA a connu neuf versions sur la période, v0.2, v0.3, v0.3.1, v0.3.2, v0.3.3, v0.4, v0.4.1, v0.6, v0.7, chacune ancrée dans un fait nouveau documenté ou une rétractation publique. Le saut v0.5 a été assumé après la session empirique gorgon mi-mai, pas escamoté.

Je n'écris pas ces chiffres pour impressionner. Je les écris parce que la suite ne tient pas debout sans eux, et parce que la pratique sera passée son temps à démontrer qu'ils ne disent pas ce qu'ils ont l'air de dire.

Trois mécanismes, et seulement trois, méritent d'être nommés. Chacun a son incident de fondation daté, et chacun a payé son coût d'apprentissage avant d'être rentable.

Falsifier avant de fixer. Le 6 mai en début d'après-midi, un bug Sentry remonte que le compteur d'inscriptions du jour affiche zéro alors qu'on en a saisi trois en matinée. Mon réflexe arrive avant le protocole, et la main est déjà sur le clavier. « Le cache n'est pas invalidé », je commit, je déploie. Trente minutes plus tard, rollback, le bug est toujours là. La cause réelle, qu'une sonde grep de quatre-vingt-dix secondes aurait remontée, c'est qu'aucun appel à cache_invalidate

n'existait dans le pipeline d'inscription, pas un cache obsolète mais un cache absent. La règle textuelle qui demandait de formuler une hypothèse falsifiable avant tout fix vivait dans CLAUDE.md depuis trois semaines. Je ne l'ai simplement pas suivie ce jour-là, parce qu'aucun dispositif n'interrompait ma course entre le bug et le commit. Dix jours plus tard, le skill falsify-before-fix

est commit, non plus une règle textuelle mais un interrupteur matériel qui se charge sur les mots-clés fix, bug, doesn't work et qui impose son protocole avant qu'aucune ligne ne soit écrite. L'écart entre la règle textuelle qui ne tient pas sous pression et le dispositif matériel qui interrompt physiquement la session est exactement ce qui sépare une doctrine pieuse d'une doctrine opérationnelle. Sur les quarante-quatre sessions consignées, je peux nommer au moins une douzaine d'incidents où ce skill a évité un cycle fix-puis-rollback. Cinq à dix minutes de sondes en amont valent trente à quatre-vingt-dix minutes économisées en aval, ce qui à raison de deux ou trois bugs par semaine se traduit en une journée pleine de récupérée chaque mois.

Live, Snapshot, Cache. Fin avril, je prépare l'audit source unique que je remettais à plus tard depuis trois mois. Je croise deux requêtes que personne n'avait jamais croisées avant. Une fiche élève, la colonne contacts.montant_total

portait mille cent cinquante-neuf euros saisis quelque part en 2024, jamais touchés depuis. La somme réelle des échéances, calculée à la volée, en faisait deux mille deux cent soixante-deux. Mille euros d'écart, sur une seule fiche, sans qu'aucune alarme n'ait jamais sonné. J'élargis le grep, cinq cent soixante contacts dans le même état, parfois à plusieurs milliers d'euros près. La valeur était lue chaque jour dans le dashboard trésorerie, traitée comme un fait passé immuable alors qu'elle aurait dû vivre à la volée. La règle qui en sort impose à toute nouvelle colonne stockée de répondre à trois questions avant qu'aucune migration ne passe en revue. La valeur doit-elle évoluer avec ses sources ? Le calcul à la volée est-il acceptable côté performance ? Quel mécanisme de rafraîchissement déclaré si on choisit le Cache ? Aucune nouvelle colonne dérivable n'entre dans le schéma sans réponse explicite à ces trois questions. La règle a fermé la classe à la racine, et trois mois plus tard, l'audit ne trouve plus la même famille d'incidents. C'est cette absence dans les nouveaux audits qui constitue le vrai succès, plus encore que les cinq cent soixante fiches corrigées.

Filesystem plutôt que résumé. R2 est sortie en avril après un constat qui m'avait coûté du sommeil, le backlog.md

que je relisais le matin pour me situer disait des choses qui n'étaient plus vraies. Pas par malveillance, par construction. Un fichier de résumé est produit vite et maintenu lentement, il vieillit en silence comme un cache sans rafraîchisseur. Je l'avais déjà mesuré sur l'inventaire des dettes techniques, onze jours d'écart entre ce que INVENTAIRE.md

annonçait et ce que git log

disait avoir été fait, sans qu'aucune alarme n'apparaisse, parce qu'aucune alarme n'avait été câblée. Depuis R2, tout point d'état commence par git log --since='7d'

, ls docs/adr/ | wc -l

, git status --porcelain exécutés contre le filesystem, avant la lecture du résumé écrit. Le résumé écrit n'est jamais l'autorité. Le filesystem l'est toujours, parce que c'est le seul artefact qui ne ment pas par négligence d'écrivain. Cette règle me sauve une fois par semaine d'une assertion fausse que j'allais sortir de bonne foi.

Trois pièges, dont chacun a sa propre cicatrice. Je les nomme parce qu'aucune publication DEV.to que j'ai lue sur Claude Code ne les avoue, et qu'ils sont précisément ce qui distingue la pratique réelle du thought leadership de hackathon.

Le réflexe d'over-engineering de l'agent. Mi-mai je demande à Claude Code d'automatiser l'envoi des premiers contacts aux leads, un cas métier simple qui devrait tenir en une journée de dev. La première proposition arrive en six fichiers, table app_config

dédiée, warm-up progressif des envois, hash déterministe pour l'idempotence, dashboard admin pour superviser la cadence. « Plus simple », je tape. La deuxième proposition coupe le warm-up mais garde la table de config et le hash. « Plus simple encore. » La troisième proposition arrive enfin à six fichiers honnêtes, une route de cron, un email_outbox déjà existant qu'on réutilise, et une journée de dev qui tient sa promesse. Trois tours de recadrage pour empêcher l'agent d'écrire une feature deux fois trop chère que personne n'avait demandée. Le piège n'est pas qu'il propose la solution complexe, c'est qu'il la propose si bien que tu acceptes la première fois, et que tu ne sais que tu te fais déborder qu'au bout d'une semaine, quand la table app_config

que tu n'as jamais demandée vit dans ton schéma comme un meuble qui ne sert à rien. La règle R11 Parsimony a été codifiée à la suite de cette session, mais elle n'a pas encore son dispositif matériel équivalent au skill falsify-before-fix

. C'est une dette doctrinale ouverte que j'aurais aimé clore avant la version v0.7.

La dérive silencieuse des résumés que j'écris moi-même. R2 décrit le problème côté lecture, les résumés vieillissent sans alarme. Ce que j'ai mis du temps à comprendre, c'est que ce sont d'abord les résumés que moi je produis qui dérivent. La doctrine elle-même a péché contre R2, pendant des semaines, le manifesto annonçait « trente-cinq mille lignes » pour qualifier Rembrandt. La pratique en avait largement plus. Le chiffre avait été projeté une fois, repris six fois dans les versions successives, jamais re-mesuré. Quand un quatrième relecteur externe l'a fait re-mesurer, le compteur a explosé à cent dix-huit mille puis à cent trente et un mille au moment où j'écris cet article. La doctrine était un Cache sans rafraîchisseur projeté sur sa propre description. La rétractation est consignée dans les notes de release de la version v0.4.1, parce qu'écrire une doctrine sur la falsification systématique sans rétracter ses propres chiffres faux serait précisément la complaisance qu'elle dénonce. La leçon dure, si ta propre doctrine ne survit pas à sa propre règle, ce n'est pas la règle qui est mauvaise, c'est ton application qui n'avait pas encore commencé.

Les sub-agents qui ne chargent pas la même mémoire que moi. Le commit 3756e63

du 18 mai a été poussé directement sur la branche main

par un sub-agent ERP que j'avais brieffé sur une refonte d'autosend. Le feedback user-scope « vérifie toujours git branch --show-current avant un commit non-trivial » existait depuis le 14 mai, j'avais payé son apprentissage par un incident de la même nature. Mais le feedback vit dans la mémoire

git log

après coup et qu'on découvre la branche d'où vient le commit. Le filesystem comme autorité, encore.Si je devais redémarrer Rembrandt aujourd'hui sachant ce que je sais, je ferais trois choses différemment et trois seulement. Le reste, la masse du travail, c'est-à-dire schema, routes, auth, dashboard, planning, émargement, valorisation, finance, je referais à peu près comme c'est venu, parce que la nature du projet imposait sa structure et que j'aurais eu peu de marge de manœuvre.

J'installerais le skill falsify-before-fix dès le premier jour, pas après l'incident du 6 mai. Il n'existait pas alors, je sais bien. Mais aujourd'hui que le dispositif existe, le premier réflexe d'un dev solo qui démarre Claude Code devrait être de cloner le repo

doctrine-counterpart

et de lancer ./install.sh

sur son projet, J'écrirais le premier ADR avant la première feature, pas après le premier incident. L'ADR-0001 dans ce repo est daté de fin mars et porte sur la décision stack Next.js Server Components, il a été écrit deux semaines après la décision, en remontage. Les huit suivants ont la même cicatrice. C'est seulement à l'ADR-0009 que j'ai commencé à écrire avant la décision, et c'est seulement à l'ADR-0024 que j'ai commencé à écrire l'ADR comme conséquence d'un audit, pas comme cérémonie d'archivage. La règle R3 Success criteria before code aurait dû être ma règle zéro. Elle est devenue la troisième parce que j'avais mis du temps à comprendre qu'elle valait pour la doctrine elle-même.

Je refuserais le premier sub-agent autonome jusqu'à avoir matériellement testé sa propagation de mémoire. Le pattern « délègue à un sub-agent pour aller plus vite » est tentant à la quatrième semaine, quand on a accumulé assez de discipline pour penser qu'on peut s'en passer ponctuellement. C'est le moment où l'incident 3756e63

arrive, parce que c'est exactement le moment où on cesse de vérifier ce qu'on a délégué. La règle R12 amendée dans la version v0.7 codifie le test matériel obligatoire avant adoption d'un sub-agent, j'aurais dû l'inventer à la deuxième semaine, pas à la sixième.

Soixante jours plus tard, ce qui me reste de cette période n'est pas la fierté des cent trente et un mille lignes. Les lignes existent, elles tiennent, elles tournent en production, elles servent une équipe et une école, c'est très bien. Ce qui me reste, c'est la mesure que je n'avais pas au début et qui est devenue ma seule boussole. Cette mesure n'est ni la vitesse de production, ni la qualité du code prise isolément. Elle est l'écart entre ce que je crois avoir fait et ce que le filesystem dit que j'ai fait.

R2 Filesystem over summary est la règle-mère de la doctrine parce qu'elle ferme cet écart. Tant qu'on travaille en accord avec elle, on n'écrit pas ses propres mensonges. Tant qu'on l'oublie, on les écrit, et l'IA les ré-écrit avec nous parce qu'elle a été entraînée pour nous plaire.

Un agent qui ne vous contredit pas n'est pas un counterpart, c'est une dactylo plus rapide. La doctrine qui a tenu sur ces soixante jours est une prothèse de contradiction matérielle pour qui code sans PR review et refuse de coder à l'oreille. Si une seule des règles vous évite un cycle fix-rollback la semaine prochaine, elle s'est déjà remboursée. Si aucune ne vous parle, attendez votre premier incident silencieux, il arrivera, et ce jour-là, vous saurez quoi installer.

Bilan honnête à 60 jours sur Rembrandt — 131 628 lignes, 74 ADR, 67 articles DEV.to, 9 versions de doctrine, 44 sessions documentées, 984 commits sur 58 jours actifs. Prénoms et école fictifs, scènes recomposées, négociation commerciale en cours. La doctrine référencée : github.com/michelfaure/doctrine-counterpart (CC-BY-4.0).

── more in #large-language-models 4 stories · sorted by recency
pinecone.io · · #large-language-models
RAG
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/60-jours-avec-claude…] indexed:0 read:12min 2026-07-07 ·