+210 XP

Boucles et exécutions autonomes : /loop, itération et planification

Boucles et exécutions autonomes : itération et planification

Certains travaux ne sont pas une tâche unique mais la même tâche répétée jusqu'à ce qu'une condition soit remplie. « Continue à corriger les bugs jusqu'à ce que tous les tests passent. » « Interroge le déploiement chaque minute jusqu'à ce qu'il soit en ligne, puis préviens-moi. » « Chaque matin à 8 h, résume ce qui a changé dans le repo pendant la nuit. » Aucune de ces demandes n'est une action unique. Ce sont des boucles avec une condition d'arrêt, et Claude Code les traite de deux façons différentes selon que la répétition se produit à l'intérieur d'une exécution ou à travers plusieurs exécutions planifiées.

Cette leçon porte sur l'exécution de Claude Code en boucle : itérer jusqu'à ce qu'un objectif soit atteint, tourner en autonomie sans surveiller chaque étape, et planifier un agent pour qu'il se déclenche à intervalle régulier. Tout aussi important, elle porte sur les garde-fous qui empêchent une exécution non surveillée de consommer votre budget de tokens ou d'abîmer votre code.

Quand la boucle est le bon outil

Une boucle mérite d'être envisagée quand trois conditions sont réunies :

  • La tâche se répète. Vous effectuez la même opération plus d'une fois (interroger, réessayer, itérer).
  • Il existe une condition d'arrêt mesurable. Les tests passent, un build est vert, un fichier existe, une valeur franchit un seuil. Si vous ne pouvez pas décrire « terminé » avec précision, vous ne pouvez pas boucler sans risque.
  • Le résultat s'améliore à chaque passage, ou vous attendez un changement externe. Corriger des tests s'améliore à chaque passage. Interroger un build revient à attendre quelque chose d'externe.

Si aucune de ces conditions n'est vraie, un appel unique est plus propre et moins coûteux. Ne bouclez pas juste parce que c'est possible. « Refactorise cette fonction » est un appel unique. « Refactorise chaque fonction jusqu'à ce que le linter se taise » est une boucle.

Comment l'itération fonctionne réellement dans Claude Code

Claude Code tourne dans votre terminal et a déjà accès à vos fichiers, à votre shell et à votre historique git. Il n'existe pas de commande de boucle dédiée. À la place, vous obtenez l'itération de deux manières.

La première se situe à l'intérieur d'une seule exécution. Vous décrivez la tâche, la condition d'arrêt et un plafond strict directement dans votre prompt, et Claude effectue le travail, confronte sa propre sortie à la condition, et répète jusqu'à ce que la condition soit remplie ou le plafond atteint. Claude peut lancer une commande, lire le résultat, décider si c'est terminé, et agir de nouveau, le tout dans une même session. C'est le motif « continue jusqu'à X ».

