Build This Now
Build This Now
TastenkürzelStatus Line Guide
Hooks-LeitfadenPlattformübergreifende Hooks für Claude CodeClaude Code Setup-HooksStop HooksSelbstvalidierende Claude Code AgentenClaude Code Session-HooksKontext-Backup-Hooks für Claude CodeSkill-Aktivierungs-HookClaude Code Permission-Hook
speedy_devvkoen_salo
Blog/Toolkit/Hooks/Cross-Platform Hooks for Claude Code

Plattformübergreifende Hooks für Claude Code

Plattformübergreifende Claude Code Hooks: Vermeide .cmd-, .sh- und .ps1-Wrapper und rufe node direkt auf, damit eine .mjs-Datei auf macOS, Linux und Windows im Team funktioniert.

Hören Sie auf zu konfigurieren. Fangen Sie an zu bauen.

SaaS-Builder-Vorlagen mit KI-Orchestrierung.

Published Jan 16, 2026Toolkit hubHooks index

Problem: Ein Hook, den du von Windows via cmd /c oder PowerShell ausgeliefert hast, leuchtet rot, sobald ein Linux-Teamkollege das Repo öffnet. Die Lösung, auf die die meisten landen, ist hässlich. Drei Shim-Skripte pro Hook: ein .cmd für Windows, ein .sh für Linux, ein .ps1 für PowerShell. Alle drei machen genau dasselbe: die .mjs-Datei aufrufen, die eigentlich zählt.

Schneller Gewinn: Wirf die Wrapper weg. Zeige die Hook-Konfiguration direkt auf Node.js:

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

Läuft auf Windows, Linux und macOS ohne Änderungen. node ist immer im $PATH, weil Claude Code Node.js als feste Voraussetzung listet.

Warum Hooks brechen, wenn sich das OS ändert

Wenn niemand sonst dein Setup anfasst, beißt dich das nie. Ärger beginnt in dem Moment, wo .claude/settings.json geteilt wird, das Repo öffentlich wird oder du zwischen einem Windows-Tower und einem macOS-Laptop wechselst. Sobald bash oder powershell in einem Befehl auftaucht, kann die Hälfte des Teams ihn nicht ausführen.

Die meisten Tutorials gehen sowieso plattformspezifisch vor:

// 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"

Jeder dieser Wrapper besteht aus zwei Zeilen Boilerplate um einen node-Aufruf. Drei Dateien, drei Plattformen, gleicher Job auf allen. Wenn die einzige Schicht, die das OS kennt, der Shim ist, kannst du den Shim löschen.

Das universelle Muster in settings.json

Hooks innerhalb von settings.json teilen eine Form:

{
  "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
          }
        ]
      }
    ]
  }
}

Kein cmd /c. Kein bash. Kein powershell. Nur node. Jeder Hook-Typ nimmt dieselbe Form an, also PostToolUse, SessionStart/SessionEnd, Stop und alle 12 Lifecycle-Events werden identisch verdrahtet.

Drei Regeln für plattformübergreifende Hook-Logik

Innerhalb jeder .mjs-Datei halten drei Gewohnheiten die Logik portabel, egal welches OS sie ausführt.

Verwende os.homedir() statt Plattform-Variablen

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");

Halte $HOME, $env:USERPROFILE und %USERPROFILE% aus dem Quellcode. Lass den Helper die richtige wählen.

Verwende os.tmpdir() für temporäre Dateipfade

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");

Greif nicht von Hand nach /tmp oder $env:TEMP.

Verwende path.join() für alle Dateipfad-Konstruktionen

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

Hör auf, Pfade mit / oder \\ von Hand zusammenzukleben. Node.js kennt bereits den richtigen Separator für das OS, auf dem der Hook landet.

Berechtigungen, die beide Plattformen abdecken

Der permissions-Block in settings.json sollte den Windows-Namen und den Unix-Namen nebeneinander enthalten:

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

