Mode headless de Claude Code : claude -p en script et CI

Le mode headless de Claude Code expliqué : claude -p, sorties JSON et stream-json, --allowedTools, --max-turns, --bare, reprise de sessions, pipes, cron et CI.

Solviera Teknoloji 10 min de lecture

Le mode headless de Claude Code, c’est l’option -p. claude -p "votre prompt" lance Claude Code une fois sans l’interface interactive : il lit votre prompt (et tout ce que vous lui envoyez par un pipe), travaille avec les outils que vous autorisez, affiche le résultat et s’arrête. Le code de sortie 0 signifie un succès, tout autre code un échec. Cela en fait un outil en ligne de commande ordinaire, que vous pouvez placer dans des scripts shell, des tâches cron, des hooks git et des pipelines CI.

Ce guide couvre les options que vous utiliserez vraiment : formats de sortie, permissions des outils, limites de tours et de budget, --bare, poursuite de sessions et envoi de données par pipe, puis des patterns prêts à l’emploi pour les scripts, cron et la CI, et le moment de passer à l’Agent SDK. Chaque option citée ici a été vérifiée dans la référence officielle du CLI telle qu’elle était en octobre 2026.

Les bases

claude -p "What does the auth module do?"

-p et --print sont la même option. La plupart des options interactives s’y combinent, comme --model, --effort, --append-system-prompt et --mcp-config. Quelques options n’existent qu’en mode print, parmi lesquelles --max-turns, --max-budget-usd, --json-schema et --no-session-persistence.

Deux détails comptent pour les scripts :

  • Si vous passez une option invalide, l’erreur part sur stderr avant le début de l’exécution.
  • Si quelque chose échoue pendant l’exécution, par exemple une authentification manquante, l’échec est affiché comme résultat sur stdout. Vérifiez le code de sortie, pas seulement la sortie.

Envoyer des données en entrée, rediriger les résultats

Le mode headless lit stdin, donc les logs, les diffs et les fichiers arrivent comme avec n’importe quel outil Unix :

cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt
git diff main | claude -p "Review this diff for bugs. List each as file:line and one sentence."

L’entrée stdin par pipe est plafonnée à 10 Mo. Au-delà, Claude Code sort avec une erreur ; pour les grosses entrées, écrivez donc le contenu dans un fichier et nommez son chemin dans le prompt.

Vous pouvez aussi le brancher dans package.json, comme le fait la documentation officielle avec un linter de fautes de frappe :

{
  "scripts": {
    "lint:claude": "git diff main | claude -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
  }
}

Choisir un format de sortie

--output-format accepte trois valeurs :

FormatCe que vous obtenezÀ utiliser pour
text (par défaut)La réponse finale en texte brutHumains, fichiers, scripts simples
jsonUn seul objet JSON à la finScripts qui ont besoin de la réponse et des métadonnées
stream-jsonUn événement JSON par ligne, au fil de l’eauProgression en direct, interfaces sur mesure, journalisation

L’objet JSON contient la réponse dans result, plus session_id, des chiffres d’usage et total_cost_usd. Ce coût est une estimation côté client et peut différer de votre facture.

claude -p "Summarize this project" --output-format json | jq -r '.result'

Sortie structurée avec —json-schema

Quand un script a besoin de données plutôt que de prose, passez un JSON Schema. Le résultat validé arrive dans structured_output :

claude -p "Extract the main function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'

Si l’exécution se termine sans sortie structurée valide, par exemple parce que Claude a refusé, le champ est absent. Vérifiez sa présence avant de l’utiliser :

out=$(claude -p "Extract the main function names from auth.py" --output-format json --json-schema "$(cat schema.json)")
echo "$out" | jq -e '.structured_output' > /dev/null || { echo "no structured output" >&2; exit 1; }

Événements en streaming

stream-json exige --verbose. Ajoutez --include-partial-messages pour recevoir les tokens au fur et à mesure qu’ils sont générés. Ceci n’affiche que le texte en streaming :

claude -p "Write a poem" --output-format stream-json --verbose --include-partial-messages | \
  jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