La seconde est une boucle shell autour du mode headless. Vous appelez claude -p "..." (un prompt unique qui s'exécute puis se termine) depuis une boucle bash while ou un script, et votre script prend en charge la répétition, le délai entre les exécutions et la logique de sortie. C'est la bonne forme pour interroger quelque chose d'externe à intervalle fixe, car votre script contrôle le rythme.

Voici le motif intra-session. Vous donnez à Claude la tâche, la condition d'arrêt et le plafond en langage clair :

bash
claude
> Run the full test suite with pytest. If any tests fail,
  read the failure output, fix the SOURCE code (not the tests),
  and run the suite again. Repeat until all tests pass or you
  have made 10 attempts. If you hit 10 attempts, stop and tell me
  what is still failing.

Remarquez trois choses intégrées à ce prompt. La tâche est explicite (lancer pytest, corriger le code). La condition d'arrêt est sans ambiguïté (tous les tests passent). Et il y a un plafond strict (10 tentatives) pour qu'un bug tenace ne puisse pas tourner indéfiniment.

Et voici le motif à intervalle sous forme de boucle shell, utile quand vous attendez quelque chose hors de votre contrôle :

bash
# Interroge un déploiement toutes les 30 s, jusqu'à 20 fois, jusqu'à obtenir un 200
for i in $(seq 1 20); do
  if curl -sf -o /dev/null https://myapp.example.com/health; then
    claude -p "The deploy is live. Post a one-line 'shipped' note."
    break
  fi
  sleep 30
done

Le script prend en charge la boucle, le délai et le plafond. Claude ne s'exécute que lorsqu'il y a quelque chose à faire.

Pourquoi la condition d'arrêt doit être vérifiable par une machine

« Corrige le code jusqu'à ce qu'il soit bien » n'est pas une condition de boucle. Claude n'a aucun signal objectif à vérifier, il va donc soit s'arrêter arbitrairement, soit continuer à polir indéfiniment. « Corrige le code jusqu'à ce que `pytest` sorte avec le code 0 » est vérifiable : le code de sortie est un fait, pas un jugement.

Les bonnes conditions de boucle sont celles auxquelles une commande peut répondre :

  • le code de sortie de pytest est 0
  • npm run build réussit
  • git status ne montre aucune modification non commitée
  • une chaîne précise apparaît dans un fichier de log
  • un endpoint HTTP renvoie 200

Chaque fois que vous pouvez exprimer « terminé » sous forme de commande qui renvoie succès ou échec, vous avez une boucle dont vous pouvez attendre qu'elle s'arrête d'elle-même.

L'exemple travaillé : corriger jusqu'à ce que la suite soit verte

C'est le cas d'usage canonique, rendons-le concret. Vous avez une suite de tests avec quelques échecs après un merge bâclé. Vous voulez que Claude itère : lancer les tests, lire ce qui a cassé, patcher la source, relancer, jusqu'à ce que toute la suite soit verte.

bash
claude
> Goal: make the entire test suite pass.
  1. Run: pytest -x --tb=short
  2. If exit code is 0, the goal is met. Stop and summarize what changed.
  3. If tests failed, read the traceback, fix the SOURCE code only.
     Never edit or delete tests to make them pass.
  4. Commit each fix with a clear message, then repeat from step 1.
  Budget: stop after 8 attempts and report if not green by then.

Lisez les garde-fous cachés dans ce prompt. L'étape 3 interdit la triche la plus courante vers laquelle un agent autonome va se tourner : supprimer le test qui échoue. Sans contrainte, un modèle auquel on demande de « faire passer les tests » peut très bien décider que le chemin le plus rapide est de supprimer le test. L'instruction « corrige uniquement le code SOURCE, ne modifie jamais les tests » ferme cette porte.

L'instruction de commiter chaque correction compte aussi. Elle vous donne un historique git propre à relire et un revert facile si l'une des corrections de Claude était mauvaise. Quand l'exécution se termine, vous relisez le diff, pas le processus.

C'est exactement le type de tâche où l'itération justifie son coût. Une correction unique suivie d'un arrêt réglerait un premier tour d'échecs, en révélant probablement un second tour qu'elle n'aurait jamais touché. L'itération traite tout cela pendant que vous faites autre chose.

Autonomous Test-Fixing Loops in Claude Code

Watch on YouTube

Garde-fous pour les exécutions non surveillées

Dès qu'une exécution se déroule sans que vous surveilliez chaque étape, elle peut faire des dégâts ou gaspiller de l'argent à vitesse machine. Trois garde-fous ne sont pas négociables.

1. Un budget strict

Toute boucle a besoin d'un plafond qui ne dépend pas du jugement du modèle. Un compteur de tentatives dans le prompt est le plus simple. Si votre script prend en charge la boucle, plafonnez-y le nombre d'itérations (le for i in $(seq 1 20) ci-dessus fait exactement cela). Le budget est un filet de sécurité pour les cas où la condition d'arrêt ne se déclenche jamais, car parfois les tests ne peuvent réellement pas être rendus passants, et vous voulez que l'exécution abandonne et vous le dise, pas qu'elle continue indéfiniment.

2. Une condition d'arrêt claire

Déjà traitée plus haut, mais elle figure dans la liste des garde-fous parce qu'elle est le mécanisme de sécurité principal. Le budget est le filet ; la condition d'arrêt est la sortie prévue. Une exécution avec un budget mais sans véritable condition d'arrêt brûle jusqu'au plafond à chaque fois.

3. Un point de validation humaine

Pour tout ce qui modifie un état (écrit du code, pousse des commits, envoie des messages, appelle une API payante), décidez à l'avance où un humain valide. Deux motifs courants :

  • Relecture à la fin. L'exécution se déroule en pleine autonomie mais ne produit qu'une branche et un diff. Vous relisez avant de merger. C'est l'exemple des tests verts : les commits s'empilent sur une branche, rien ne partit avant votre accord.
  • Relecture par action. Vous configurez les demandes d'autorisation de Claude Code pour que les opérations risquées (écritures de fichiers hors d'un répertoire, commandes shell, appels réseau) exigent votre validation à chaque fois. Plus lent, mais approprié quand le rayon d'impact est large.

