Workflow de debug Claude Code : observer, reproduire, corriger, tester
Guide pratique pour debugger avec Claude Code, TypeScript, Node, Vitest, prompts, tests et CTA.
Claude Code peut proposer un correctif plausible depuis une erreur, mais le debug en production demande plus qu’un patch plausible. Une session fiable sépare observation, hypothèse, reproduction minimale, correction et test de régression. Sinon, le bug disparaît sur un écran et revient par une autre entrée, langue ou route de déploiement.
Cet article utilise TypeScript, Node et Vitest. Associez-le à Claude Code and TDD pour conserver la condition qui échoue, à error handling patterns si le modèle d’exception est flou, et à build error triage loop quand la commande de preuve échoue avant le vrai bug.
Donner un ordre d’enquête
Une demande vague comme “corrige cette erreur” pousse Claude Code vers le premier patch raisonnable. Donnez plutôt erreur complète, stack trace, reproduction, forme d’entrée, attendu, réel et fichiers récemment modifiés. Demandez trois hypothèses avant édition.
L’observation garde les faits. L’hypothèse explique une cause possible. La reproduction minimale transforme l’hypothèse en test ou script qui échoue. La correction reste étroite et le test de régression reste dans le dépôt.
{
"name": "claude-debug-lab",
"private": true,
"type": "module",
"scripts": {
"test": "vitest run",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/node": "^22.0.0",
"typescript": "^5.6.0",
"vitest": "^3.0.0"
}
}
Exemple 1 : transformer map undefined en règle
Le premier bug est classique : le code appelle map sur des données pas encore arrivées. Le but n’est pas seulement d’éviter le crash. La règle est qu’un payload absent donne une liste vide, que les noms vides sont retirés et que les noms valides sont trim.
export type User = {
id: string;
name?: string | null;
};
export function normalizeUsers(users: User[] | null | undefined): string[] {
if (!Array.isArray(users)) return [];
return users
.filter((user): user is User & { name: string } => typeof user.name === "string")
.map((user) => user.name.trim())
.filter((name) => name.length > 0);
}
import { describe, expect, it } from "vitest";
import { normalizeUsers } from "../src/normalize-users.js";
describe("normalizeUsers", () => {
it("returns an empty list when the API payload is missing", () => {
expect(normalizeUsers(undefined)).toEqual([]);
expect(normalizeUsers(null)).toEqual([]);
});
it("keeps only usable display names", () => {
expect(
normalizeUsers([
{ id: "u1", name: " Masa " },
{ id: "u2", name: "" },
{ id: "u3", name: null },
]),
).toEqual(["Masa"]);
});
});
Utilisez ce prompt :
Nous voyons Cannot read properties of undefined (reading 'map').
normalizeUsers doit tolérer un payload API absent et retirer les display names vides.
Ajoute d'abord un cas Vitest qui échoue, puis fais le plus petit correctif.
Lance npm test et npm run typecheck à la fin.
Le piège est de s’arrêter à users ?? []. Cela évite le crash mais ne définit pas les noms null, noms vides et payloads non-array. Donnez la règle produit à Claude Code, pas seulement l’exception.
Exemple 2 : retry async sans cacher la dernière erreur
Les bugs de retry async paraissent intermittents. Un bon test vérifie nombre d’appels, attente, succès final et échec total. Si la dernière erreur est cachée, l’incident ne pointe plus vers le service fautif.
type RetryOptions = {
times: number;
delayMs: number;
sleep?: (ms: number) => Promise<void>;
};
const defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
export async function retry<T>(
task: () => Promise<T>,
{ times, delayMs, sleep = defaultSleep }: RetryOptions,
): Promise<T> {
let lastError: unknown;
for (let attempt = 1; attempt <= times; attempt += 1) {
try {
return await task();
} catch (error) {
lastError = error;
if (attempt < times) await sleep(delayMs);
}
}
throw lastError instanceof Error ? lastError : new Error("Retry failed");
}
Quand vous demandez les tests, mentionnez isolation des mocks, pas de grand refactor et conservation de la dernière erreur. Les logs temporaires aident l’enquête, mais doivent disparaître du patch final sauf besoin de logging structuré.
Exemple 3 : reproduire les limites de dates avant de toucher l’UI
Le troisième cas concerne les limites de dates. À l’écran, on voit un export de mars qui oublie les commandes du 31 mars, mais la cause est souvent la comparaison entre le début du mois choisi et le début du mois suivant.
export type Order = {
id: string;
createdAt: string;
total: number;
};
export function exportMonthlyOrderIds(orders: Order[], month: string): string[] {
const [yearText, monthText] = month.split("-");
const year = Number(yearText);
const monthIndex = Number(monthText) - 1;
const start = new Date(Date.UTC(year, monthIndex, 1));
const end = new Date(Date.UTC(year, monthIndex + 1, 1));
return orders
.filter((order) => {
const createdAt = new Date(order.createdAt);
return createdAt >= start && createdAt < end;
})
.map((order) => order.id);
}
import { describe, expect, it } from "vitest";
import { exportMonthlyOrderIds } from "../src/export-orders.js";
describe("exportMonthlyOrderIds", () => {
it("includes orders from the first day through the last moment of the month in UTC", () => {
const orders = [
{ id: "feb-end", createdAt: "2026-02-28T23:59:59.999Z", total: 1000 },
{ id: "mar-start", createdAt: "2026-03-01T00:00:00.000Z", total: 2000 },
{ id: "mar-end", createdAt: "2026-03-31T23:59:59.999Z", total: 3000 },
{ id: "apr-start", createdAt: "2026-04-01T00:00:00.000Z", total: 4000 },
];
expect(exportMonthlyOrderIds(orders, "2026-03")).toEqual(["mar-start", "mar-end"]);
});
});
Demandez à Claude Code d’éviter le parsing dépendant du fuseau local. La règle est simple : inclure le début du mois choisi et exclure le début du mois suivant.
Prompt de debug copiable
Objectif:
Trouver la cause, ajouter un test de régression et corriger avec le plus petit diff utile.
Observations:
- Erreur complète:
- Étapes de reproduction:
- Résultat attendu:
- Résultat réel:
- Fichiers changés récemment:
Contraintes:
- Liste trois hypothèses avant d'éditer.
- Évite les grands refactors.
- Ne cache pas les erreurs de type avec any.
- Retire les logs temporaires à la fin.
- Lance npm test et npm run typecheck à la fin.
Rapport:
- Cause racine
- Fichiers changés
- Test de régression ajouté
- Risques restants
Claude Code devient ainsi un partenaire d’enquête. Le reviewer voit cause, preuve et risque avant tout le diff. En équipe, copiez ces champs dans le review gate pour garder le même standard pour IA et humains.
Debugger sans casser le chemin de revenus
Sur un site public, le debug doit aussi vérifier les CTA. Une correction de contenu peut déplacer le formulaire PDF gratuit, changer un lien Gumroad ou rendre la consultation moins visible. Plus l’article est populaire, plus revenue routing doit faire partie du périmètre.
Utilisez une petite règle :
const debuggingRoutes = {
first_error: "free_pdf",
repeated_bugfixes: "prompt_templates",
setup_or_ci_blocked: "setup_guide",
team_process_blocked: "consultation",
};
export function chooseDebuggingCta(intent) {
return debuggingRoutes[intent] ?? "free_pdf";
}
console.log(chooseDebuggingCta("repeated_bugfixes"));
Le free cheatsheet convient aux débutants et comparateurs. 50 Prompt Templates convient au debug et à la review répétés. Setup Guide convient aux permissions, CI/CD et setup. La consultation convient au rollout équipe et aux décisions d’exploitation.
Vérification de cet article
Cette réécriture garde texte UTF-8 propre, blocs exécutables, liens internes, liens externes et chemin PDF gratuit, Gumroad, consultation. Les prochaines métriques sont inscriptions PDF, clics Prompt Templates, clics Setup Guide et visites Training depuis ce slug.
Note de vérification après publication
Pour un article de debug, ne vous arrêtez pas à la justesse du code. Ouvrez l’URL publique et vérifiez h1, canonical, début du corps, hero image, formulaire PDF gratuit, liens Gumroad et consultation. Sur un article populaire, améliorer le workflow de debug influence directement l’action suivante. Si l’explication est meilleure mais que PDF, Gumroad ou consultation sont faux, le chemin de revenus reste incomplet.
Dans les versions localisées, les exemples de code peuvent être communs, mais l’explication et le CTA doivent être dans la langue cible. Le lecteur doit comprendre observation, reproduction, correctif et test sans changer de langue. En revue screenshot, regardez début du corps, zone prompt et zone CTA.
Les métriques suivantes sont inscriptions PDF, clics Prompt Templates, clics Setup Guide et visites Training depuis ce slug. Les lecteurs debug ont une douleur active, donc le mouvement après l’article compte plus que les PV seules.
PDF gratuit: cheatsheet Claude Code
Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.
Nous protégeons vos données et n'envoyons pas de spam.
À propos de l'auteur
Masa
Ingénieur spécialisé dans les workflows pratiques avec Claude Code.
Articles liés
Workflow Obsidian vers CLAUDE.md avec Claude Code
Transformer des notes Obsidian en notes CLAUDE.md concises pour reprendre les sessions sans réexpliquer.
Claude Code Revenue CTA Routing : relier articles, PDF, Gumroad et consultation
Un workflow Claude Code pour orienter les lecteurs vers PDF gratuit, Gumroad ou consultation selon l'intention.
Règles de handoff Claude Code en équipe: preuves, permissions, rollback et revenus
Un format concret pour transmettre un travail Claude Code avec preuves, permissions, rollback, PDF gratuit, Gumroad et consultation.