Le premier événement est normalement system/init, avec le modèle, les outils, les serveurs MCP et les plugins. La dernière ligne est un message result avec le texte final, le coût et les métadonnées de session. Les nouvelles tentatives apparaissent sous forme d’événements system/api_retry. Un contrôle utile en CI : quand vous passez --mcp-config, une entrée de serveur dont la validation échoue est ignorée sans faire échouer l’exécution, et elle apparaît dans mcp_server_errors sur l’événement init. Faites échouer le job si ce tableau n’est pas vide.

Contrôler ce que l’exécution a le droit de faire

Dans un script, personne n’est là pour répondre à une demande de permission ; décidez donc à l’avance ce que Claude peut faire.

--allowedTools pré-approuve des outils avec la syntaxe des règles de permission :

claude -p "Look at my staged changes and create an appropriate commit" \
  --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"

L’espace avant * compte : Bash(git diff *) correspond aux commandes qui commencent par git diff, alors que Bash(git diff*) correspondrait aussi à git diff-index.

--permission-mode fixe le comportement de base pour tout ce qui n’est pas listé. En octobre 2026 (Claude Code v2.1.302 et versions suivantes), une exécution -p démarre en mode Manual quand rien ne fixe de mode, et un appel qui demande une approbation est refusé. Valeurs utiles :

ModeComportement dans une exécution headless
dontAskTout ce qui n’est pas pré-approuvé est refusé. Le choix prévisible pour les scripts
acceptEditsLes modifications de fichiers sont autorisées sans demander
planLecture et planification uniquement, aucune modification
autoUn classifieur examine chaque action ; un blocage refuse cette action et l’exécution continue
bypassPermissionsAucun contrôle. Uniquement dans un conteneur ou une VM jetable

--tools restreint les outils intégrés qui existent tout court, et --disallowedTools ajoute des règles deny. --permission-prompts none indique à Claude que personne ne peut approuver les demandes, pour qu’il ne les retente pas sans fin ; les refus sont listés dans permission_denials sur le résultat final. Pourquoi contourner les permissions sur votre propre machine est risqué est expliqué dans Claude Code et —dangerously-skip-permissions.

Fixer des limites à chaque exécution sans surveillance

  • --max-turns 20 s’arrête après ce nombre de tours agentiques et sort avec une erreur. Pas de limite par défaut.
  • --max-budget-usd 5.00 s’arrête quand la dépense estimée atteint ce montant. Il s’appuie sur l’estimation côté client et la dépense peut légèrement dépasser le plafond, donc gardez de la marge.
  • timeout, côté shell ou étape de CI, reste utile. Si vous arrêtez une exécution avec SIGTERM, Claude Code sort avec le code 143, n’enregistre aucun résultat pour le tour inachevé et lance quand même les hooks SessionEnd.

Utiliser —bare pour des exécutions reproductibles

Sans --bare, claude -p charge les mêmes éléments qu’une session interactive : hooks, skills, plugins, serveurs MCP, mémoire automatique et CLAUDE.md, depuis le dossier de travail et depuis ~/.claude. La même commande se comporte donc différemment sur votre portable et sur un runner de CI.

claude --bare -p "Summarize README.md" --allowedTools "Read"

--bare saute toute cette découverte et démarre plus vite. Vous ne passez que ce dont l’exécution a besoin :

À chargerOption
Instructions supplémentaires--append-system-prompt, --append-system-prompt-file
Réglages--settings <file-or-json>
Serveurs MCP--mcp-config <file-or-json>
Agents personnalisés--agents <file-or-json>
Un plugin--plugin-dir <path>

Le mode bare ne lit jamais les identifiants OAuth ni le trousseau du système. Avec l’API Anthropic, définissez ANTHROPIC_API_KEY ou fournissez un apiKeyHelper dans le JSON de --settings. La documentation officielle recommande --bare pour les appels scriptés et indique qu’il deviendra le comportement par défaut de -p dans une future version ; l’écrire explicitement dès maintenant garde vos scripts stables le jour où cela arrivera.

Une raison de plus d’y prêter attention : sans --bare, une exécution -p dans un dépôt fraîchement cloné lance les hooks de projet et les serveurs .mcp.json de ce dépôt sans boîte de dialogue de confiance. Ne lancez pas une exécution headless sans --bare sur du code que vous n’avez pas relu.