Vous contrôlez cela via les réglages de permissions de Claude Code. Restreignez les outils que l'agent peut utiliser et les répertoires auxquels il peut toucher avant de le laisser tourner sans surveillance. La documentation Claude Code détaille les modes de permission et la configuration des outils.

Une règle mentale utile : plus l'exécution est autonome, plus le bac à sable doit être étroit. Une exécution que vous surveillez peut avoir de larges permissions. Une qui se déclenche à 3 h du matin pendant que vous dormez ne devrait pouvoir toucher presque rien, sauf la seule chose pour laquelle elle est là.

Vérification des acquis

1. D'après la leçon, quelle est la différence essentielle entre une tâche qui justifie une boucle et une tâche qui devrait être un appel unique ?

2. Pourquoi la leçon insiste-t-elle sur le fait qu'il faut pouvoir décrire « terminé » avec précision avant d'utiliser une boucle ?

3. Un développeur veut que Claude interroge un déploiement CI chaque minute et le prévienne dès qu'il est en ligne. Quelle variante de /loop convient, et pourquoi ?

CHOIX MULTIPLES

4. Sélectionnez TOUTES les affirmations qui décrivent correctement les deux variantes de la commande /loop.

Sélectionnez toutes les réponses correctes.

CHOIX MULTIPLES

5. Sélectionnez TOUS les éléments qui, selon la leçon, définissent la forme d'une commande /loop bien construite.

Sélectionnez toutes les réponses correctes.

Planification : des exécutions déclenchées à intervalle régulier

L'itération répond à « répète jusqu'à ce que ce soit fait ». La planification répond à « relance plus tard, selon un rythme ». Un digest récurrent, une vérification nocturne des dépendances, un rapport hebdomadaire : ce ne sont pas des exécutions qui tournent jusqu'à une condition, ce sont des tâches qui se réveillent selon un calendrier.

Claude Code ne fait pas tourner de démon en arrière-plan. Vous le planifiez comme n'importe quel outil en ligne de commande : avec le planificateur de votre système d'exploitation (cron sur Linux et macOS, le Planificateur de tâches sur Windows) ou un runner CI comme GitHub Actions.

Voici un digest nocturne du repo sous forme d'entrée cron qui lance Claude en mode non interactif (headless) :

bash
# Chaque jour de semaine à 8h00, résume l'activité git de la nuit
0 8 * * 1-5 cd /home/me/project && \
  claude -p "Summarize commits from the last 24 hours grouped by \
  author. Flag anything touching auth/ or billing/. Output markdown." \
  >> ~/digests/daily-$(date +\%F).md 2>&1

