- Avancé
- Headless Ci
Le mode headless : Claude Code sans interface
Le mode headless permet d'utiliser Claude Code comme un outil de ligne de commande classique : il reçoit une instruction, l'exécute, et retourne un résultat, sans interface interactive, sans demander de confirmation, sans attendre de saisie.
C'est la porte d'entrée vers l'intégration dans des pipelines CI/CD, des scripts d'automatisation et des outils DevOps.
Le flag --print (-p) : usage basique
Le flag --print (ou -p) lance Claude Code en mode non-interactif et affiche le résultat sur stdout :
# Usage basiqueclaude --print "Explique ce que fait cette fonction"# Avec un fichier en contexte (piping)cat src/utils/auth.ts | claude --print "Identifie les risques de sécurité dans ce code"# Piping vers d'autres commandesgit diff HEAD~1 | claude --print "Rédige un résumé de ces changements pour le CHANGELOG"# Raccourci -pclaude -p "Génère des tests unitaires pour le fichier src/lib/parser.ts"
Piping et scripts
Le mode --print s'intègre naturellement dans les pipes Unix :
#!/bin/bash# Script d'analyse de code avant commitCHANGED_FILES=$(git diff --name-only HEAD)for file in $CHANGED_FILES; doif [[ "$file" == *.ts ]] || [[ "$file" == *.tsx ]]; thenecho "Analyse de $file..."REVIEW=$(cat "$file" | claude --print \"Identifie les problèmes critiques dans ce code TypeScript.Réponds en JSON : {issues: array, severity: critical|high|medium|low}")echo "$REVIEW" | python3 -c "import sys, jsondata = json.load(sys.stdin)critical = [i for i in data.get('issues', []) if i.get('severity') == 'critical']if critical:print('BLOQUANT:', critical)exit(1)print('OK: pas de problème critique')"fidone
--output-format json : parsing automatisé
Pour intégrer la sortie de Claude dans des scripts, utilisez le format JSON :
# Format JSON structuréclaude --print --output-format json "Analyse ce code et retourne un objet JSON"# Stream JSON (pour les sorties longues)claude --print --output-format stream-json "Génère la documentation de cette API"
Le format json retourne un objet avec la structure suivante :
{"type": "result","subtype": "success","result": "Le contenu de la réponse de Claude...","session_id": "sess_abc123","total_cost_usd": 0.0023,"num_turns": 1}
Extraire uniquement la réponse avec jq :
RESULT=$(claude --print --output-format json "Résume en une phrase : $(cat README.md)" | jq -r '.result')echo "Résumé : $RESULT"
--max-turns : limiter les itérations
En mode headless, Claude peut effectuer plusieurs "tours" (lire des fichiers, écrire du code, vérifier...). --max-turns limite ce nombre pour éviter des boucles infinies :
# Limiter à 5 tours d'exécutionclaude --print --max-turns 5 "Corrige les erreurs TypeScript dans src/"# Pour des tâches simples, 1 tour suffitclaude --print --max-turns 1 "Génère un fichier README.md pour ce projet"
--dangerously-skip-permissions : mode automatique complet
# En CI/CD uniquement, dans un conteneur isoléclaude --print --dangerously-skip-permissions \"Génère les tests manquants pour src/services/ et exécute-les"
En production CI/CD, la combinaison recommandée est :
claude \--print \--dangerously-skip-permissions \--max-turns 10 \--output-format json \"Ta tâche ici"
Intégration GitHub Actions
Workflow complet : review automatique de PR
Ce workflow déclenche une review Claude Code sur chaque Pull Request :
name: Claude Code PR Reviewon:pull_request:types: [opened, synchronize]jobs:claude-review:runs-on: ubuntu-latestpermissions:contents: readpull-requests: writesteps:- name: Checkoutuses: actions/checkout@v4with:fetch-depth: 0- name: Setup Node.jsuses: actions/setup-node@v4with:node-version: '20'- name: Install Claude Coderun: npm install -g @anthropic-ai/claude-code- name: Run Claude Code reviewid: reviewenv:ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}run: |DIFF=$(git diff origin/${{ github.base_ref }}...HEAD -- '*.ts' '*.tsx' '*.js' | head -c 10000)REVIEW=$(echo "$DIFF" | claude \--print \--max-turns 3 \--output-format json \"Tu es un expert en review de code. Analyse ce diff Git et fournis :1. Un résumé des changements2. Les problèmes potentiels (sécurité, performance)3. Des suggestions d'amélioration concrètesFormat: Markdown structuré et concis." | jq -r '.result')echo "$REVIEW" > /tmp/review.mdecho "review_done=true" >> $GITHUB_OUTPUT- name: Post review commentif: steps.review.outputs.review_done == 'true'uses: actions/github-script@v7with:script: |const fs = require('fs');const review = fs.readFileSync('/tmp/review.md', 'utf8');github.rest.issues.createComment({issue_number: context.issue.number,owner: context.repo.owner,repo: context.repo.repo,body: `## Review automatique : Claude Code\n\n${review}\n\n---\n*Généré automatiquement par Claude Code*`});
Workflow : génération de tests automatique
name: Générer les tests manquantson:workflow_dispatch:inputs:target_path:description: 'Chemin à analyser (ex: src/services/)'required: truedefault: 'src/'jobs:generate-tests:runs-on: ubuntu-latestpermissions:contents: writepull-requests: writesteps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with:node-version: '20'- name: Install dependenciesrun: npm ci- name: Install Claude Coderun: npm install -g @anthropic-ai/claude-code- name: Generate missing testsenv:ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}run: |claude \--print \--dangerously-skip-permissions \--max-turns 15 \"Analyse les fichiers dans ${{ github.event.inputs.target_path }}.Pour chaque fichier sans test : crée le fichier de test Jest + TypeScriptcouvrant les cas nominaux et les cas d'erreur.Exécute ensuite npm test pour vérifier."- name: Create Pull Requestuses: peter-evans/create-pull-request@v5with:commit-message: "test: génération automatique des tests manquants"title: "Tests générés automatiquement par Claude Code"body: |Tests générés automatiquement pour les fichiers sans couverture.**Vérifier avant de merger :**- [ ] Les tests couvrent les cas nominaux- [ ] Les tests couvrent les cas d'erreur- [ ] La couverture est > 80%branch: "auto/generated-tests"
Workflow : audit de sécurité hebdomadaire
name: Audit de sécurité Claude Codeon:schedule:- cron: '0 6 * * 1' # Chaque lundi à 6hworkflow_dispatch:jobs:security-audit:runs-on: ubuntu-latestpermissions:contents: readissues: writesteps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with:node-version: '20'- name: Install Claude Coderun: npm install -g @anthropic-ai/claude-code- name: Run security auditid: auditenv:ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}run: |AUDIT=$(claude \--print \--max-turns 8 \--output-format json \"Audit de sécurité complet :1. Recherche de secrets hardcodés2. Dépendances vulnérables (package.json)3. Patterns dangereux (eval, innerHTML)4. Configurations de sécurité (CORS, CSP)Retourne JSON avec : critical (array), warnings (array), score (/10)" \| jq -r '.result')echo "$AUDIT" > /tmp/audit.jsonCRITICAL_COUNT=$(echo "$AUDIT" | python3 -c "import sys, jsontry:data = json.loads(sys.stdin.read())print(len(data.get('critical', [])))except:print(0)")echo "critical_count=$CRITICAL_COUNT" >> $GITHUB_OUTPUT- name: Create issue if critical findingsif: steps.audit.outputs.critical_count > 0uses: actions/github-script@v7with:script: |const fs = require('fs');const audit = fs.readFileSync('/tmp/audit.json', 'utf8');github.rest.issues.create({owner: context.repo.owner,repo: context.repo.repo,title: '[SECURITE] Problèmes critiques détectés par Claude Code',body: `## Rapport d'audit de sécurité\n\n\`\`\`json\n${audit}\n\`\`\``,labels: ['security', 'critical']});
Variables secrets et configuration
Intégration GitLab CI
Exemple basique d'intégration dans un pipeline GitLab :
# .gitlab-ci.ymlstages:- review- testclaude-review:stage: reviewimage: node:20-alpineonly:- merge_requestsscript:- npm install -g @anthropic-ai/claude-code- |DIFF=$(git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD | head -c 8000)REVIEW=$(echo "$DIFF" | claude \--print \--max-turns 3 \"Review ce diff et identifie les problèmes potentiels.")echo "$REVIEW"variables:ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY
Pre-commit hooks avec Claude Code
Intégrez Claude Code dans vos hooks git pre-commit :
#!/bin/bash# .git/hooks/pre-commit# Rendre exécutable : chmod +x .git/hooks/pre-commitset -eSTAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx|js|jsx)$' || true)if [ -z "$STAGED_FILES" ]; thenexit 0fiecho "Analyse Claude Code des fichiers staged..."for file in $STAGED_FILES; doISSUES=$(cat "$file" | claude \--print \--max-turns 1 \--output-format json \"Identifie les problèmes CRITIQUES (bugs évidents, failles de sécurité).Réponds avec un JSON {issues: string[], has_critical: boolean}" \| jq -r '.result' 2>/dev/null || echo '{"has_critical": false}')HAS_CRITICAL=$(echo "$ISSUES" | python3 -c "import sys, jsontry:d = json.loads(sys.stdin.read())print('true' if d.get('has_critical') else 'false')except:print('false')")if [ "$HAS_CRITICAL" = "true" ]; thenecho "BLOQUÉ : problème critique dans $file"exit 1fidoneecho "OK : pas de problème critique détecté"exit 0
Bonnes pratiques de sécurité en mode headless
Limiter les coûts en CI/CD
# Mauvais : envoie tout le codebaseclaude --print "Analyse tout le projet"# Bon : cible les fichiers modifiésgit diff --name-only HEAD~1 | xargs -I{} sh -c \'cat {} | claude --print --max-turns 1 "Analyse ce fichier"'# Bon : limite la taille du diffgit diff | head -c 5000 | claude --print --max-turns 2 "Review ce diff"
Prochaines étapes
Combinez le mode headless avec les providers enterprise (Bedrock, Vertex) pour des pipelines CI/CD conformes aux contraintes de données de votre organisation.