Poursuivre et reprendre des sessions

Les exécutions headless sont enregistrées comme les sessions interactives, vous pouvez donc enchaîner les étapes :

# First request
claude -p "Review this codebase for performance issues"

# Continue the most recent conversation
claude -p "Now focus on the database queries" --continue
claude -p "Generate a summary of all issues found" --continue

Quand plusieurs exécutions ont lieu en même temps, --continue peut choisir la mauvaise. Récupérez plutôt l’ID de session :

session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"

--resume retrouve la session par son ID depuis n’importe quel dossier de la machine, et accepte aussi un nom ou le chemin du transcript .jsonl d’une session. --fork-session démarre une nouvelle branche à partir de la conversation reprise au lieu de la prolonger, et --no-session-persistence évite d’enregistrer les exécutions ponctuelles.

Patterns pour les scripts, cron et la CI

Une boucle sur des fichiers

La page officielle des bonnes pratiques propose un bon modèle pour un changement mécanique sur de nombreux fichiers :

for file in $(cat files.txt); do
  claude --bare -p "Migrate $file to the new logger API and commit. Reply OK or FAIL." \
    --allowedTools "Read,Edit,Bash(git add *),Bash(git commit *)" \
    --permission-mode dontAsk \
    --max-turns 20
done

Lancez-le d’abord sur trois fichiers, lisez les commits, corrigez le prompt, puis lancez le reste. Une exécution qui atteint la limite de tours sort avec une erreur, que votre boucle peut journaliser.

Un script de revue

gh pr diff "$1" | claude -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json

Enregistrez-le sous review.sh et lancez bash review.sh 123 ; le texte de la revue est dans result.

Une tâche cron de nuit

# crontab -e
0 2 * * * cd /srv/app && claude --bare -p "Run the test suite, fix failing tests, commit on the current branch. Do not push." --allowedTools "Read,Edit,Bash(npm test *),Bash(git add *),Bash(git commit *)" --permission-mode dontAsk --max-turns 30 --output-format json >> /var/log/claude-nightly.jsonl 2>> /var/log/claude-nightly.err

Cron tourne avec un environnement minimal : assurez-vous que claude est dans son PATH et que ANTHROPIC_API_KEY est défini pour cet utilisateur. Lancez-le sur une branche ou dans un worktree, pas sur main. Si vous ajoutez --worktree, notez que les exécutions -p --worktree ne sont pas nettoyées pour vous ; supprimez-les avec git worktree remove <path>. Pour la configuration complète de nuit avec budgets et relecture le matin, voir Lancer Claude Code la nuit, et pour les minuteurs de chaque système, Planifier des tâches Claude Code.

Pipelines CI

En CI, utilisez --bare, gardez la clé API dans le gestionnaire de secrets de la CI et traitez le code de sortie comme le résultat de l’étape. Pour GitHub en particulier, l’action officielle s’en charge pour vous, avec des commentaires de PR et des mentions @claude : voir Claude Code GitHub Actions. Si vous utilisez un abonnement plutôt qu’une clé API, claude setup-token affiche un token OAuth longue durée pour la CI et les scripts ; il n’est pas enregistré, stockez-le donc tout de suite comme secret. N’oubliez pas que --bare ignore OAuth : un token d’abonnement exige une exécution sans --bare.

Pièges

  • Skills et commandes slash. Les skills utilisateur fonctionnent si vous mettez /skill-name dans le prompt. Les commandes qui n’existent que dans l’interface du terminal, comme /login, ne fonctionnent pas.
  • Refus d’outils silencieux. Si Claude dit qu’il n’a pas pu faire quelque chose, regardez permission_denials dans le résultat JSON et ajoutez la règle manquante à --allowedTools.
  • Travail en arrière-plan. Une exécution -p peut rester ouverte pour attendre des commandes en arrière-plan ou des subagents lancés par Claude ; par défaut, elle cesse d’attendre après 10 minutes d’inactivité.
  • Remplacer le prompt système. --system-prompt remplace entièrement le prompt par défaut, y compris l’instantané du statut git. Préférez --append-system-prompt, sauf si vous voulez vraiment partir d’une page blanche.

