Build This Now
Build This Now
Raccourcis clavierGuide de la Status Line
Guide des HooksHooks cross-platform pour Claude CodeHooks de configuration Claude CodeStop HooksAgents Claude Code Auto-ValidantsHooks de Cycle de Vie de Session Claude CodeHooks de sauvegarde de contexte pour Claude CodeHook d'activation des skillsHook de Permission Claude Code
speedy_devvkoen_salo
Blog/Toolkit/Hooks/Cross-Platform Hooks for Claude Code

Hooks cross-platform pour Claude Code

Hooks Claude Code cross-platform : supprime les wrappers .cmd, .sh et .ps1 et invoque node directement pour qu'un seul fichier .mjs tourne sur macOS, Linux et Windows dans toute l'équipe.

Arrêtez de configurer. Commencez à construire.

Templates SaaS avec orchestration IA.

Published Jan 16, 2026Toolkit hubHooks index

Problème : un hook que tu as livré depuis Windows via cmd /c ou PowerShell passe au rouge dès qu'un coéquipier Linux ouvre le repo. La solution de contournement sur laquelle la plupart des gens atterrissent est moche. Trois scripts shim par hook : un .cmd pour Windows, un .sh pour Linux, un .ps1 pour PowerShell. Les trois font exactement la même chose, c'est-à-dire appeler le fichier .mjs qui compte vraiment.

Solution rapide : jette les wrappers. Pointe la config du hook directement sur Node.js :

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/formatter.mjs"
          }
        ]
      }
    ]
  }
}

Tourne sur Windows, Linux et macOS sans modification. node est toujours dans le $PATH parce que Claude Code liste Node.js comme dépendance obligatoire.

Pourquoi les hooks cassent quand l'OS change

Si personne d'autre ne touche ton setup, rien de tout ça ne te mord. Le problème commence dès que .claude/settings.json est partagé, que le repo devient public, ou que tu alternes entre une tour Windows et un laptop macOS. Dès que bash ou powershell apparaît dans une commande, la moitié de l'équipe ne peut pas l'exécuter.

La plupart des tutoriels sont de toute façon spécifiques à une plateforme :

// Windows-only
"command": "cmd /c \".claude\\hooks\\formatter.cmd\""
 
// Linux-only
"command": "bash .claude/hooks/formatter.sh"
 
// PowerShell-only
"command": "powershell -NoProfile -File .claude/hooks/statusline.ps1"

Chacun de ces wrappers est deux lignes de boilerplate autour d'un appel node. Trois fichiers, trois plateformes, même boulot sur toutes. Si la seule couche qui connaît l'OS est le shim, tu peux supprimer le shim.

Le pattern universel dans settings.json

Les hooks dans settings.json partagent une seule forme :

{
  "statusLine": {
    "type": "command",
    "command": "node .claude/hooks/statusline-monitor.mjs"
  },
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/skill-activation.mjs"
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/backup.mjs",
            "async": true
          }
        ]
      }
    ]
  }
}

Pas de cmd /c. Pas de bash. Pas de powershell. Juste node. Chaque type de hook prend la même forme, donc PostToolUse, SessionStart/SessionEnd, Stop, et les 12 événements du cycle de vie se câblent de façon identique.

Trois règles pour une logique de hook cross-platform

Dans chaque fichier .mjs, trois habitudes gardent la logique portable quel que soit l'OS qui finit par l'exécuter.

Utilise os.homedir() plutôt que les variables de plateforme

import { homedir } from "os";
import { join } from "path";
 
// Cross-platform: resolves to C:\Users\you or /home/you
const settingsPath = join(homedir(), ".claude", "settings.json");

Garde $HOME, $env:USERPROFILE, et %USERPROFILE% hors du code source. Laisse le helper choisir le bon.

Utilise os.tmpdir() pour les chemins de fichiers temporaires

import { tmpdir } from "os";
import { join } from "path";
 
// Cross-platform: resolves to C:\Users\you\AppData\Local\Temp or /tmp
const cacheFile = join(tmpdir(), "my-hook-cache.json");

Ne va pas chercher /tmp ou $env:TEMP à la main.

Utilise path.join() pour toute construction de chemin de fichier

import { join } from "path";
 
