KURSE / CLAUDE-CODE / MODUL 11

Mode headless et CI/CD : Claude Code comme brique d'automatisation

⚠ Diese Seite ist noch nicht uebersetzt. Anzeige auf Englisch.
← Claude Code: vom Einsteiger zum Experten
Modul 11/12 Experte 20 min

Mode headless et CI/CD : Claude Code comme brique d'automatisation

Transformez Claude Code en brique d'automatisation : mode headless claude -p, pipes Unix, sortie JSON, GitHub Actions et garde-fous pour une CI sûre.

Ziele dieses Moduls
  • Scripter Claude Code en mode headless avec claude -p et exploiter sa sortie JSON
  • Verrouiller une exécution non interactive avec --allowedTools, --permission-mode et --max-turns
  • Intégrer Claude Code dans GitHub Actions et maîtriser les coûts en CI

Depuis le début de cette formation, vous dialoguez avec Claude Code. Vous tapez, il répond, vous validez. Dans ce module, on coupe le dialogue. Claude Code devient une commande silencieuse, comme grep ou git : vous la lancez, elle travaille, elle rend son résultat, elle s’arrête. C’est le mode headless, et c’est la clé qui ouvre l’automatisation : scripts shell, intégration continue, GitHub Actions. À la fin de ce module, Claude travaillera pour vous même quand vous n’êtes pas devant l’écran.

Ce que vous allez apprendre

  • Lancer Claude Code en mode headless avec claude -p et le brancher sur des pipes Unix
  • Récupérer une sortie structurée en JSON, exploitable dans n’importe quel script
  • Verrouiller une exécution sans humain avec --allowedTools, --permission-mode et --max-turns
  • Appliquer trois recettes concrètes : migration de masse, triage d’issues, revue de pull request
  • Câbler votre dépôt GitHub pour qu’une simple mention @claude déclenche le travail

Le déclic : Claude Code est une commande Unix comme les autres

Le mot headless signifie « sans tête ». Comprenez : sans interface interactive. Pas de conversation, pas de questions-réponses. Vous donnez un prompt, Claude Code l’exécute, imprime le résultat, et rend la main. C’est l’option -p (comme print) qui active ce mode.

# Une question, une réponse, terminé
claude -p "Que fait le module d'authentification de ce projet ?"

Ça paraît anodin. C’est en réalité un changement de nature. Une commande qui lit l’entrée standard et écrit sur la sortie standard, c’est la définition même d’un outil Unix. Et un outil Unix, ça se branche sur tout : des scripts, des tâches planifiées, des chaînes d’intégration continue.

Des pipes pour tout brancher

Un pipe, c’est le symbole | dans votre terminal. Il branche la sortie d’une commande sur l’entrée de la suivante, comme un tuyau entre deux machines. Claude Code sait lire ce qui arrive par ce tuyau.

# Le contenu du fichier de log part dans le tuyau,
# Claude le reçoit et applique le prompt
cat erreurs.log | claude -p 'explique la cause racine de ces erreurs'

Et comme toute commande Unix, la réponse peut repartir dans un fichier ou vers une autre commande.

# La réponse est écrite dans un fichier de rapport
cat erreurs.log | claude -p 'explique la cause racine' > rapport.txt

Retenez cette image : Claude Code devient un maillon de chaîne. Ce qui entre, ce qui sort, tout se raccorde.

Une sortie que vos scripts comprennent

Un texte libre, c’est agréable pour un humain. Pour un script, c’est fragile. L’option --output-format règle le problème avec trois valeurs : text (le défaut), json et stream-json.

Avec json, la réponse arrive dans un objet structuré : le texte dans le champ result, l’identifiant de session dans session_id, et même le coût de l’appel dans total_cost_usd. Votre script peut extraire exactement ce dont il a besoin.

# jq est l'outil standard pour lire du JSON en ligne de commande
# L'option -r extrait le texte brut, sans guillemets
claude -p "Résume ce projet" --output-format json | jq -r '.result'

Le format stream-json, lui, émet un objet JSON par ligne, au fil de l’eau. Utile quand vous voulez suivre une longue exécution en temps réel, événement par événement.

💡 Astuce — Le champ total_cost_usd de la sortie JSON vous donne le coût exact de chaque appel API. Enregistrez-le dans vos journaux de CI : vous saurez précisément ce que coûte chaque automatisation, sans consulter aucun tableau de bord.

