Aller au contenu
Dispatch

Guardrails vs guidelines : sortir du CLAUDE.md

Sébastien Giband · Dev Symfony/TypeScript · terminal-first ·
Claude Code PHP/Symfony 7 TypeScript/React

TL;DR

Une règle écrite dans un CLAUDE.md, l'agent finit par l'oublier : quelques dizaines de milliers de tokens plus tard, elle n'est plus dans sa fenêtre. Un guardrail — un hook qui refuse l'action — ne s'oublie pas. J'ai déplacé mes règles qui comptent du markdown vers une quinzaine de hooks. Voici ce que ça change, et ce que ça coûte vraiment.

coding-agents guardrails hooks claude-code dev-experience

Une règle que l’agent peut ignorer n’est pas une règle. C’est un vœu pieux.

Sur du code écrit par des humains, on s’en sortait avec un vœu : une convention dans un doc, une culture d’équipe, un reviewer attentif. Une guideline ratée se rattrapait à la review. Le rythme laissait le temps.

Avec un agent de coding qui génère du code plusieurs fois plus vite, ce filet craque. Le reviewer humain devient le goulot d’étranglement, et le vrai coût de l’IA apparaît : non pas la licence, mais la verification tax — le temps passé à relire du code qui ressemble dangereusement à du code correct. Le rapport DORA 2025 le formule à sa manière (plus l’adoption IA monte, plus l’instabilité de livraison monte — sauf si tu investis dans ta plateforme) ; je le rapporte, je ne l’ai pas mesuré moi-même. Mais le mécanisme, lui, je le vis tous les jours.

Une guideline s’oublie, un guardrail refuse

La bascule tient en un exemple. « Ne commit pas de .env », écrit dans un CLAUDE.md : ça tient deux ou trois sessions, puis ça sort de la fenêtre de contexte et un beau jour la clé part avec le commit. La même règle en hook — un script qui scanne le diff staged et sort en erreur s’il matche — ne s’oublie jamais. Le système refuse l’action, point.

C’est ça, la différence entre une guideline (une règle qu’on espère lue) et un guardrail (une contrainte que le système applique). Elle n’est pas cosmétique, elle est structurelle : l’une dépend de la mémoire de l’agent, l’autre pas.

Ce que j’applique par gate (pas par espoir)

En usage quotidien, sur mes projets perso — testé, pas théorique :

  • un commit est bloqué tant qu’une review n’a pas tourné ;
  • un push est bloqué si tsc → lint → tests ne passent pas, dans cet ordre ;
  • un .env ou un secret ne quitte jamais le working dir ;
  • une poignée de commandes shell destructrices sont refusées d’office ;
  • et la review ne rend pas un avis « à la louche » mais un verdict machine (un bloc YAML) : s’il reste du CRITICAL ou du HIGH, c’est iterate ; sinon ship. Le score qualité « ressenti » du modèle, lui, ne gate rien — il informe, il ne décide pas.

Le glissement mental est là : on ne code plus seulement avec l’agent, on code l’environnement autour de l’agent. Le harnais devient le produit ; les hooks sont le harnais.

Ce que ça coûte (parce que ça coûte)

Un guardrail n’est pas gratuit, et prétendre le contraire serait vendre du rêve.

Il faut le maintenir : chaque gate est du code, avec ses bugs. Et un gate qui produit des faux positifs est pire que pas de gate du tout — parce que tu commences à le contourner, et un garde-fou qu’on enjambe par réflexe n’est plus qu’un théâtre de sécurité. Le seuil est étroit : assez strict pour protéger, assez juste pour qu’on ne cherche pas à le désarmer.

Il y a aussi les cas où le jeu n’en vaut pas la chandelle : un script jetable, un one-shot en solo, un repo de test. Mettre trois gates sur un fichier qu’on supprimera ce soir, c’est de l’over-engineering — et je me suis fait la remarque plus d’une fois.

Le jour où mon propre gate m’a filé entre les doigts

Petit aveu, parce qu’un garde-fou qui n’a jamais lâché n’existe pas. J’avais un hook de review censé estampiller un commit après la review. Sauf qu’en enchaînant l’estampille et le commit dans le même appel shell, la logique du gate se faisait doubler : l’action passait « validée » alors qu’elle ne l’était pas. Ma première théorie — « le hook déconne » — était fausse. Le vrai bloquant était ma propre séquence, avalée par un enchaînement trop malin. J’ai documenté le piège dans le refus du hook lui-même et ajouté une vérification d’écriture. Un guardrail se debug comme du code de prod, parce que c’en est.

À se demander avant d’écrire la prochaine règle

La question utile, avant de rédiger ta prochaine note « bonnes pratiques avec l’agent » : est-ce que je peux la transformer en check ? En lint ? En hook ? En policy ? Si oui, fais-le — elle tiendra pour toujours au lieu de trois sessions. Si non, c’est souvent qu’elle est trop floue pour être utile, même à un humain.

Une guideline, c’est de la confiance qu’on renouvelle à chaque session. Un guardrail, c’est de la confiance qu’on n’a plus besoin d’accorder. Sur du code généré à la chaîne, la seconde passe mieux à l’échelle — et accessoirement, elle dort mieux la nuit.

Reste une conséquence qu’on ose rarement chiffrer : si le harnais est le produit, une part assumée de ce que tu paies — abonnement, tokens — doit financer le harnais lui-même, pas seulement les tokens qui crachent du code. Le pourcentage juste, je ne sais pas le fixer — mais je sais qu’il n’est pas nul. Ça mérite son propre dispatch ; celui-ci s’arrête là.

Aller plus loin