Le flag `-p` exécute un prompt unique puis se termine, ce qui est exactement ce que vous voulez pour un job planifié : pas de session interactive, un début et une fin déterministes, une sortie redirigée vers un fichier. Associez cela à un serveur MCP et la même exécution planifiée pourrait poster ce digest sur Slack ou ouvrir une issue GitHub. Voyez la documentation Model Context Protocol pour savoir comment câbler ces connexions.

Pour une planification qui vit avec votre repo plutôt que sur une seule machine, GitHub Actions est le lieu naturel. La Claude Code GitHub Action officielle d'Anthropic vous permet de déclencher Claude selon un calendrier ou sur des événements du repo (une nouvelle PR, une issue étiquetée d'une certaine façon). Un workflow hebdomadaire on: schedule qui lance Claude pour auditer les dépendances et ouvrir une PR est une exécution autonome planifiée, propre et relisible.

Les exécutions planifiées ont besoin des mêmes garde-fous, encore plus

Un job planifié est autonome par définition : personne ne regarde quand il se déclenche. Tout ce qui figure dans la section garde-fous s'applique doublement. Donnez-lui un budget, donnez-lui une condition d'arrêt même pour un digest one-shot (afin qu'un appel externe bloqué ne le laisse pas tourner), et faites passer tout ce qui modifie un état par un point de validation. Une exécution planifiée qui ouvre une PR est sûre. Une exécution planifiée qui pousse sur main est un fusil pointé vers votre pied qui attend une mauvaise nuit.

Itération, planification ou appel unique

Guide de décision rapide :

  • Appel unique : une tâche, pas de répétition, vous êtes présent. « Refactorise ce module. »
  • Itération intra-session : décrivez la tâche, une condition d'arrêt vérifiable et un plafond de tentatives dans un seul prompt ; Claude répète jusqu'à ce que ce soit terminé. « Corrige jusqu'à ce que les tests passent, 8 tentatives maximum. »
  • Boucle shell autour de claude -p : votre script prend en charge la répétition et le délai, en appelant Claude à chaque passage. Idéal pour interroger quelque chose d'externe à intervalle régulier. « Interroge le déploiement toutes les 30 s jusqu'à ce qu'il soit en ligne. »
  • Exécution planifiée : se réveille à intervalle régulier, en général sur une nouvelle tâche unique à chaque fois, via cron ou GitHub Actions lançant claude -p. « Chaque matin, fais le digest du repo. »

Les configurations les plus puissantes les combinent : un workflow GitHub Actions planifié qui se déclenche chaque nuit et, à l'intérieur de cette exécution, fait itérer Claude jusqu'à ce que ses montées de version de dépendances passent la CI. La cadence à l'extérieur, l'itération à l'intérieur.

Points clés

  • Ne bouclez que si la tâche se répète et si « terminé » est vérifiable par une machine. Si vous ne pouvez pas exprimer la condition d'arrêt sous forme de commande qui renvoie succès ou échec, vous n'avez pas encore de boucle sûre.
  • Claude Code n'a pas de commande de boucle dédiée. Vous obtenez l'itération en décrivant la tâche, la condition d'arrêt et un plafond de tentatives dans un seul prompt, ou en enveloppant claude -p dans une boucle shell qui prend en charge la répétition.
  • Toute exécution non surveillée a besoin de trois garde-fous : un budget strict (tentatives, temps ou tokens), une condition d'arrêt claire, et un point de validation humaine sur tout ce qui modifie un état.
  • Contraignez l'agent sur la triche. « Fais passer les tests » invite à supprimer les tests ; dites « corrige uniquement la source, ne modifie jamais les tests » et commitez chaque correction pour relire un diff propre, pas un processus opaque.
  • Planifiez avec les outils que vous avez déjà : cron, le Planificateur de tâches ou GitHub Actions lançant claude -p en mode headless. Claude Code est l'exécutant, pas le planificateur.
  • Plus l'exécution est autonome, plus le bac à sable doit être étroit. Une exécution que vous surveillez peut avoir de larges permissions ; une qui se déclenche pendant que vous dormez ne devrait pouvoir toucher que la seule chose pour laquelle elle existe.