Garder le contrôle quand personne ne surveille

En mode interactif, Claude vous demande la permission avant chaque action sensible. En mode headless, il n’y a personne pour répondre. Tout doit donc être déclaré à l’avance. Trois options forment votre ceinture de sécurité.

La première, --allowedTools, est une liste blanche stricte : vous énumérez les outils autorisés, tout le reste est refusé. La syntaxe reprend les règles de permission vues au module sur la configuration.

# Lecture, recherche, et uniquement les commandes npm run test:*
claude -p "Lance les tests et corrige les échecs" \
  --allowedTools "Read,Grep,Edit,Bash(npm run test:*)"

La deuxième, --permission-mode, fixe un cadre global. Le mode plan, par exemple, met Claude en lecture seule : parfait pour des analyses sans aucun risque d’écriture.

# Analyse en lecture seule : aucun fichier ne sera modifié
claude -p "Audite la gestion des erreurs de ce projet" --permission-mode plan

La troisième, --max-turns, plafonne le nombre d’allers-retours entre Claude et ses outils. C’est votre coupe-circuit : une tâche qui s’emballe s’arrête d’elle-même au lieu de tourner sans fin.

Reste l’authentification. En CI, pas de /login interactif : la clé API passe par la variable d’environnement ANTHROPIC_API_KEY, stockée dans le coffre à secrets de votre plateforme. Jamais dans le code, jamais dans un fichier versionné.

⚠️ Piège courant — Oublier --allowedTools en headless ne rend pas Claude tout-puissant, c’est l’inverse : dès qu’il tente une action non autorisée, l’exécution se bloque ou échoue. Votre script rend alors un résultat incomplet sans que vous compreniez pourquoi. Déclarez toujours explicitement ce dont la tâche a besoin, et rien de plus.

Trois recettes d’automatisation qui changent le quotidien

La théorie est en place. Passons à la pratique avec trois recettes directement réutilisables.

Recette 1 : la migration de masse, fichier par fichier

Imaginez 200 fichiers à convertir de JavaScript vers TypeScript. En session interactive, le contexte déborderait vite. En headless, chaque fichier a droit à son propre appel, avec un contexte tout neuf : chaque itération est isolée, vérifiable, et un commit la fige.

#!/bin/bash
# Migration de masse : un appel Claude par fichier, un commit par fichier
for fichier in $(find src -name "*.js"); do
  echo "Migration de $fichier..."
  claude -p "Convertis $fichier en TypeScript. Ne modifie aucun autre fichier." \
    --allowedTools "Read,Edit,Write" \
    --max-turns 10
  # Verification immediate : les tests valident chaque etape
  npm test || echo "$fichier" >> a-verifier.txt
  git add -A && git commit -m "migration TS : $fichier"
done

Si un fichier pose problème, il atterrit dans a-verifier.txt et la boucle continue. Le lendemain matin, vous relisez la liste des cas douteux au lieu de surveiller 200 conversions une à une.

Recette 2 : le triage automatique des issues GitHub

Deuxième recette : labelliser et prioriser les tickets entrants. On s’appuie sur gh, l’outil en ligne de commande officiel de GitHub, et on demande à Claude une réponse ultra-courte, facile à réinjecter.

#!/bin/bash
# Triage : Claude choisit un label, gh l'applique
numero=42
label=$(gh issue view "$numero" --json title,body | \
  claude -p "Voici une issue GitHub en JSON. Choisis UN label parmi : bug, amelioration, documentation, question. Reponds uniquement par le label, rien d'autre.")
gh issue edit "$numero" --add-label "$label"

Le même principe s’étend à la priorisation (répondre haute, moyenne ou basse) ou à la détection de doublons : donnez à Claude la liste des titres d’issues ouvertes et demandez-lui les paires probablement identiques. La consigne « réponds uniquement par… » est le secret : elle transforme un modèle bavard en composant prévisible.

Recette 3 : revue de pull request et changelog générés

Troisième recette : faire relire chaque pull request avant la revue humaine. Le diff part dans le tuyau, le commentaire revient dans la PR.

# Le diff de la PR 128 est relu, le verdict est poste en commentaire
gh pr diff 128 | \
  claude -p "Relis ce diff en relecteur senior : bugs, failles, cas limites. Sois concis." \
  --output-format json | jq -r '.result' | \
  gh pr comment 128 --body-file -

