IA générative et agents de codage : comprendre, choisir et bien travailler avec un agent IA
Des fondamentaux de l'IA aux agents de codage — LLM, prompts, mémoire, sous-agents, skills, MCP, permissions — puis un atelier complet : un mini-projet réalisé de A à Z avec Claude Code, Context7 et frontend-design, en TDD, audité, conteneurisé et livré en v1.0.0.

En quelques années, l'intelligence artificielle est passée du laboratoire à notre poche, puis à notre éditeur de code. Elle rédige, résume, traduit, explique — et désormais, elle agit : elle lit un projet, modifie des fichiers, lance des tests et propose des corrections. Pour un développeur, un architecte ou un DSI, la question n'est plus de savoir s'il faut s'y intéresser, mais comment l'adopter avec méthode, efficacité et sécurité.
Cet article propose un parcours complet, du plus général au plus concret : ce qu'est réellement l'IA, comment fonctionne un modèle de langage, ce qui distingue un assistant d'un agent, comment choisir et piloter un agent de codage, comment rédiger un bon prompt, gérer la mémoire, configurer les permissions et protéger les données. Les exemples s'appuient sur Claude Code, l'agent de codage d'Anthropic, mais les principes valent pour la plupart des outils.
Comment lire cet article ? Les parties 01 à 05 posent les bases (accessibles à tous). Les parties 06 à 09 décrivent les agents et leur écosystème. Les parties 10 à 15 sont un guide pratique pour les équipes techniques. Les parties 16 à 24 forment un atelier complet : le mini-projet LinkLite, réalisé de A à Z avec Claude Code, jusqu'à sa version 1.0.0. Un glossaire termine l'article.
Comprendre l'intelligence artificielle
Une définition simple
L'intelligence artificielle désigne l'ensemble des techniques qui permettent à une machine d'accomplir des tâches que l'on associe habituellement à l'intelligence humaine : reconnaître une image, comprendre une phrase, traduire un texte, prendre une décision, résoudre un problème ou générer un contenu.
Analogie : un programme classique, c'est une recette de cuisine écrite ligne par ligne par un humain. Une IA, c'est un apprenti cuisinier à qui l'on montre des milliers de plats réussis jusqu'à ce qu'il en déduise lui-même les règles.
Cette différence est fondamentale. Dans la programmation traditionnelle, le développeur écrit les règles. Dans l'apprentissage automatique, on fournit des exemples et la machine apprend les règles.
Une brève histoire
L'IA n'est pas née avec les assistants conversationnels. Elle a connu plusieurs vagues d'enthousiasme et de désillusion (les « hivers de l'IA ») avant l'accélération actuelle, rendue possible par trois ingrédients réunis : des données massives, une puissance de calcul abondante (GPU) et de nouvelles architectures de réseaux de neurones.
IA faible, IA générale
Toutes les IA en production aujourd'hui sont des IA dites « faibles » ou spécialisées : elles excellent dans un domaine précis (langage, image, recommandation…) sans conscience ni compréhension du monde au sens humain. L'IA générale — capable de raisonner sur n'importe quel sujet comme un humain — reste un objectif de recherche et un sujet de débat. Garder cette distinction en tête évite deux erreurs symétriques : sous-estimer les outils actuels, ou leur prêter des capacités qu'ils n'ont pas.
Les grandes familles : Machine Learning, Deep Learning, NLP, LLM et IA générative
Les termes se chevauchent et sont souvent employés à tort comme synonymes. La meilleure image est celle des poupées russes : chaque notion est un sous-ensemble de la précédente.
Notion | Ce que c’est | Exemple concret |
|---|---|---|
Machine Learning | Algorithmes qui apprennent des régularités à partir de données. | Détection de fraude bancaire, scoring de crédit, prévision des ventes. |
Deep Learning | Machine Learning fondé sur des réseaux de neurones à nombreuses couches. | Reconnaissance d'images médicales, reconnaissance vocale. |
NLP | Traitement automatique du langage naturel (texte et parole). | Traduction, analyse de sentiment, extraction d’informations d’un CV. |
IA générative | Modèles capables de produire un contenu nouveau : texte, image, son, code. | Générer une illustration, un résumé, un brouillon de courrier. |
LLM | Grand modèle de langage entraîné sur d’immenses corpus de textes et de code. | Assistants conversationnels, agents de codage. |
Comment fonctionne un LLM ?
Un LLM ne « cherche » pas une réponse dans une base de données : il prédit, mot après mot (plus exactement token après token), la suite la plus plausible d'un texte. Un token est un fragment de mot : « développement » peut être découpé en plusieurs tokens.
Analogie : c'est l'autocomplétion de votre téléphone, mais entraînée sur une bibliothèque gigantesque et capable de tenir compte de pages entières de contexte. Elle ne récite pas : elle compose.
Trois notions suffisent pour comprendre l’essentiel du comportement d’un LLM :
La fenêtre de contexte : la quantité de texte que le modèle « voit » à un instant donné (votre demande, l'historique de la conversation, les fichiers lus). Au-delà, l'information n'est plus prise en compte.
La date de coupure des connaissances : le modèle ne connaît que ce qui figurait dans ses données d'entraînement. D'où l'intérêt de lui fournir la documentation à jour.
La température : un réglage qui dose la part d'aléatoire. Basse, les réponses sont stables et prévisibles ; haute, elles sont plus créatives.
Hallucinations. Parce qu'il produit le texte le plus plausible, un LLM peut affirmer avec aplomb une information fausse : une fonction d'API qui n'existe pas, une référence inventée, un chiffre erroné. La parade n'est pas de s'en méfier en bloc, mais de vérifier : tests, documentation officielle, relecture.
L'IA aujourd'hui : un bouleversement du marché
L'arrivée des assistants conversationnels grand public a provoqué une adoption d'une rapidité inédite. En quelques mois, des millions de personnes ont intégré l'IA à leur travail quotidien, et les entreprises ont dû réagir sur plusieurs fronts à la fois.
Ce qui change concrètement
La productivité : rédaction, synthèse, analyse de documents et production de code sont accélérées, parfois de façon spectaculaire sur les tâches répétitives.
Les métiers : peu de métiers disparaissent du jour au lendemain, mais beaucoup se transforment. La valeur se déplace de l'exécution vers la conception, la vérification et la décision.
Les compétences recherchées : savoir formuler un besoin, évaluer un résultat, connaître les limites des outils et sécuriser leur usage devient aussi important que la maîtrise technique.
Le recrutement : les offres intègrent de plus en plus la maîtrise des outils d'IA, et les candidatures elles-mêmes sont souvent filtrées et analysées automatiquement.
La réglementation : en Europe, l'AI Act encadre progressivement les usages selon leur niveau de risque, en complément du RGPD pour les données personnelles.
Une formule résume bien la situation : l'IA ne remplacera pas un professionnel, mais un professionnel qui maîtrise l'IA remplacera probablement celui qui l'ignore.
L'IA, assistant du quotidien
Avant même de parler de code, l'IA générative est d'abord un assistant polyvalent. Bien utilisée, elle fait gagner un temps considérable sur des tâches que chacun rencontre.
Usage | Exemple de demande | Point de vigilance |
|---|---|---|
Rédiger | « Rédige un courriel de relance cordial pour une facture impayée. » | Relire le ton et les faits. |
Résumer | « Résume ce compte rendu de 12 pages en 5 points d’action. » | Vérifier qu’aucun point clé ne manque. |
Traduire | « Traduis ce paragraphe en anglais professionnel. » | Attention au vocabulaire métier. |
Expliquer | « Explique-moi le principe du RGPD comme à un débutant. » | Croiser avec une source officielle. |
Organiser | « Propose un plan de formation sur 4 semaines. » | Adapter au contexte réel. |
Analyser | « Quels sont les risques de ce contrat de prestation ? » | Ne remplace pas un juriste. |
Analogie : l'assistant IA est un collaborateur très rapide, cultivé et disponible à toute heure, mais qui vient d'arriver dans l'entreprise. Il ne connaît ni votre contexte, ni vos clients, ni vos règles internes — sauf si vous les lui expliquez.
Règle d'or : ne jamais coller dans un assistant grand public des données personnelles, des secrets (mots de passe, clés d'API) ou des informations confidentielles de l'entreprise, sauf si l'outil est validé pour cet usage par votre organisation.
De l'assistant à l'agent : l'IA dans l'IT et le SI
Dans le développement logiciel, l'IA a suivi une progression en trois temps, chacun donnant un peu plus d'autonomie à la machine.
Chatbot | Copilote (autocomplétion) | Agent de codage | |
|---|---|---|---|
Rôle | Répond à des questions | Suggère la suite du code dans l’éditeur | Réalise une tâche de bout en bout |
Contexte | Ce que vous collez | Le fichier ouvert | Le projet entier, les outils, le terminal |
Actions | Aucune | Insère du texte | Lit, écrit, exécute, teste, corrige |
Autonomie | Nulle | Faible | Élevée, encadrée par des permissions |
Analogie | Un manuel qui répond | Un voisin de bureau qui souffle | Un développeur junior à qui l’on délègue |
L'agent de codage s'insère dans tout le cycle de vie du logiciel : compréhension d'un code existant, conception, implémentation, tests, documentation, revue de code, migration, et même exploitation (analyse de logs, scripts d'automatisation). Dans un SI, il devient un levier pour moderniser des applications historiques, documenter un patrimoine applicatif ou industrialiser les tâches répétitives.
Qu'est-ce qu'un agent IA ?
Définition
Un agent IA est un système qui combine un modèle de langage avec la capacité d'agir sur son environnement grâce à des outils, et qui enchaîne ces actions en boucle jusqu'à atteindre un objectif. Là où un assistant répond une fois, l'agent observe, décide, agit, vérifie, puis recommence.
Analogie : l'assistant est un conseiller qui vous dit quoi faire. L'agent est un artisan qui prend les outils, fait le travail, contrôle le résultat et vous rend compte.
Les composants d’un agent
La boucle agentique
Le cœur d'un agent est une boucle simple. Prenons une demande concrète : « Le test d'inscription échoue, corrige-le. »
À retenir : la valeur d'un agent ne vient pas seulement du modèle, mais de sa capacité à vérifier lui-même son travail (tests, compilation, lint). Un agent qui peut lancer les tests corrige ses propres erreurs.
Agent, sous-agent, skill, MCP, hooks et commandes
Autour de l'agent principal gravite un écosystème de briques aux rôles bien distincts. Pour les comprendre, imaginons une entreprise :
Brique | Analogie | Rôle | Quand l’utiliser |
|---|---|---|---|
Agent | Le chef de projet | Comprend l’objectif, planifie, agit et coordonne. | Toujours : c’est votre interlocuteur principal. |
Sous-agent | Un expert à qui l’on délègue un dossier | Agent spécialisé, avec son propre contexte, ses outils et ses instructions ; il rend un résultat synthétique. | Tâche ciblée et volumineuse : revue de sécurité, exploration d’un gros code, rédaction de tests. |
Skill | Une fiche de procédure | Savoir-faire packagé (instructions, scripts, modèles) chargé seulement quand il est utile. | Procédure récurrente : générer un rapport, respecter une charte, déployer. |
MCP | La prise USB-C universelle | Protocole standard pour connecter l’agent à des outils et données externes. | Accéder à Jira, GitLab, une base de données, une documentation, un navigateur. |
Hook | Le contrôle automatique à l’entrée du bâtiment | Script déclenché automatiquement à un moment précis (avant ou après une action). | Formater après chaque modification, bloquer une commande dangereuse. |
Commande | Un raccourci de bureau | Instruction préenregistrée lancée par | Actions répétées : revue de code, création de composant, rédaction de commit. |
Sous-agent ou skill : la différence clé
La confusion est fréquente. Un sous-agent est un quelqu'un : il travaille dans un contexte séparé, ce qui évite d'encombrer la conversation principale, puis rend un résumé. Une skill est un savoir-faire : elle ne travaille pas seule, elle enrichit l'agent qui la charge, au moment où il en a besoin.
Exemple de sous-agent, défini dans un simple fichier Markdown :
---
name: security-reviewer
description: Analyse les changements pour détecter des failles de sécurité (OWASP). À utiliser après toute modification touchant l'authentification ou les données.
tools: Read, Grep, Glob
---
Tu es un expert en sécurité applicative. Pour chaque changement :
1. Repère les injections, les fuites de données et les contrôles d'accès manquants.
2. Classe chaque problème par gravité (critique, élevée, moyenne).
3. Propose un correctif précis, sans modifier toi-même les fichiers.Et une skill, rangée dans un dossier avec ses ressources :
---
name: release-notes
description: Rédige les notes de version à partir des commits conventionnels. À utiliser lors de la préparation d'une release.
---
1. Liste les commits depuis le dernier tag (git log).
2. Regroupe-les par type : feat, fix, perf, docs.
3. Rédige des notes claires, orientées utilisateur, en français.MCP : la prise universelle
Le Model Context Protocol (MCP) est un standard ouvert qui permet à n'importe quel agent compatible de se connecter à n'importe quel outil compatible. Sans lui, chaque agent devrait développer une intégration spécifique pour chaque outil ; avec lui, un connecteur écrit une fois sert partout — exactement comme un câble USB-C qui recharge indifféremment téléphone, ordinateur ou casque.
{
"mcpServers": {
"gitlab": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-gitlab"],
"env": { "GITLAB_PERSONAL_ACCESS_TOKEN": "${GITLAB_TOKEN}" }
}
}
}Un serveur MCP est du code tiers qui accède à vos outils et à vos données. N'installez que des serveurs de confiance, avec des jetons aux droits minimaux, et ne versionnez jamais un jeton en clair : passez par des variables d'environnement.
Choisir son agent IA
Il existe aujourd'hui plusieurs familles d'outils : des assistants intégrés à l'éditeur (extensions d'IDE), des agents en ligne de commande qui travaillent dans le terminal, et des agents dans le cloud qui traitent des tâches en arrière-plan sur un dépôt. Le bon choix dépend moins de l'effet de mode que de critères objectifs.
Critère | Questions à se poser |
|---|---|
Qualité du modèle | Raisonne-t-il bien sur un code complexe ? Respecte-t-il les consignes ? Comment se comporte-t-il sur vos langages ? |
Intégration | Fonctionne-t-il dans votre IDE, votre terminal, votre CI/CD ? Supporte-t-il MCP ? |
Contexte | Comprend-il un projet entier ? Gère-t-il une mémoire de projet ? |
Contrôle | Les permissions sont-elles fines ? Peut-on relire chaque modification avant application ? |
Confidentialité | Où sont traitées les données ? Sont-elles utilisées pour l’entraînement ? Quelles garanties contractuelles ? |
Extensibilité | Sous-agents, skills, hooks, commandes personnalisées ? |
Coût | Abonnement ou paiement à l’usage ? Le coût est-il prévisible pour l’équipe ? |
Conformité | Compatible avec la politique de sécurité de l’entreprise, le RGPD, l’AI Act ? |
Conseil : évaluez deux ou trois outils sur une même tâche réelle de votre projet (corriger un bug, ajouter une fonctionnalité testée), plutôt que sur des démonstrations. Mesurez le résultat, le temps de relecture nécessaire et la qualité des tests produits.
Le développement piloté par l'IA
Travailler avec un agent ne consiste pas à lui dire « fais l'application ». Les équipes qui obtiennent les meilleurs résultats suivent un cycle discipliné, où l'humain garde la main sur les décisions.
Exemple concret : ajouter un filtre sur une liste
Explorer : « Lis le module des commandes et explique-moi comment la liste est chargée. Ne modifie rien. »
Planifier : « Propose un plan pour ajouter un filtre par statut côté serveur, avec les fichiers touchés et les tests prévus. » — vous relisez et ajustez le plan.
Implémenter : « Applique l'étape 1 du plan et écris d'abord les tests. »
Vérifier : l'agent lance les tests, corrige jusqu'au vert.
Relire : vous lisez le diff comme celui d'un collègue.
Committer : « Crée un commit au format Conventional Commits. »
Le TDD est le meilleur allié de l'agent. Des tests écrits en premier donnent à l'agent un objectif vérifiable : il sait objectivement quand il a terminé, et vous savez que le résultat fonctionne.
Le prompt engineering : bien formuler sa demande
Le prompt engineering est l'art de formuler une demande pour obtenir le meilleur résultat d'un modèle. Avec un agent, l'enjeu est encore plus fort : un prompt flou produit un travail flou, sur de nombreux fichiers.
Analogie : un prompt, c'est le brief donné à un prestataire. Un bon prestataire avec un mauvais brief livre quelque chose de bien fait… mais qui ne correspond pas à votre besoin.
L’anatomie d’un bon prompt
Mauvais prompt, bon prompt
Un prompt vague laisse l’agent deviner :
Ajoute une pagination à la liste des utilisateurs.Un bon prompt cadre le travail :
Contexte : application Next.js, module src/features/users.
La liste des utilisateurs charge tous les enregistrements, ce qui ralentit la page.
Objectif : ajouter une pagination côté serveur (20 éléments par page).
Contraintes :
- respecter l'architecture existante (repository > service > action) ;
- ne pas modifier le schéma de base de données ;
- aucune nouvelle dépendance.
Critères de réussite :
- tests unitaires du service pour la première, une page intermédiaire et la dernière page ;
- tous les tests et le lint passent.
Commence par me proposer un plan, sans modifier de fichier.Le scope : une tâche à la fois
Le périmètre (scope) est le premier facteur de réussite. Une demande qui mélange refonte, nouvelle fonctionnalité et correction de bugs donne un résultat difficile à relire et à tester. Découpez : une demande = un objectif vérifiable, idéalement un commit.
Où rédiger son prompt ?
Emplacement | Pour quoi | Durée de vie |
|---|---|---|
La conversation | La demande du moment | La session |
Le fichier | Les règles permanentes du projet (conventions, commandes, architecture) | Tant que le projet existe |
Un ticket ou une spécification | Une fonctionnalité détaillée, partagée avec l’équipe | Le temps du développement |
Une commande personnalisée | Une demande répétée à l’identique | Réutilisable à volonté |
Techniques qui font la différence
Demander un plan d'abord, et le valider avant toute modification.
Donner un exemple du résultat attendu (le style d'un test existant, un composant de référence).
Pointer les fichiers concernés plutôt que de laisser l'agent les chercher.
Inviter l'agent à poser des questions lorsqu'une information manque.
Exiger une vérification : « lance les tests et montre-moi le résultat ».
Corriger tôt : interrompre dès qu'une direction ne convient pas, plutôt que de laisser l'agent s'enfoncer.
La mémoire de l'IA : pourquoi et comment mémoriser
Un LLM n'a aucune mémoire entre deux conversations. Chaque nouvelle session repart de zéro. Sans mémoire, il faudrait réexpliquer à chaque fois les conventions du projet, les commandes de test, les décisions d'architecture…
Analogie : la fenêtre de contexte est la mémoire de travail — ce que l'on garde en tête pendant une réunion. La mémoire persistante est le carnet de bord que l'on relit en arrivant le matin.
Que mémoriser ?
Les commandes : comment lancer les tests, le build, le lint.
Les conventions : architecture, nommage, style de code, format des commits.
Les décisions : choix techniques et leurs raisons (« on n'utilise pas d'ORM ici parce que… »).
Les pièges : ce qui a déjà posé problème et la bonne façon de faire.
Exemple de fichier CLAUDE.md concis et efficace :
# Projet Portfolio — règles pour l'agent
## Commandes
- Installer : bun install
- Tests : bun run test (couverture minimale 95 %)
- Vérifications : bun run lint && bun run typecheck
## Architecture
- Feature First : chaque fonctionnalité dans src/features/<nom>/
- Mutations uniquement via Server Actions, validées avec Zod
## Règles
- Jamais de push sur main : une branche et une merge request
- Commits en anglais, format Conventional Commits
- Ne jamais lire ni modifier les fichiers .envUn bon fichier de mémoire est court, factuel et à jour. Mieux vaut dix règles précises que cent lignes générales : tout ce qui est en mémoire occupe de la place dans le contexte à chaque session.
Les commandes utiles : le cas de Claude Code
Dans Claude Code, les commandes commençant par / pilotent la session elle-même. Voici les plus utiles au quotidien (la liste complète est accessible avec /help) :
Commande | À quoi elle sert | Quand l’utiliser |
|---|---|---|
| Analyse le projet et génère un premier | À la première ouverture d’un projet. |
| Ouvre et modifie les fichiers de mémoire. | Pour ajouter une règle ou une décision. |
| Vide le contexte de la conversation. | En changeant de tâche, pour repartir proprement. |
| Résume la conversation pour libérer du contexte. | Lors d’une longue session sur la même tâche. |
| Change de modèle. | Modèle plus puissant pour une tâche complexe. |
| Consulte et règle les autorisations. | Pour autoriser une commande sûre ou en interdire une. |
| Crée et gère les sous-agents. | Pour déléguer une spécialité. |
| Affiche les serveurs MCP connectés. | Pour vérifier une connexion à un outil externe. |
| Configure les hooks. | Pour automatiser un contrôle. |
| Reprend une conversation précédente. | Pour continuer une tâche interrompue. |
| Ouvre les réglages. | Pour personnaliser l’outil. |
| Liste toutes les commandes disponibles. | En cas de doute. |
Raccourcis et commandes personnalisées
@suivi d’un chemin : référence un fichier précis dans la demande.!en début de ligne : exécute directement une commande shell.Échap: interrompt l’agent pour le recadrer.Maj + Tab: bascule entre les modes (dont le mode plan, où l’agent propose sans modifier).
Une commande personnalisée est un simple fichier Markdown placé dans .claude/commands/. Le fichier .claude/commands/review.md devient la commande /review :
Relis les changements non commités de la branche courante.
Pour chaque fichier modifié, vérifie :
- le respect de l'architecture et des conventions du CLAUDE.md ;
- la présence de tests pour toute nouvelle logique ;
- l'absence de secret ou de donnée personnelle en clair.
Rends une liste de remarques classées par priorité.Le dossier .claude : local, utilisateur, organisation
La configuration d'un agent se répartit sur plusieurs niveaux, du plus personnel au plus collectif. Chez Claude Code, elle vit principalement dans des dossiers nommés .claude.
Analogie : le dossier
.claudedu projet est le classeur d'accueil remis à chaque nouvel arrivant : règles de la maison, procédures, contacts utiles. Le dossier utilisateur est votre trousse personnelle, qui vous suit de projet en projet.
mon-projet/
├── CLAUDE.md # mémoire du projet, partagée (versionnée)
├── .mcp.json # serveurs MCP du projet (versionné, sans secret)
└── .claude/
├── settings.json # permissions et hooks partagés (versionné)
├── settings.local.json # réglages personnels (non versionné)
├── commands/ # commandes personnalisées : /review, /release…
├── agents/ # sous-agents du projet
└── skills/ # skills du projet
~/.claude/ # niveau utilisateur, propre à votre machine
├── CLAUDE.md # préférences personnelles, tous projets confondus
├── settings.json # réglages personnels globaux
├── commands/ # vos commandes personnelles
└── agents/ # vos sous-agents personnelsNiveau | Portée | Exemples de contenu | Versionné ? |
|---|---|---|---|
Organisation (réglages gérés) | Tous les postes de l’entreprise | Interdictions globales, serveurs MCP autorisés | Géré par l’IT |
Projet partagé ( | Toute l’équipe sur ce projet | Conventions, commandes de test, permissions communes, sous-agents | Oui |
Projet personnel ( | Vous, sur ce projet | Autorisations propres à votre poste | Non |
Utilisateur ( | Vous, sur tous vos projets | Langue préférée, style de réponse, outils favoris | Non |
Ce qui est versionné est partagé avec toute l'équipe — et parfois au-delà. Aucun secret dans CLAUDE.md, settings.json ou .mcp.json : utilisez des variables d'environnement et gardez les fichiers .env hors du dépôt.
Permissions et sécurité des données
Un agent qui peut lire des fichiers et exécuter des commandes dispose d'un vrai pouvoir sur votre poste et votre code. La question n'est donc pas « faut-il tout autoriser ? » — la réponse est clairement non — mais « comment n'autoriser que le nécessaire, au bon moment ».
Analogie : on ne donne pas à un prestataire le passe-partout de tout l'immeuble. On lui remet un badge qui ouvre les pièces dont il a besoin, pour la durée de sa mission.
Le principe du moindre privilège
Concrètement, on autorise d'office les actions sûres et fréquentes (lancer les tests, lire le code), on interdit explicitement ce qui touche aux secrets ou à des opérations irréversibles, et on laisse tout le reste soumis à confirmation.
{
"permissions": {
"allow": [
"Bash(bun run test:*)",
"Bash(bun run lint)",
"Bash(git status)",
"Bash(git diff:*)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(git push --force:*)",
"Bash(rm -rf:*)"
]
}
}Les données personnelles et sensibles
Minimiser : ne donner à l'agent que les données nécessaires à la tâche. Des données de test fictives valent mieux qu'un extrait de production.
Isoler les secrets : fichiers
.envinterdits en lecture, jetons à droits limités, rotation régulière.Respecter le RGPD : pas de données personnelles réelles (clients, salariés, patients) dans les échanges sans base légale et sans outil validé par l'entreprise.
Se méfier des contenus externes : une page web, un ticket ou un fichier peut contenir des instructions malveillantes (« injection de prompt »). Un agent prudent traite ces contenus comme des données, jamais comme des ordres.
Garder la trace : relire les diffs, travailler sur des branches, conserver l'historique Git pour pouvoir revenir en arrière.
Approche | Avantage | Risque | Verdict |
|---|---|---|---|
Tout autoriser | Aucune interruption | Fuite de secrets, commandes destructrices, actions non voulues | ❌ À proscrire |
Tout confirmer | Contrôle total | Fatigue : on finit par tout valider sans lire | ⚠️ Contre-productif |
Autorisations ciblées et progressives | Fluidité sur le sûr, contrôle sur le sensible | Demande un peu de configuration | ✅ Recommandé |
Les bonnes pratiques du codage piloté par un agent
Une checklist à garder sous la main, pour chaque tâche confiée à un agent :
La tâche est découpée en un objectif clair et vérifiable.
L’agent travaille sur une branche dédiée, jamais directement sur la branche principale.
Un plan a été proposé et validé avant les modifications.
Des tests décrivent le comportement attendu, idéalement écrits en premier.
Les tests, le lint et le build passent avant de considérer la tâche terminée.
Le diff a été relu par un humain, comme celui d’un collègue.
Aucun secret ni aucune donnée personnelle n’apparaît dans le code ou les commits.
Le fichier CLAUDE.md a été mis à jour si une nouvelle règle a émergé.
Le commit est atomique, avec un message explicite.
Les pièges les plus courants
La confiance aveugle : accepter un code qui « a l'air juste » sans le tester.
Les demandes géantes : un seul prompt pour toute une fonctionnalité, impossible à relire.
Le contexte pollué : une session trop longue qui mélange plusieurs sujets ; mieux vaut
/clearentre deux tâches.La dette invisible : du code généré qui fonctionne mais que personne dans l'équipe ne comprend.
La perte de compétences : déléguer sans comprendre. L'agent doit rester un accélérateur, pas une béquille.
La règle qui résume tout : l'agent propose, l'humain dispose. Vous restez responsable de chaque ligne qui part en production.
Atelier pratique : LinkLite, un mini-projet de A à Z avec Claude Code
La théorie ne suffit pas : pour maîtriser un agent de codage, il faut l'avoir vu travailler sur un vrai projet, avec ses réussites, ses erreurs et ses garde-fous. Cette partie déroule un mini-projet complet, réalisé avec Claude Code : du choix du sujet jusqu'à une version 1.0.0 taguée, testée, auditée et prête à être déployée. Chaque étape reprend une notion vue plus haut — prompt, mémoire, sous-agent, skill, MCP, permissions — et la met en œuvre.
Ce que vous allez construire : LinkLite, un raccourcisseur d'URL. On y dépose une adresse longue, on repart avec un lien court (« ticket ») et un compteur de clics.
Ce que vous allez pratiquer : prompt engineering, mémoire projet (CLAUDE.md), permissions, MCP Context7, skill frontend-design, agents et skills sur mesure, TDD, tests d'intégration et de bout en bout, PostgreSQL, Docker, Git et livraison.
Pourquoi ce sujet ?
Un bon sujet d'atelier est petit mais complet : il doit toucher toutes les couches d'une application réelle sans noyer le lecteur. Le raccourcisseur d'URL coche toutes les cases :
Un domaine métier clair : des règles simples à formuler et à tester (format d'un slug, URL autorisée ou non).
Une vraie base de données : unicité, contraintes, et un compteur de clics qui doit rester exact même avec des accès simultanés.
Une API et une interface : de quoi pratiquer le design et les tests de bout en bout.
De vrais enjeux de sécurité : un raccourcisseur peut servir à masquer une adresse interne (SSRF) ou à du spam — idéal pour mettre un agent d'audit à l'épreuve.
Le périmètre : ce qui est dedans, ce qui est dehors
Fixer le périmètre avant de coder est la meilleure protection contre la dérive — la nôtre comme celle de l'agent, qui a tendance à « enrichir » une demande floue. Le périmètre a été écrit noir sur blanc, puis repris dans le premier prompt :
Dans la v1.0.0 | Hors périmètre (volontairement) |
|---|---|
Raccourcir une URL | Comptes utilisateurs et authentification |
Slug aléatoire ou personnalisé ( | Expiration des liens, QR codes |
Redirection 302 et compteur de clics exact | Statistiques détaillées (pays, navigateur…) |
Liste des 20 derniers liens | Prévisualisation de la page cible |
Thème clair/sombre, responsive, accessible | Interface d’administration |
Sécurité : anti-SSRF, limitation de débit, CSP | Déploiement cloud (la v1 est « prête à déployer ») |
Les choix techniques et leurs raisons
Chaque choix est justifié par le besoin, pas par la mode. C'est aussi ce que l'on demande à l'agent : argumenter plutôt que d'empiler des dépendances.
Besoin | Choix | Pourquoi |
|---|---|---|
Langage | TypeScript (strict) sur Node.js 22 | Typage fort : l’agent et le compilateur se corrigent mutuellement. |
Serveur HTTP | Fastify 5 | Léger, rapide, validation des entrées par schéma JSON intégrée. |
Base de données | PostgreSQL 18 (SQL) | Contraintes déclaratives, transactions, mises à jour atomiques — exactement ce qu’exige un compteur fiable. |
Accès aux données | Driver | Trois requêtes : un ORM serait plus lourd que le problème (KISS). |
Tests | Vitest + Playwright | Tests unitaires/intégration rapides ; parcours réels dans un vrai navigateur. |
Interface | HTML/CSS/JS sans framework | Une page, aucun build front : le skill frontend-design se charge de l’esthétique. |
Livraison | Docker + docker compose | Même environnement partout, base comprise. |
L'architecture : hexagonale, en version légère
Le code est organisé en couches dont les dépendances pointent toutes vers le centre. Le domaine (les règles métier) ne connaît ni Fastify ni PostgreSQL : il décrit ce dont il a besoin sous la forme d'une interface — un port — que l'infrastructure implémente via des adaptateurs. Résultat : on peut tester tout le métier sans base de données, et changer de base sans toucher au métier.
// src/domain/link.ts — le port : ce dont le métier a besoin, sans dire comment
export interface LinkRepository {
/** Inserts the link; returns false when the slug already exists. */
insert(link: Link): Promise<boolean>
findBySlug(slug: string): Promise<Link | null>
/** Atomically increments the click counter; returns the target or null if unknown. */
registerClick(slug: string): Promise<string | null>
listRecent(limit: number): Promise<Link[]>
}Préparer le terrain : mémoire, permissions et MCP Context7
Avant la première ligne de code, on donne à l'agent ce qu'un nouveau collègue recevrait le premier jour : les règles de la maison, les accès autorisés et une documentation à jour. Tout est versionné dans le dépôt, donc partagé par toute l'équipe.
Fichier | Rôle | Notion de l’article |
|---|---|---|
| Commandes, architecture, règles de code, Git, sécurité | Mémoire projet |
| Commandes autorisées, lectures et actions interdites | Permissions |
| Serveur MCP Context7 | MCP |
| Sous-agents | Sous-agents |
| Savoir-faire de livraison (notes, CHANGELOG, tag) | Skills |
| Commande | Commandes personnalisées |

Les permissions : autoriser le sûr, interdire le dangereux
Le fichier settings.json évite deux écueils : valider cent fois la même commande inoffensive, et laisser passer une commande destructrice par lassitude. Les tests, le lint et la lecture de l'historique Git sont autorisés ; la lecture des secrets, la suppression récursive et le push sur main sont interdits.
{
"permissions": {
"allow": [
"Bash(npm test)", "Bash(npm run test:*)", "Bash(npm run check)",
"Bash(git status)", "Bash(git diff:*)", "Bash(git log:*)",
"mcp__context7__resolve-library-id", "mcp__context7__query-docs"
],
"deny": [
"Read(./.env)", "Read(./.env.*)", "Read(./node_modules/**)", "Read(./coverage/**)",
"Bash(git push --force:*)", "Bash(git push origin main:*)",
"Bash(rm -rf:*)", "Bash(docker compose down -v:*)"
]
}
}Vécu pendant l'atelier : l'agent a voulu supprimer d'anciennes captures avec rm -f docs/screenshots/*. Le garde-fou de Claude Code a bloqué la suppression par motif et l'agent a contourné proprement le besoin (les fichiers étaient de toute façon réécrits). C'est exactement le rôle des permissions : rendre l'erreur coûteuse impossible.
Context7 : une documentation à jour, directement dans le contexte
Un modèle de langage a une date de coupure : il connaît les bibliothèques telles qu'elles étaient lors de son entraînement. Or les API évoluent vite — une option renommée, un comportement par défaut modifié, une version majeure qui casse tout. Résultat classique : du code plausible… qui ne compile pas, ou pire, qui compile mais se comporte mal.
Context7 est un serveur MCP qui résout ce problème : il indexe la documentation officielle et les exemples de milliers de bibliothèques, version par version, et les sert à l'agent à la demande. Au lieu de « se souvenir », l'agent consulte.
Installer Context7
Deux façons équivalentes, au niveau du projet (recommandé, car partagé avec l'équipe) :
# Option 1 — en ligne de commande, portée projet (écrit .mcp.json)
claude mcp add --transport http --scope project context7 https://mcp.context7.com/mcp
# Vérifier la connexion depuis une session Claude Code
/mcp// Option 2 — directement dans .mcp.json, à la racine du dépôt
{
"mcpServers": {
"context7": { "type": "http", "url": "https://mcp.context7.com/mcp" }
}
}Context7 expose deux outils : resolve-library-id (trouver l'identifiant d'une bibliothèque, par exemple /fastify/fastify) et query-docs (poser une question ciblée sur cette bibliothèque). Une clé d'API gratuite permet d'augmenter les quotas, mais n'est pas nécessaire pour démarrer.
Comment s’en servir au quotidien
Le réflexe : ajouter « use context7 » à la fin d'un prompt qui touche une bibliothèque. On peut aussi l'inscrire dans
CLAUDE.mdpour que ce soit systématique.Des questions précises : « options de
webServerdansplaywright.config» consomme bien moins de tokens que « documentation de Playwright ».Les outils pré-autorisés : les deux outils Context7 sont dans la liste
allowdusettings.json, ils ne demandent donc pas de confirmation.
Ce que Context7 a réellement changé dans LinkLite
Bibliothèque | Question posée | Ce que la doc à jour a évité |
|---|---|---|
Vitest 4 | Configuration de la couverture v8 et des seuils | Une configuration écrite pour l’API de la version installée (v4), et non d’une version antérieure. |
Playwright |
| Un serveur de test lancé à la main : Playwright démarre et attend lui-même l’application. |
@fastify/rate-limit | Limite par route, gestion de la réponse 429 | Un 429 transformé en 500 par le gestionnaire d’erreurs global : la doc le signalait, un test le verrouille. |
Fastify 5 |
| Le cas le plus parlant : la confiance par « nombre de sauts » ne fonctionne plus (elle échoue désormais en mode fermé pour empêcher l’usurpation d’IP). Le code « de mémoire » aurait été faux. |
Context7 ne remplace pas les tests. La documentation dit ce qui devrait marcher ; seuls les tests prouvent ce qui marche. Dans LinkLite, chaque information issue de Context7 a été verrouillée par un test.
Les prompts de l’atelier : du cadrage à la livraison
Un projet entier ne se pilote pas avec un seul prompt géant, mais avec une suite de demandes courtes et vérifiables, chacune terminée par un critère d'acceptation. Toutes suivent le même gabarit :
CONTEXTE : où l'on en est, fichiers concernés (@src/domain/...)
OBJECTIF : un seul résultat observable
CONTRAINTES : règles du CLAUDE.md, ce qu'il ne faut PAS faire
VÉRIFICATION: la commande qui prouve que c'est fini (tests, lint, capture)
FORMAT : plan d'abord / diff / tableau…La séquence complète
Étape | Prompt (résumé) | Mode |
|---|---|---|
1. Cadrage | « Voici le sujet et le périmètre. Propose l’architecture et la liste des fichiers, sans coder. » | Plan |
2. Socle | « Initialise le projet : TypeScript strict, Vitest, ESLint, Prettier, CLAUDE.md et settings.json. » | Édition |
3. Domaine (rouge) | « Avec l’agent test-writer, écris les tests de validation d’URL et de slug. Ils doivent échouer. » | Sous-agent |
4. Domaine (vert) | « Implémente le minimum pour faire passer ces tests, sans les modifier. » | Édition |
5. Cas d’usage | « Crée LinkService derrière le port LinkRepository ; adaptateur en mémoire pour les tests. » | Édition |
6. API + base | « Ajoute l’API Fastify et l’adaptateur PostgreSQL. use context7 » | Édition + MCP |
7. Interface | « /frontend-design Une page unique pour LinkLite… (voir plus bas) » | Skill |
8. Bout en bout | « Écris les parcours Playwright bureau et mobile, avec captures. use context7 » | Édition + MCP |
9. Conteneurs | « Dockerfile multi-étapes non root, .dockerignore, compose avec PostgreSQL. » | Édition |
10. Audit | « Lance l’agent security-auditor sur toute l’application. » | Sous-agent |
11. Correctifs | « Corrige chaque constat Élevé et Moyen en TDD, puis relance l’audit. » | Édition + sous-agent |
12. Livraison | « Prépare la v1.0.0 avec le skill release-notes. » | Skill |
Exemple : le prompt de l’étape 4
Contexte : les tests de tests/unit/target-url.test.ts échouent (étape rouge).
Objectif : implémente parseTargetUrl dans src/domain/target-url.ts.
Contraintes :
- ne modifie PAS les tests ;
- aucune dépendance externe : uniquement node:net et l'API URL ;
- respecte l'architecture du CLAUDE.md (le domaine n'importe rien d'autre).
Vérification : npm test doit passer, puis npm run check.
Format : montre-moi le diff, puis la sortie des tests.Pourquoi « ne modifie pas les tests » ? Face à un test rouge, un agent peut être tenté d'ajuster le test plutôt que le code. Le dire explicitement ferme cette porte : le test est la spécification.
TDD avec un agent : rouge, vert, refactor
Le développement piloté par les tests est le meilleur allié d'un agent : il transforme une intention floue en critère objectif. L'agent n'a plus à deviner ce que « correct » veut dire — il le lit dans les tests, et il sait quand il a fini.
La pyramide des tests de LinkLite
Niveau | Outil | Ce qui est testé | Volume |
|---|---|---|---|
Unitaire | Vitest | Domaine et cas d’usage, sans base ni réseau (adaptateur en mémoire) | ≈ 60 tests, quelques millisecondes |
Intégration | Vitest + vrai PostgreSQL | SQL, contraintes, 20 clics simultanés, injection SQL, migrations ; API via | ≈ 25 tests |
Bout en bout | Playwright | Parcours réels dans Chrome, bureau et mobile | 10 parcours |

La couverture comme garde-fou
La couverture ne prouve pas que le code est juste, mais elle révèle ce qui n'a jamais été exécuté. Le seuil est bloquant : en dessous de 90 %, la commande échoue — en local comme en intégration continue.
// vitest.config.ts
coverage: {
provider: 'v8',
include: ['src'],
exclude: ['src/server.ts', 'src/infrastructure/migrate-cli.ts'], // points d'entrée
thresholds: { lines: 90, functions: 90, branches: 90, statements: 90 },
},
Un vrai bug, attrapé grâce à la démarche
Première ouverture de l'interface dans le navigateur : la page s'affiche… sans aucun style. Le diagnostic est rapide : la route GET /:slug, censée rediriger un lien court, capturait aussi /styles.css et /app.js, qu'elle prenait pour des slugs inconnus.

La correction a suivi le cycle TDD, à l'échelle d'un bug :
Rouge — un test d'intégration exige que
/assets/styles.cssréponde200entext/css: il échoue (302).Vert — les fichiers statiques sont servis sous le préfixe
/assets/, qui est déjà un slug réservé par le domaine : aucune collision possible.Garde-fou — le test reste dans la suite : ce bug ne peut plus revenir sans faire échouer l'intégration continue.
it.each([
['/assets/styles.css', /text\/css/],
['/assets/app.js', /javascript/],
])('sert la ressource statique %s sans la confondre avec un slug', async (url, type) => {
const res = await app.inject({ method: 'GET', url })
expect(res.statusCode).toBe(200)
expect(res.headers['content-type']).toMatch(type)
})Concevoir l'interface avec le skill frontend-design
Laissé à lui-même, un modèle produit des interfaces « moyennes » : la même police, le même dégradé violet, les mêmes cartes arrondies. C'est logique — il reproduit la moyenne de ce qu'il a vu. Le skill frontend-design, publié par Anthropic, corrige ce biais : il oblige l'agent à choisir une direction artistique assumée avant d'écrire la moindre ligne de CSS.
Ce que contient le skill
Une phase de réflexion imposée : à qui s'adresse l'interface, quel ton (brutaliste, éditorial, rétro, luxueux…), quelle contrainte technique, et surtout quel détail la rendra mémorable.
Des consignes précises : typographie distinctive (pas d'Inter ni d'Arial), palette dominante avec un accent franc, animations ciblées, textures et profondeur plutôt qu'aplats.
Des interdits explicites : les esthétiques génériques « générées par IA ».
L'installer et l'invoquer
Un skill est un simple dossier contenant un SKILL.md. Celui-ci est disponible dans le dépôt public de skills d'Anthropic ; on le copie soit au niveau utilisateur (tous les projets), soit au niveau projet (partagé avec l'équipe) :
~/.claude/skills/frontend-design/SKILL.md # portée utilisateur
.claude/skills/frontend-design/SKILL.md # portée projet (versionné)Claude Code charge alors seulement sa description au démarrage ; le contenu complet n'entre dans le contexte que lorsque le skill est utilisé — automatiquement si la demande porte sur une interface, ou explicitement avec /frontend-design.
Le prompt utilisé pour LinkLite
/frontend-design Interface d'une seule page pour LinkLite, un raccourcisseur d'URL :
formulaire (URL + slug personnalisé optionnel), résultat avec bouton copier,
liste des 20 derniers liens avec compteur de clics, message si un lien est
introuvable (?missing=slug). HTML/CSS/JS vanilla sans framework, servi par
Fastify, CSP stricte (pas de script inline, styles Google Fonts autorisés),
accessible, responsive, mode clair et sombre.Remarquez que le prompt décrit le besoin et les contraintes, pas le style : c'est le skill qui conduit l'agent à proposer une direction. Il a retenu le concept de « consigne à liens » : on dépose une URL comme un bagage et l'on repart avec un ticket — papier kraft, encre, orange signalétique, tickets perforés et compteur de clics apposé comme un tampon.
Décision de design | Mise en œuvre |
|---|---|
Typographies de caractère | Bricolage Grotesque pour les titres, IBM Plex Mono pour le texte (registre « ticket imprimé »). |
Matière | Fond kraft ligné, grain de papier en SVG, ombres franches décalées. |
Mouvement | Apparition en cascade du registre ; le nouveau ticket « tombe » ; respect de |
Thème sombre | Variables CSS redéfinies sous |
Sécurité | Aucun |




Les tests de bout en bout produisent aussi la démo
Les parcours Playwright tournent sur la vraie pile (Fastify + PostgreSQL), en version bureau et mobile. Avec SCREENSHOTS=1, ils enregistrent au passage les captures de la documentation : la démo ne peut donc jamais être en retard sur le code.
test('refuse une adresse interne (protection SSRF)', async ({ page }) => {
await page.goto('/')
await page.getByLabel('URL à raccourcir').fill('http://169.254.169.254/latest/meta-data')
await page.getByRole('button', { name: 'Raccourcir' }).click()
await expect(page.getByRole('alert')).toContainText('adresses internes sont interdites')
await expect(page.locator('#result')).toBeHidden()
await capture(page, 'ssrf') // capture uniquement si SCREENSHOTS=1
})
Un test qui échoue n'accuse pas toujours le code. Le parcours « slug déjà pris » a d'abord échoué : il remplissait le formulaire une seconde fois avant que la première réponse ne le réinitialise. Le correctif était dans le test (attendre le premier ticket), pas dans l'application. Lire l'erreur avant de « corriger » reste un réflexe humain à exiger de l'agent.
Créer ses propres agents et skills
Les outils fournis sont un point de départ. La vraie productivité vient des agents et skills taillés pour votre projet : ils encapsulent un savoir-faire une fois pour toutes, et chaque membre de l'équipe en profite.
Un sous-agent d’audit de sécurité
Un sous-agent est un fichier Markdown avec un en-tête YAML : un nom, une description (qui dit quand l'utiliser), des outils autorisés et un modèle. Celui-ci est volontairement en lecture seule : un auditeur analyse, il ne corrige pas.
---
name: security-auditor
description: Audite le code de LinkLite pour détecter des failles de sécurité
(OWASP Top 10, SSRF, injection SQL, open redirect, secrets). À utiliser après
toute modification des routes HTTP, de la validation d'URL, de l'accès base de
données ou de la configuration Docker. Ne modifie jamais les fichiers.
tools: Read, Grep, Glob
model: sonnet
---
Tu es un auditeur de sécurité applicative senior. Tu analyses, tu ne corriges pas.
## Méthode
1. Liste les points d'entrée : routes Fastify, variables d'environnement, Dockerfile, compose.
2. Pour chaque point d'entrée, vérifie : injection SQL, validation des entrées,
open redirect / SSRF, XSS, secrets, conteneur.
3. Classe chaque constat : Critique, Élevé, Moyen, Faible.
## Format de réponse
Un tableau | Gravité | Fichier:ligne | Problème | Correctif proposé |, trié par gravité.
L'audit en conditions réelles
Lancé sur l'application « terminée » (62 tests verts, couverture à 97 %), l'auditeur a pourtant trouvé de quoi faire. Il a même vérifié ses hypothèses en exécutant le code plutôt que de spéculer :
Gravité | Constat | Correctif |
|---|---|---|
Élevé | Contournement du filtre par IPv6 : | Filtre réécrit avec |
Élevé | Un point final suffisait : | Normalisation du nom d’hôte avant vérification. |
Moyen | Plages réservées acceptées (CGNAT, dont l’adresse de métadonnées d’Alibaba Cloud). | Plages ajoutées et testées. |
Moyen | Noms sans domaine ( | Refus des noms à un seul label. |
Moyen | Aucune limitation de débit : spam de liens et gonflement des compteurs. |
|
Faible | Pas de limite de taille de requête, CSP incomplète, pool de connexions sans délai. | Corps limité à 4 Ko, |
Chaque constat a d'abord été transformé en test rouge (douze d'un coup pour les contournements), puis corrigé. Un second passage de l'auditeur a confirmé les correctifs et relevé quelques cas résiduels de gravité faible, corrigés à leur tour. Il a aussi détecté qu'une plage ajoutée bloquait par erreur… toutes les adresses IPv4 : c'est un test « accepte 8.8.8.8 » qui l'a révélé immédiatement.
Un skill de livraison, avec références et script
Un skill va plus loin qu'un prompt réutilisable : c'est un dossier qui peut embarquer des documents de référence et des scripts. L'agent ne lit les références qu'au moment où il en a besoin (c'est la « divulgation progressive ») et exécute les scripts sans les recopier dans son contexte.
.claude/skills/release-notes/
├── SKILL.md # quand l'utiliser + les étapes
├── references/
│ ├── commit-types.md # type de commit → section des notes
│ └── release-template.md # gabarit exact des notes de version
└── scripts/
└── collect-commits.sh # commits depuis le dernier tag, groupés par type
Une commande pour la revue
Enfin, une commande personnalisée /review (fichier .claude/commands/review.md) relit la branche courante par rapport à main : respect de l'architecture, principes SOLID et DRY, présence de tests, absence de secret. Elle se termine par « Prêt à fusionner » ou par la liste des points bloquants.
Économiser les tokens et tenir le périmètre
Chaque fichier lu, chaque sortie de commande, chaque page de documentation occupe la fenêtre de contexte. Un contexte encombré coûte plus cher, ralentit l'agent et dégrade la qualité de ses réponses : il « oublie » les consignes du début. Économiser les tokens, c'est donc aussi travailler mieux.
Technique | Mise en œuvre dans LinkLite | Effet |
|---|---|---|
Déléguer aux sous-agents | Les deux audits ont tourné dans un sous-agent (≈ 57 000 puis 69 000 tokens de travail) ; seul le tableau final est revenu. | Le contexte principal reste centré sur le code. |
Un modèle adapté à la tâche |
| Moins cher pour un travail cadré. |
Interdire les lectures inutiles |
| Pas de milliers de lignes lues par erreur. |
Skills à la demande | Seule la description est chargée ; le contenu, quand il sert. | Des savoir-faire riches sans coût permanent. |
Requêtes Context7 ciblées | Une question précise par bibliothèque. | Quelques extraits au lieu d’une documentation entière. |
Sorties filtrées |
| On lit le verdict, pas mille lignes de log. |
| Une page : commandes, architecture, règles. | Chargé à chaque session : chaque ligne compte. |
| Entre deux étapes indépendantes. | Repartir d’un contexte propre. |
Le périmètre est la première économie. Toutes les idées « en plus » (statistiques, QR codes, comptes) ont été notées dans la liste hors périmètre plutôt que codées. Une fonctionnalité non demandée coûte des tokens à écrire, à tester, à auditer… et à maintenir.
PostgreSQL et Docker : une application prête à déployer
Pourquoi PostgreSQL, et du SQL « à la main »
Les règles critiques sont inscrites dans la base elle-même : même si un bug passait la validation applicative, PostgreSQL refuserait une donnée invalide. Les migrations sont de simples fichiers SQL versionnés, appliqués dans une transaction et tracés dans une table schema_migrations.
-- db/migrations/001_create_links.sql
CREATE TABLE IF NOT EXISTS links (
slug VARCHAR(32) PRIMARY KEY CHECK (slug ~ '^[a-z0-9][a-z0-9-]{2,31}$'),
target_url VARCHAR(2048) NOT NULL,
clicks INTEGER NOT NULL DEFAULT 0 CHECK (clicks >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS links_created_at_idx ON links (created_at DESC);Le compteur de clics illustre l'intérêt du SQL : lire la valeur, ajouter 1, puis l'écrire perdrait des clics en cas d'accès simultanés. Une seule instruction atomique règle le problème — et un test d'intégration lance 20 clics en parallèle pour le prouver.
async registerClick(slug: string): Promise<string | null> {
// Single atomic statement: concurrent clicks are never lost
const { rows } = await this.pool.query<{ target_url: string }>(
'UPDATE links SET clicks = clicks + 1 WHERE slug = $1 RETURNING target_url',
[slug] // paramètre : jamais de concaténation, donc pas d'injection SQL
)
return rows[0]?.target_url ?? null
}Le Dockerfile : multi-étapes, léger, non root
# 1. Build : dépendances de développement + compilation TypeScript
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src ./src
RUN npm run build
# 2. Dépendances de production uniquement
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force
# 3. Image finale : pas d'outils de build, utilisateur non root
FROM node:22-alpine AS runtime
ENV NODE_ENV=production PORT=3000
WORKDIR /app
COPY --from=deps --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/dist ./dist
COPY --chown=node:node package.json ./
COPY --chown=node:node public ./public
COPY --chown=node:node db ./db
USER node
EXPOSE 3000
HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=3 \
CMD wget -qO- "http://127.0.0.1:${PORT}/health" > /dev/null || exit 1
CMD ["node", "dist/server.js"]Le .dockerignore est aussi important que le Dockerfile : il empêche d'envoyer dans l'image les secrets (.env), l'historique Git, les tests et la configuration de l'agent.
docker compose : la base, les migrations, puis l’application

cp .env.example .env # choisir un vrai POSTGRES_PASSWORD
docker compose up --build # PostgreSQL 18 → migrations → application
open http://localhost:3000Transparence : Docker n'était pas installé sur la machine de l'atelier. L'image n'a donc pas pu être construite en local. Pour ne pas livrer un fichier non vérifié, deux parades : la disposition exacte de l'image (code compilé + dépendances de production seules) a été reproduite et testée hors conteneur — migration, redirection, ressources statiques —, et la CI construit l'image et démarre toute la pile à chaque modification. Un agent honnête signale ce qu'il n'a pas pu vérifier ; exigez-le.
Git, qualité du code et livraison de la v1.0.0
Une branche par intention, main toujours stable
Aucun commit n'a été fait directement sur main après l'initialisation : chaque étape vit sur sa branche, et main n'avance que lorsque tout est vert. L'historique raconte le projet, dans l'ordre :
Les messages suivent les Conventional Commits (feat, fix, test, build, docs, chore), en anglais. Ce n'est pas qu'une convention esthétique : c'est ce qui permet au skill release-notes de générer automatiquement les notes de version. Ici, faute de dépôt distant, main a été avancée en fast-forward uniquement (git merge --ff-only), ce qui garde un historique linéaire ; dans une équipe, cette étape passe par une merge request revue et une branche main protégée.
Clean Code, SOLID et DRY : des exemples concrets
Principe | Où le voir dans LinkLite |
|---|---|
S — responsabilité unique |
|
O — ouvert/fermé | Un nouveau stockage (Redis…) = un nouvel adaptateur, sans modifier le cas d’usage. |
L — substitution | Les adaptateurs mémoire et PostgreSQL sont interchangeables : la même suite de comportements s’applique. |
I — interfaces ciblées | Le port |
D — inversion des dépendances |
|
DRY | Une seule fonction |
KISS | Pas d’ORM pour trois requêtes, pas de framework front pour une page. |
Échec rapide |
|
L'intégration continue
Le pipeline rejoue tout ce qui a été fait en local, sur une machine neuve : types, lint, format, tests avec couverture contre un PostgreSQL de service, audit des dépendances, parcours Playwright, puis construction de l'image Docker et démarrage de la pile complète. Une branche dont le pipeline est rouge ne fusionne pas.
La livraison, avec le skill release-notes
Le prompt « Prépare la v1.0.0 avec le skill release-notes » a déroulé les étapes du skill :
Collecte des commits depuis le début du projet, groupés par type (script du skill).
Rédaction des notes selon le gabarit de référence, orientées utilisateur (l'effet, pas l'implémentation).
Ajout de la section
[1.0.0]en tête duCHANGELOG.mdet passage depackage.jsonen 1.0.0.Vérifications bloquantes :
npm run check, couverture (98,9 %) et 10 parcours de bout en bout au vert.Commit
chore(release): v1.0.0sur une brancherelease/v1.0.0.Avance de
mainen fast-forward, puis tag annotév1.0.0posé surmain.
$ git log --oneline --decorate -3
93a1936 (HEAD -> main, tag: v1.0.0, release/v1.0.0) chore(release): v1.0.0
d369e61 (fix/security) fix(security): address the low-severity findings of the re-audit
e735e9b docs: add the MIT licenseLe bilan chiffré
Indicateur | Résultat |
|---|---|
Tests unitaires et d’intégration | 89, tous verts |
Couverture | 98,9 % des instructions, 98,8 % des branches (seuil : 90 %) |
Parcours de bout en bout | 10 (bureau + mobile) |
Audit de sécurité | 2 Élevés et 4 Moyens corrigés, risques faibles résiduels documentés |
Bugs attrapés avant livraison | Ressources statiques interceptées, contournements SSRF, 429 transformé en 500, régression IPv4 |
Livraison | Tag |
Ce qu'il faut retenir de l'atelier : l'agent a écrit l'essentiel du code, mais la qualité est venue du cadre — un périmètre écrit, une mémoire projet, des tests d'abord, une documentation à jour via Context7, un design guidé par un skill, un auditeur indépendant et une livraison outillée.
Conclusion
L'IA générative a franchi un cap : après avoir appris à répondre, elle sait désormais agir. Pour les équipes de développement et les directions des systèmes d'information, les agents de codage sont une opportunité majeure — à condition de les traiter comme ce qu'ils sont : des collaborateurs très rapides, qui ont besoin d'un cadre clair (mémoire, conventions), d'un objectif vérifiable (tests), de garde-fous (permissions, sécurité des données) et d'une relecture humaine.
L'atelier LinkLite l'a montré concrètement : un agent bien cadré livre en quelques étapes une application testée, auditée et conteneurisée — et les erreurs qu'il commet sont attrapées par les tests, l'auditeur et les permissions plutôt que par les utilisateurs. La meilleure façon de commencer est simple : choisir une tâche réelle mais limitée, lancer /init, enrichir le CLAUDE.md, configurer quelques permissions prudentes, puis suivre le cycle explorer, planifier, implémenter, vérifier, relire. C'est en pratiquant, avec méthode, que l'IA devient un véritable multiplicateur de compétences.
Glossaire
Terme | Définition |
|---|---|
Agent IA | Système qui combine un modèle de langage, des outils et une boucle d’actions pour atteindre un objectif. |
Context7 | Serveur MCP qui fournit à l’agent la documentation à jour et versionnée des bibliothèques. |
Contexte (fenêtre de) | Quantité de texte que le modèle peut prendre en compte à un instant donné. |
Hallucination | Information fausse produite avec assurance par un modèle. |
Hook | Script déclenché automatiquement avant ou après une action de l’agent. |
LLM | Large Language Model : grand modèle de langage. |
MCP | Model Context Protocol : standard ouvert pour connecter un agent à des outils et des données. |
Port / adaptateur | Architecture hexagonale : interface définie par le métier (port) et implémentation technique interchangeable (adaptateur). |
Prompt | Instruction ou demande adressée au modèle. |
Skill | Savoir-faire packagé (instructions, scripts) chargé par l’agent quand il est utile. |
Sous-agent | Agent spécialisé, avec son propre contexte, à qui l’agent principal délègue une tâche. |
SSRF | Server-Side Request Forgery : abuser d’un serveur pour atteindre des adresses internes. |
TDD | Test-Driven Development : écrire le test qui échoue avant le code qui le fait passer. |
Token | Fragment de texte, unité de base traitée par un modèle de langage. |