// Cross-platform path construction
const logFile = join(".claude", "hooks", "logs", "hook.log");

Arrête de coller des chemins ensemble avec / ou \\ à la main. Node.js connaît déjà le bon séparateur pour l'OS sur lequel le hook atterrit.

Permissions qui couvrent les deux plateformes

Le bloc permissions dans settings.json doit contenir le nom Windows et le nom Unix côte à côte :

{
  "permissions": {
    "allow": [
      "Bash(where:*)",
      "Bash(which:*)",
      "Bash(tasklist:*)",
      "Bash(ps:*)",
      "Bash(taskkill:*)",
      "Bash(kill:*)",
      "Bash(findstr:*)",
      "Bash(node:*)"
    ]
  }
}

Quelle que soit la commande qui n'est pas installée sur la machine actuelle, elle reste silencieuse. Lister les deux ne coûte rien, et ton hook choisit celle qui existe vraiment sans déclencher de dialog de permission. Pour une automatisation plus poussée de ce côté, consulte le guide Permission Hook.

Exemple complet : logger de fichiers cross-platform

Un hook complet, portable tel quel. Le boulot est un logger de fichiers. Chaque écriture ou modification que Claude effectue est ajoutée à un log :

#!/usr/bin/env node
import { readFileSync, appendFileSync, mkdirSync } from "fs";
import { join } from "path";
 
const logDir = join(".claude", "hooks", "logs");
mkdirSync(logDir, { recursive: true });
 
try {
  const input = JSON.parse(readFileSync(0, "utf-8"));
  const toolName = input.tool_name;
  const filePath = input.tool_input?.file_path || "unknown";
  const timestamp = new Date().toISOString();
 
  appendFileSync(
    join(logDir, "file-changes.log"),
    `${timestamp} | ${toolName} | ${filePath}\n`,
  );
} catch {
  // Silent fail -- don't block Claude
}
 
process.exit(0);

Enregistre-le dans ton settings.json :

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/file-logger.mjs"
          }
        ]
      }
    ]
  }
}

Même comportement sur Windows 11, Arch Linux, et macOS Sequoia. Zéro wrapper.

Déboguer quand un OS casse

Tu as un hook qui tourne sur une machine et échoue sur l'autre ? Parcours cette liste de haut en bas :

  1. Séparateurs de chemin codés en dur. Cherche dans chaque fichier .mjs les / ou \\ qui apparaissent dans un chemin. Passe ces cas à path.join().
  2. Références à des variables d'environnement. Cherche process.env.HOME, process.env.USERPROFILE, ou process.env.TEMP et remplace chacun par os.homedir() ou os.tmpdir().
  3. Commandes spécifiques à un shell dans settings.json. Toute entrée command qui mentionne bash, cmd, powershell, ou sh casse partout sauf sur son OS natal. Pointe sur node.

Déclenche le hook manuellement pour que l'échec ne puisse pas se cacher :

echo '{"tool_name":"Write","tool_input":{"file_path":"test.js"}}' | node .claude/hooks/your-hook.mjs
echo $?  # Should output 0

Un 0 sur un OS et autre chose sur l'autre te pointe vers la gestion des chemins dans le fichier .mjs, jamais vers l'entrée du hook dans les settings.

Checklist de mise en production

Parcours cette liste avant un déploiement en équipe ou une mise en production publique :

  • Chaque command dans settings.json pointe vers node, pas cmd, powershell, ou bash
  • Les répertoires home viennent de os.homedir(), jamais de $HOME ou %USERPROFILE%
  • Les chemins temporaires viennent de os.tmpdir(), jamais de /tmp ou $env:TEMP
  • Les chemins sont construits avec path.join(), pas des séparateurs tapés à la main
  • Les permissions listent les équivalents Windows et Unix
  • La commande statusLine se résout vers node, pas powershell

Un fichier. Trois plateformes. Zéro maintenance.

Est-ce que les hooks Claude Code fonctionnent sur Windows ?

Oui. Appelle-les via node plutôt qu'un shell qui ne vit que sur un OS, et ils tournent pareil sur Windows, Linux et macOS. Node.js est une dépendance obligatoire de Claude Code sur toutes les plateformes, donc node est toujours dans le $PATH. Mets node .claude/hooks/your-hook.mjs dans settings.json et tu obtiens un comportement identique sur les trois.