Et pour le changelog, ce journal des modifications que personne n’aime rédiger, la matière première existe déjà : vos messages de commit.

# Les commits depuis la derniere version deviennent un changelog propre
git log --oneline v1.4.0..HEAD | \
  claude -p "Transforme ces commits en changelog en francais, groupe par categorie : nouveautes, corrections, interne."

💡 Astuce — Dans toutes ces recettes, soignez la dernière phrase du prompt : « réponds uniquement par… », « sois concis », « groupe par catégorie ». En automatisation, la précision de la consigne remplace la conversation. Un prompt flou en interactif se rattrape ; en headless, il se paie à chaque exécution.

GitHub Actions sans effort : la mention @claude

Tout ce que nous venons de scripter à la main, GitHub peut le déclencher pour vous. GitHub Actions, c’est le service d’automatisation intégré à GitHub : à chaque événement du dépôt (une issue ouverte, une PR créée, un commentaire posté), il exécute des tâches sur des machines louées à la minute, les runners.

La mise en place tient en une commande, lancée depuis Claude Code dans votre dépôt.

# Dans une session Claude Code, a la racine du depot
/install-github-app

Cette commande installe l’application GitHub de Claude sur votre dépôt, ajoute le workflow, et vous guide pour enregistrer la clé API dans le secret ANTHROPIC_API_KEY. Il faut être administrateur du dépôt pour la dérouler.

Ensuite, la magie opère : mentionnez @claude dans une issue ou un commentaire de pull request, et l’action anthropics/claude-code-action se réveille. Écrivez « @claude corrige cette erreur de typage » dans une issue, et Claude analyse le contexte, code la correction et ouvre une pull request. Le workflow minimal ressemble à ceci :

name: Claude Code
on:
  issue_comment:
    types: [created]
jobs:
  claude:
    runs-on: ubuntu-latest
    steps:
      - uses: anthropics/claude-code-action@v1
        with:
          # La cle vit dans les secrets du depot, jamais en clair
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

Côté bonnes pratiques : la clé API reste dans les secrets GitHub, les permissions de l’application se limitent au strict nécessaire (contenus, issues, pull requests), et chaque proposition de Claude passe par une revue humaine avant fusion. Le paramètre claude_args du workflow accepte les mêmes options que la ligne de commande, --max-turns en tête.

💡 Astuce — Votre fichier CLAUDE.md versionné, vu au module sur la mémoire, s’applique aussi en CI. Les conventions de code, les règles de revue, les interdits du projet : Claude les respecte sur le runner GitHub exactement comme sur votre machine. Un CLAUDE.md soigné, c’est une CI disciplinée.

Une CI sûre et économe

Automatiser, c’est déléguer. Et on ne délègue sereinement qu’avec des garde-fous. Quatre principes structurent une CI saine avec Claude Code.

Premier principe : l’isolation. Un job de CI tourne dans un conteneur, une machine virtuelle jetable, détruite après usage. C’est là, et seulement là, que l’option --dangerously-skip-permissions devient légitime : elle désactive toutes les demandes de permission, ce qui est dangereux sur votre poste, mais acceptable dans un environnement sans secrets superflus, sans accès à vos données, et qui disparaît à la fin du job.

Deuxième principe : les permissions minimales. Même isolé, un job n’a pas besoin de tout. Une revue de diff se contente de --permission-mode plan ou d’une liste --allowedTools réduite à la lecture. Réservez les droits d’écriture aux jobs qui en ont réellement besoin.

Troisième principe : le budget. En CI, chaque exécution consomme des jetons d’API, et une tâche mal bornée peut coûter cher. Vos leviers : --max-turns pour plafonner chaque appel, des timeouts au niveau du workflow, et le choix du modèle. Un triage d’issue n’a pas besoin du modèle le plus puissant : la gamme Haiku, rapide et économe, suffit largement, quand une revue de sécurité mérite la gamme Opus. L’option --model fait la bascule, et notre comparatif des IA vous aide à situer chaque gamme.

Quatrième principe : les journaux. Conservez les sorties JSON de chaque exécution comme artefacts de CI. Le champ total_cost_usd alimente votre suivi de coûts, le champ session_id permet de retracer une exécution douteuse, et l’historique complet vous protège le jour où il faut comprendre ce que l’automate a réellement fait. Pour approfondir la place de ces agents dans votre boîte à outils, notre dossier IA complète ce module.