Welcher Befehl auch immer nicht auf dem aktuellen Rechner installiert ist, bleibt still. Beide aufzulisten kostet nichts, und dein Hook nimmt den, der tatsächlich existiert, ohne einen Berechtigungs-Dialog auszulösen. Für tiefere Automatisierung auf dieser Seite, lies den Permission-Hook-Leitfaden.

Vollständiges Beispiel: Plattformübergreifender Datei-Logger

Ein vollständiger Hook, portabel wie er ist. Die Aufgabe ist ein Datei-Logger. Jeder Write oder Edit, den Claude ausführt, wird an ein Log angehängt:

#!/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);

Registriere ihn in deiner settings.json:

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

Gleiches Verhalten auf Windows 11, Arch Linux und macOS Sequoia. Null Wrapper.

Debuggen, wenn ein OS bricht

Hast du einen Hook, der auf einem Rechner läuft und auf dem nächsten fehlschlägt? Geh diese Liste von oben nach unten durch:

  1. Hardcodierte Pfad-Trennzeichen. Durchsuche jede .mjs-Datei nach / oder \\ innerhalb eines Pfades. Übergib diese Fälle an path.join().
  2. Umgebungsvariablen-Referenzen. Suche nach process.env.HOME, process.env.USERPROFILE oder process.env.TEMP und tausche jeden gegen os.homedir() oder os.tmpdir() aus.
  3. Shell-spezifische Befehle in settings.json. Jeder command-Eintrag, der bash, cmd, powershell oder sh erwähnt, bricht überall außer seinem Heim-OS. Zeige es auf node.

Führe den Hook manuell aus, damit der Fehler sich nicht verstecken kann:

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

Eine 0 auf einem OS und etwas anderes auf dem nächsten zeigt auf die Pfad-Behandlung in der .mjs-Datei, nie auf den Hook-Eintrag in settings.

Release-Checkliste

Geh diese Liste durch, bevor du ein Team-Rollout oder ein öffentliches Release machst:

  • Jeder command in settings.json zeigt auf node, nicht auf cmd, powershell oder bash
  • Home-Verzeichnisse kommen aus os.homedir(), nie aus $HOME oder %USERPROFILE%
  • Temporäre Pfade kommen aus os.tmpdir(), nie aus /tmp oder $env:TEMP
  • Pfade werden mit path.join() gebaut, nicht mit hand-getippten Trennzeichen
  • Berechtigungen listen sowohl Windows- als auch Unix-Äquivalente auf
  • Der statusLine-Befehl löst sich zu node auf, nicht zu powershell

Eine Datei. Drei Plattformen. Kein Aufwand.

Funktionieren Claude Code Hooks auf Windows?

Ja. Ruf sie über node auf statt über eine Shell, die nur auf einem OS existiert, und sie laufen gleich auf Windows, Linux und macOS. Node.js ist eine feste Voraussetzung von Claude Code auf jeder Plattform, also ist node immer im $PATH. Schreib node .claude/hooks/dein-hook.mjs in settings.json und du bekommst identisches Verhalten auf allen dreien.

Kann ich Python statt Node.js für Hooks verwenden?

Python funktioniert auch, vorausgesetzt jeder Teamkollege hat bereits einen Interpreter auf seinem Rechner. Greif im command-Feld auf python3 statt python, weil bestimmte Linux-Distributionen nie ein einfaches python mitliefern. Node.js bleibt die sicherere Wahl: Claude Code verspricht es auf jeder Plattform, Python tut das nicht.

Wie gehe ich mit Zeilenenden auf verschiedenen Plattformen um?

Meistens gar nicht. readFileSync und writeFileSync normalisieren die Zeilenenden bereits. Jeder Hook liest JSON von stdin, und der JSON-Parser ist egal ob die Zeilenumbrüche CRLF oder LF sind. Die Ausnahme ist jeder Hook, der sein eigenes Shell-Skript ausgibt. Für diesen Fall schreib \n und überlass den Rest Gits autocrlf-Einstellung.