Quand passer à l’Agent SDK

claude -p, c’est le moteur de l’Agent SDK derrière un CLI. Dès que votre script commence à analyser des flux, à gérer des approbations ou à piloter de nombreuses sessions, passez à l’Agent SDK pour Python ou TypeScript. Il vous donne des objets message natifs, des callbacks d’approbation des outils et des sorties structurées directement dans le code, sans passer par le shell. L’article Bonnes pratiques Claude Code couvre ce qu’il faut mettre en place avant de laisser tourner une exécution sans surveillance.

Avec AgentVera

Les exécutions headless se lancent et s’oublient ; parfois, vous voulez la même automatisation avec un terminal que vous pouvez regarder. Dans AgentVera, les tâches planifiées (sur toutes les offres) envoient un prompt à un agent selon un planning cron pendant que l’application est ouverte, et l’agent tourne dans un vrai volet que vous pouvez ouvrir et réorienter. Les automatisations (Pro et Team) lancent un agent quand la CI passe au rouge ou qu’une PR reçoit un commentaire, et ne poussent jamais sur la branche par défaut. Le centre CI/CD liste les exécutions GitHub Actions, GitLab et Jenkins et peut confier un log en échec à un agent. Night shift (Pro et Team) exécute le travail en file pendant la nuit dans un worktree sur une branche night/<date>-<slug>, committe sans pousser et laisse un rapport le matin. Téléchargez AgentVera si vous voulez voir ces exécutions au lieu de les enfouir dans un fichier de log.

En résumé

La recette de base du Claude Code headless est courte : claude --bare -p "clear task with a check", une liste --allowedTools explicite, --permission-mode dontAsk, --max-turns, --output-format json, et un code de sortie que votre script respecte. Commencez petit, lisez ce que produisent les premières exécutions, et seulement ensuite mettez-le sur un minuteur.

Questions

Qu’est-ce que le mode headless de Claude Code ?

C’est Claude Code lancé de façon non interactive avec l’option -p (ou --print). Vous passez un prompt, Claude fait le travail avec les outils que vous autorisez, affiche le résultat sur stdout et s’arrête. Le code de sortie 0 signifie un succès et un code non nul un échec, donc les scripts peuvent s’appuyer dessus.

Comment laisser claude -p modifier des fichiers sans demander ?

Listez les outils avec --allowedTools, par exemple --allowedTools "Read,Edit,Bash(npm test *)". En octobre 2026, les exécutions -p démarrent en mode Manual quand rien ne fixe de mode, et les appels d’outils qui demandent une approbation sont refusés. Ajoutez --permission-mode dontAsk pour le rendre explicite, ou acceptEdits pour autoriser toutes les modifications de fichiers.

Comment obtenir une sortie JSON de Claude Code ?

Ajoutez --output-format json. La réponse est un seul objet JSON avec la réponse dans result, plus session_id, usage et une estimation total_cost_usd. Passez-la à jq -r ".result" pour obtenir le texte. Ajoutez --json-schema pour obtenir des données validées dans structured_output, et vérifiez que le champ existe avant de l’utiliser.

Peut-on poursuivre une session headless de Claude Code ?

Oui. claude -p "étape suivante" --continue reprend la conversation la plus récente du dossier courant. Pour en cibler une précise, récupérez session_id depuis une exécution JSON et passez-le à --resume ; Claude Code retrouve la session par son ID depuis n’importe quel dossier de cette machine.

Le mode headless utilise-t-il mon abonnement Claude ou une clé API ?

Une exécution -p normale utilise la connexion présente sur la machine. Avec --bare, Claude Code ne lit jamais les identifiants OAuth ni le trousseau, il lui faut donc ANTHROPIC_API_KEY ou un apiKeyHelper dans le JSON de --settings. Pour la CI avec un abonnement, claude setup-token génère un token OAuth longue durée.

Réunissez vos agents sur un seul bureau.

Téléchargez AgentVera gratuitement ; vos CLI installées sont prêtes à l’emploi.

Autres articles