⚠️ Piège courant — Ne recopiez jamais --dangerously-skip-permissions d’un exemple de CI vers votre terminal personnel. Sur votre machine, cette option donne à Claude le droit d’exécuter n’importe quelle commande sans validation. La règle tient en une phrase : conteneur jetable, oui ; poste de travail, jamais.

À vous de jouer

Écrivons ensemble le script de l’exercice : une relecture automatique du diff de votre branche courante, qui échoue si Claude signale un problème bloquant. Exactement ce qu’on branche ensuite dans une CI.

  1. À la racine d’un projet git, créez un fichier relecture.sh et rendez-le exécutable avec chmod +x relecture.sh.
  2. Récupérez le diff de la branche courante par rapport à main : c’est la commande git diff main...HEAD. Si le diff est vide, le script se termine tout de suite avec succès.
  3. Envoyez ce diff à Claude par un pipe, avec --output-format json et une consigne de verdict stricte : la réponse doit commencer par VERDICT: BLOQUANT ou VERDICT: OK.
  4. Extrayez le texte avec jq -r '.result', affichez-le, puis cherchez le verdict avec grep. S’il est bloquant, quittez avec le code d’erreur 1 : c’est ce code qui fait échouer une CI.
#!/bin/bash
# relecture.sh — echoue si Claude signale un probleme bloquant
diff=$(git diff main...HEAD)
if [ -z "$diff" ]; then
  echo "Aucun changement a relire."
  exit 0
fi
reponse=$(echo "$diff" | claude -p "Relis ce diff. Commence ta reponse par VERDICT: BLOQUANT si un probleme critique (bug, faille, donnee sensible) doit empecher la fusion, sinon par VERDICT: OK. Justifie en trois points maximum." --output-format json)
texte=$(echo "$reponse" | jq -r '.result')
echo "$texte"
if echo "$texte" | grep -q "VERDICT: BLOQUANT"; then
  echo "Relecture bloquante : fusion refusee."
  exit 1
fi
echo "Relecture validee."
  1. Testez : créez une branche, introduisez volontairement un bug évident (une clé d’API en dur dans le code, par exemple), puis lancez ./relecture.sh. Le script doit afficher le verdict bloquant et sortir en erreur.
  2. Pour aller plus loin, appelez ce script depuis votre CI ou un hook git : vous venez de construire votre premier garde-barrière IA.

En résumé

  • claude -p "prompt" transforme Claude Code en commande Unix : lisible par pipe, redirigeable, scriptable partout.
  • --output-format json structure la réponse : le texte dans result, le coût dans total_cost_usd, la session dans session_id ; stream-json émet le détail ligne par ligne.
  • En non-interactif, tout se déclare à l’avance : --allowedTools en liste blanche, --permission-mode pour le cadre, --max-turns en coupe-circuit, et la clé API dans la variable d’environnement ANTHROPIC_API_KEY.
  • Les trois recettes à retenir : boucle de migration fichier par fichier, triage d’issues avec réponse courte réinjectable, revue de PR et changelog générés depuis le diff et les commits.
  • /install-github-app câble votre dépôt en quelques minutes ; ensuite, mentionner @claude dans une issue ou une PR déclenche l’action anthropics/claude-code-action.
  • --dangerously-skip-permissions n’a sa place que dans un conteneur isolé et jetable ; sur votre machine, jamais.

Vous savez maintenant piloter Claude Code depuis n’importe quel script. Mais la ligne de commande a ses limites : au prochain et dernier module, vous passerez de l’autre côté du miroir avec l’Agent SDK, pour intégrer le moteur de Claude Code directement dans vos propres applications TypeScript ou Python.

Testen Sie Ihr Wissen

0 / 5
  1. Dans un script, vous lancez : cat erreurs.log | claude -p 'explique la cause racine'. Que se passe-t-il ?

  2. Votre script doit récupérer uniquement le texte de la réponse de Claude pour le traiter automatiquement. Quelle est la bonne approche ?

  3. En CI, vous voulez que Claude puisse lire les fichiers et lancer uniquement des commandes git diff, rien d'autre. Que passez-vous à claude -p ?

  4. Votre dépôt a été configuré avec /install-github-app. Un collègue écrit « @claude corrige ce bug » dans un commentaire d'issue. Que se passe-t-il ?

  5. Dans quel cas l'option --dangerously-skip-permissions est-elle un choix raisonnable ?