Puis-je utiliser Python plutôt que Node.js pour les hooks ?

Python fonctionne aussi, à condition que chaque coéquipier ait déjà un interpréteur sur sa machine. Dans le champ command, utilise python3 plutôt que python, parce que certaines distros Linux ne livrent jamais un simple python. Node.js reste le choix le plus sûr : Claude Code le garantit sur toutes les plateformes, Python non.

Comment gérer les fins de ligne entre plateformes ?

Tu n'as généralement pas à le faire. readFileSync et writeFileSync normalisent déjà les fins de ligne. Chaque hook lit du JSON depuis stdin, et le parser JSON ne se soucie pas de savoir si les retours à la ligne sont CRLF ou LF. L'exception est un hook qui génère son propre script shell. Pour ce cas, écris \n et laisse le reste au paramètre autocrlf de Git.

Continue in Hooks

  • Hooks de configuration Claude Code
    Assemble scripts, agents et docs dans des hooks de configuration Claude Code. Une commande lance un script déterministe, passe la sortie à un agent de diagnostic, et journalise une doc vivante.
  • Hooks de sauvegarde de contexte pour Claude Code
    Un hook de sauvegarde de contexte Claude Code piloté par StatusLine. Écrit des snapshots structurés toutes les 10K tokens pour que la compaction automatique ne mange jamais les erreurs, signatures et décisions.
  • Guide des Hooks
    Les hooks Claude Code depuis les bases : codes de sortie, sortie JSON, commandes asynchrones, endpoints HTTP, matchers PreToolUse et PostToolUse, patterns de production.
  • Hook de Permission Claude Code
    Installe un hook de permission Claude Code à trois niveaux : approbation instantanée pour les appels sûrs, refus instantané pour les dangereux, vérification LLM pour la zone grise. Sans flag skip.
  • Agents Claude Code Auto-Validants
    Agents Claude Code auto-validants : câble des hooks lint PostToolUse, des hooks Stop, et des sous-agents réviseurs en lecture seule dans les définitions d'agents pour que le mauvais code ne soit jamais livré.
  • Hooks de Cycle de Vie de Session Claude Code
    Quatre hooks de cycle de vie de session Claude Code : lance init à la demande, injecte le contexte du projet au SessionStart, sauvegarde les transcripts, et journalise le nettoyage à la sortie SessionEnd.

More from Toolkit

  • Raccourcis clavier
    Configurer keybindings.json dans Claude Code : 17 contextes, syntaxe des touches, séquences d'accords, combinaisons de modificateurs, et comment désactiver n'importe quel raccourci par défaut instantanément.
  • Guide de la Status Line
    Configure une status line Claude Code affichant le nom du modèle, la branche git, le coût de session et l'utilisation du contexte. Config settings.json, JSON d'entrée, scripts bash, Python, Node.js.
  • SEO IA et optimisation GEO
    Un tour d'horizon de la Generative Engine Optimization : comment faire citer ton contenu dans les réponses de ChatGPT, Claude et Perplexity plutôt que simplement classé sur Google.
  • Claude Code vs Cursor en 2026
    Une comparaison côte à côte de Claude Code et Cursor en 2026 : modèles d'agents, fenêtres de contexte, niveaux de prix, et comment chaque outil s'adapte aux différents workflows des développeurs.

Arrêtez de configurer. Commencez à construire.

Templates SaaS avec orchestration IA.

On this page

Pourquoi les hooks cassent quand l'OS change
Le pattern universel dans settings.json
Trois règles pour une logique de hook cross-platform
Utilise os.homedir() plutôt que les variables de plateforme
Utilise os.tmpdir() pour les chemins de fichiers temporaires
Utilise path.join() pour toute construction de chemin de fichier
Permissions qui couvrent les deux plateformes
Exemple complet : logger de fichiers cross-platform
Déboguer quand un OS casse
Checklist de mise en production
Est-ce que les hooks Claude Code fonctionnent sur Windows ?
Puis-je utiliser Python plutôt que Node.js pour les hooks ?
Comment gérer les fins de ligne entre plateformes ?

Arrêtez de configurer. Commencez à construire.

Templates SaaS avec orchestration IA.