Le 11 juin 2025, Anthropic a publié le Claude Code SDK — TypeScript et Python disponibles dès le premier jour. Le principe est simple mais structurant : piloter Claude Code comme n'importe quel subprocess, sans interface graphique, avec des réponses JSON exploitables directement dans tes pipelines. Pour une équipe PHP qui tourne sous Symfony 7.3 et déploie via GitHub Actions, c'est une brique concrète à intégrer aujourd'hui — pas un proof-of-concept de plus à surveiller.
Ce que le SDK change par rapport au CLI classique
Jusqu'ici, appeler claude en ligne de commande et parser sa sortie texte était fragile, imprévisible, impossible à intégrer proprement en CI. Le SDK apporte trois changements qui modifient l'équation :
- Réponses JSON structurées : type, contenu, coût en tokens, statut — tout est parseable sans regex fragile
- Mode subprocess contrôlé : timeout explicite, isolation du processus, exit codes exploitables dans un pipeline
- Intégration MCP native : tes outils maison (lecture base de données, appel Sentry, analyse PHPUnit) sont injectables directement dans le contexte de Claude au moment de l'exécution
Le SDK est disponible en TypeScript via @anthropic-ai/claude-code et en Python via claude-code-sdk. Pour une équipe PHP, le chemin le plus direct passe par Python : un script léger appelé en subprocess depuis Symfony ou depuis un job GitHub Actions. C'est ce montage qu'on détaille ci-dessous.
Revue de PR automatisée : le script Python
Le cas d'usage le plus immédiat est la revue de diff déclenchée à chaque Pull Request. Ce script Python minimal utilise le SDK pour analyser un diff Symfony 7.3 et retourner un JSON directement parseable :
# scripts/claude_review.py
import asyncio
import sys
from claude_code_sdk import query, ClaudeCodeOptions
SYSTEM_PROMPT = """Tu es expert PHP 8.4 / Symfony 7.3.
Analyse le diff fourni. Retourne un JSON avec :
- issues: liste de problèmes (severity, file, line, message)
- summary: résumé en 2 phrases
Réponds uniquement en JSON valide, sans balise markdown."""
async def review_diff(diff: str) -> str:
options = ClaudeCodeOptions(
max_turns=1,
system_prompt=SYSTEM_PROMPT,
)
async for message in query(
prompt=f"Diff à analyser :\n```diff\n{diff}\n```",
options=options,
):
if message.type == "result":
return message.result
return "{}"
if __name__ == "__main__":
diff_content = sys.stdin.read()
print(asyncio.run(review_diff(diff_content)))Côté PHP, le composant Process de Symfony suffit pour appeler le script et consommer la sortie — sans aucune dépendance supplémentaire :
Votre équipe utilise Claude Code ?
Découvrir le workshop →<?php
// src/Service/CodeReviewService.php
namespace App\Service;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
final class CodeReviewService
{
public function reviewDiff(string $diff): array
{
$process = new Process(
command: ['python3', 'scripts/claude_review.py'],
timeout: 120,
input: $diff,
);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
return json_decode(
$process->getOutput(),
associative: true,
flags: JSON_THROW_ON_ERROR
);
}
}Pipeline GitHub Actions complet pour un projet Symfony
Ce job s'ajoute proprement à ton workflow existant. Il génère le diff entre la branche courante et main, lance la revue Claude, puis publie le résultat en commentaire de PR via actions/github-script :
# .github/workflows/claude-review.yml
name: Claude Code PR Review
on:
pull_request:
types: [opened, synchronize]
jobs:
claude-review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Claude Code SDK
run: pip install claude-code-sdk
- name: Generate diff
id: diff
run: |
git diff origin/${{ github.base_ref }}...HEAD -- '*.php' > /tmp/pr.diff
echo "diff_size=$(wc -c < /tmp/pr.diff)" >> "$GITHUB_OUTPUT"
- name: Run Claude review
if: steps.diff.outputs.diff_size != '0'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: python3 scripts/claude_review.py < /tmp/pr.diff > review.json
- name: Post review comment
if: steps.diff.outputs.diff_size != '0'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = JSON.parse(fs.readFileSync('review.json', 'utf8'));
const lines = (review.issues ?? []).map(i =>
`- **${i.severity}** \`${i.file}:${i.line}\` — ${i.message}`
);
const body = `### Revue Claude Code\n\n${review.summary}\n\n${lines.join('\n')}`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});Ce que ça vaut vraiment en pratique
Le SDK est utile, pas magique. Deux points de vigilance immédiats. Premier : le coût en tokens monte vite sur des diffs volumineux — filtrer sur *.php uniquement (comme dans le YAML ci-dessus) et limiter la taille en amont est indispensable pour garder le budget prévisible. Deuxième : la cohérence du JSON de sortie dépend entièrement de la solidité du system prompt — un JSON_THROW_ON_ERROR strict côté PHP et un fallback explicite évitent d'ignorer silencieusement une réponse malformée.
Le vrai gain n'est pas la qualité de la revue en elle-même — un senior reste meilleur sur le domaine métier. C'est la reproductibilité : la même analyse, versionnée dans le dépôt, rejouable sur n'importe quelle branche, déclenchable depuis un Makefile ou un webhook. Elle s'intègre exactement comme phpstan ou php-cs-fixer — et peut être remplacée ou améliorée sans toucher à l'architecture CI.
Tu veux aller plus loin et connecter Claude Code à tes outils internes via MCP — lecture du schéma Doctrine, remontée d'erreurs Sentry, analyse de couverture PHPUnit — pour que la revue soit vraiment contextualisée à ton projet ? C'est exactement ce qu'on couvre dans le Workshop Claude Code : une demi-journée pratique pour équiper ton équipe, choisir les bons modèles (Sonnet 4 ou Opus 4 selon l'usage) et tenir le budget sous contrôle dès le premier sprint.
Votre équipe utilise Claude Code ?
Workshop intensif : votre équipe opérationnelle en 1 jour.