Continue in Hooks

  • Claude Code Setup-Hooks
    Verknüpfe Skripte, Agenten und Docs in Claude Code Setup-Hooks. Ein Befehl führt ein deterministisches Skript aus, übergibt die Ausgabe an einen diagnostizierenden Agenten und protokolliert lebendige Dokumentation.
  • Kontext-Backup-Hooks für Claude Code
    Ein StatusLine-gesteuerter Claude Code Kontext-Backup-Hook. Schreibt strukturierte Snapshots alle 10K Tokens, damit die Auto-Komprimierung nie Fehler, Signaturen und Entscheidungen verschluckt.
  • Hooks-Leitfaden
    Claude Code Hooks von Grund auf: Exit-Codes, JSON-Ausgabe, asynchrone Befehle, HTTP-Endpunkte, PreToolUse- und PostToolUse-Matcher, Produktionsmuster.
  • Claude Code Permission-Hook
    Installiere einen dreistufigen Claude Code Permission-Hook: sofortiges Allow für sichere Aufrufe, sofortiges Deny für gefährliche, LLM-Check für die Grauzone. Kein Skip-Flag.
  • Selbstvalidierende Claude Code Agenten
    Selbstvalidierende Claude Code Agenten: PostToolUse-Lint-Hooks, Stop-Hooks und schreibgeschützte Reviewer-Subagenten in Agentendefinitionen verdrahten, damit fehlerhafte Ausgaben nie ausgeliefert werden.
  • Claude Code Session-Hooks
    Vier Claude Code Session-Lifecycle-Hooks: Init bei Bedarf ausführen, Projektkontext bei SessionStart injizieren, Transkripte sichern und Cleanup beim SessionEnd-Exit protokollieren.

More from Toolkit

  • Tastenkürzel
    Claude Code keybindings.json konfigurieren: 17 Kontexte, Tastenkombinations-Syntax, Chord-Sequenzen, Modifier-Kombinationen und wie du jeden Standard-Shortcut sofort deaktivierst.
  • Status Line Guide
    Richte eine Claude Code Status Line ein, die Modellname, Git-Branch, Sitzungskosten und Kontextnutzung anzeigt. settings.json-Konfiguration, JSON-Eingabe, Bash-, Python- und Node.js-Skripte.
  • KI-SEO und GEO-Optimierung
    Ein Überblick über Generative Engine Optimization: Wie du dafür sorgst, dass deine Inhalte in ChatGPT-, Claude- und Perplexity-Antworten zitiert werden, statt nur bei Google zu ranken.
  • Claude Code vs Cursor in 2026
    Ein direkter Vergleich von Claude Code und Cursor in 2026: Agentenmodelle, Kontextfenster, Preisstufen und welches Tool zu welchem Entwickler-Workflow passt.

Hören Sie auf zu konfigurieren. Fangen Sie an zu bauen.

SaaS-Builder-Vorlagen mit KI-Orchestrierung.

On this page

Warum Hooks brechen, wenn sich das OS ändert
Das universelle Muster in settings.json
Drei Regeln für plattformübergreifende Hook-Logik
Verwende os.homedir() statt Plattform-Variablen
Verwende os.tmpdir() für temporäre Dateipfade
Verwende path.join() für alle Dateipfad-Konstruktionen
Berechtigungen, die beide Plattformen abdecken
Vollständiges Beispiel: Plattformübergreifender Datei-Logger
Debuggen, wenn ein OS bricht
Release-Checkliste
Funktionieren Claude Code Hooks auf Windows?
Kann ich Python statt Node.js für Hooks verwenden?
Wie gehe ich mit Zeilenenden auf verschiedenen Plattformen um?

Hören Sie auf zu konfigurieren. Fangen Sie an zu bauen.

SaaS-Builder-Vorlagen mit KI-Orchestrierung.