Hooks: automatizace bez kompromisů
Přejít na sekci
Co jsou hooks a proč je potřebujete
Hooks jsou pravidla, která se automaticky spouštějí při určitých akcích Claude Code. Když Claude Code chce zapsat soubor, spustit příkaz nebo dokončí úkol, hook může zasáhnout — zablokovat akci, modifikovat ji, nebo spustit vlastní logiku. Představte si git hooks, ale pro AI agenta.
Bez hooks musíte po každé změně ručně spouštět linter, kontrolovat formátování, pouštět testy. S hooks se to děje automaticky. Claude Code zapíše soubor → hook spustí ruff → pokud jsou chyby, Claude Code je vidí a opraví. Nulový manuální zásah.
Typy hooks
Claude Code podporuje čtyři typy hooks. Každý se spouští v jiném momentě a má jiný účel.
PreToolUse — před použitím nástroje
Spustí se PŘEDTÍM, než Claude Code použije nástroj (Write, Bash, Edit atd.). Může akci zablokovat, modifikovat, nebo jen logovat. Ideální pro validaci — 'nesmíš zapisovat do production configu', 'nesmíš pushovat na main'.
PostToolUse — po použití nástroje
Spustí se PO tom, co Claude Code použije nástroj. Výsledek hooků se vrátí zpět Claude Code jako kontext. Ideální pro automatický linting, formátování, spouštění testů po změně souboru.
Notification — při notifikaci
Spustí se, když Claude Code pošle notifikaci (typicky při čekání na input nebo při dokončení). Ideální pro custom notifikace — Slack zprávy, zvuky, desktop notifikace.
Stop — při zastavení
Spustí se, když Claude Code dokončí svůj turn a přestane generovat. Můžete ho využít pro finální validaci nebo cleanup.
Konfigurace hooks
Hooks se konfigurují v souboru .claude/settings.json (projektový) nebo ~/.claude/settings.json (globální). Každý hook má matcher (na který nástroj reaguje) a command (co spustí).
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo 'About to run a bash command'"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "cd $PROJECT_DIR && uv run ruff check --fix $CLAUDE_FILE_PATH 2>&1 || true"
}
]
}
]
}
}Hook environment variables
Hooks mají přístup k proměnným prostředí, které popisují kontext akce. Ty jsou klíčové pro psaní užitečných hooků.
# Dostupné proměnné v hooks:
$CLAUDE_FILE_PATH # Cesta k souboru, se kterým se pracuje
$CLAUDE_TOOL_NAME # Název nástroje (Write, Edit, Bash...)
$CLAUDE_TOOL_INPUT # JSON vstup nástroje (přes stdin)
$PROJECT_DIR # Kořenový adresář projektuPraktický příklad: auto-lint po každé úpravě
Nejběžnější hook — po každé změně souboru spustí linter a formátovač. Výsledek se vrátí Claude Code, který automaticky opraví případné chyby.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *.py ]]; then cd $PROJECT_DIR && uv run ruff check --fix \"$CLAUDE_FILE_PATH\" && uv run ruff format \"$CLAUDE_FILE_PATH\"; fi"
}
]
}
]
}
}Hook command by měl vždy vracet exit code 0 při úspěchu. Pokud hook selže (nenulový exit code), Claude Code uvidí chybový výstup a pokusí se problém vyřešit. To je vlastně žádoucí chování pro linting — chcete, aby Claude Code viděl chyby a opravil je.
Praktický příklad: blokování nebezpečných příkazů
PreToolUse hook, který zablokuje nebezpečné git příkazy. Hook vrátí nenulový exit code a Claude Code akci neprovede.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); if echo \"$INPUT\" | jq -r '.command' | grep -qE 'git\\s+(push\\s+--force|reset\\s+--hard|clean\\s+-fd)'; then echo 'BLOCKED: Dangerous git command detected' >&2; exit 1; fi"
}
]
}
]
}
}Praktický příklad: auto-test po změně
Spustí relevantní testy po každé změně Python souboru. Klíč je spouštět jen relevantní testy, ne celou test suite — jinak bude hook trvat příliš dlouho.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *.py && \"$CLAUDE_FILE_PATH\" != *test* ]]; then MODULE=$(echo \"$CLAUDE_FILE_PATH\" | sed 's|/|.|g' | sed 's|\\.py$||'); TEST_FILE=$(echo \"$CLAUDE_FILE_PATH\" | sed 's|\\([^/]*\\)\\.py$|tests/test_\\1.py|'); if [ -f \"$TEST_FILE\" ]; then cd $PROJECT_DIR && uv run pytest \"$TEST_FILE\" -x -q 2>&1 | tail -5; fi; fi"
}
]
}
]
}
}Praktický příklad: custom notifikace
Notification hook, který pošle desktop notifikaci na macOS když Claude Code potřebuje vaši pozornost.
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); TITLE=$(echo \"$INPUT\" | jq -r '.title // \"Claude Code\"'); MSG=$(echo \"$INPUT\" | jq -r '.body // \"Needs attention\"'); osascript -e \"display notification \\\"$MSG\\\" with title \\\"$TITLE\\\"\""
}
]
}
]
}
}Kombinace hooks pro produkční workflow
V praxi chcete kombinaci hooks — linting, formátování, testování a bezpečnostní kontroly. Tady je kompletní konfigurace pro Python/Django projekt.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.command'); if echo \"$CMD\" | grep -qE 'rm\\s+-rf\\s+/|git\\s+push\\s+--force\\s+(origin\\s+)?main'; then echo 'BLOCKED: Dangerous command' >&2; exit 1; fi"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *.py ]]; then cd $PROJECT_DIR && uv run ruff check --fix \"$CLAUDE_FILE_PATH\" && uv run ruff format \"$CLAUDE_FILE_PATH\"; fi"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); MSG=$(echo \"$INPUT\" | jq -r '.body // \"Done\"'); osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\""
}
]
}
]
}
}Hooks se spouští v pořadí, v jakém jsou definovány. Pokud máte více hooks pro stejný matcher, všechny se spustí sekvenčně. Pokud jakýkoliv PreToolUse hook selže, akce se zablokuje.
Vytvořte soubor .claude/settings.json ve vašem projektu a nastavte PostToolUse hook, který: 1. Reaguje na Write a Edit operace 2. Kontroluje, zda změněný soubor má příponu vašeho jazyka (.py, .ts, .js...) 3. Spustí odpovídající linter (ruff, eslint, biome...) 4. Výsledek vrátí Claude Code Pak upravte nějaký soubor přes Claude Code a ověřte, že se hook spustí automaticky.
Nápověda
Použijte podmínku na příponu souboru: if [[ "$CLAUDE_FILE_PATH" == *.py ]]. Nezapomeňte na cd $PROJECT_DIR, jinak se linter spustí ze špatného adresáře.
Napište PreToolUse hook, který zablokuje: 1. Force push na main/master branch 2. rm -rf na kořenové adresáře 3. Jakýkoliv příkaz s --no-verify Otestujte ho tak, že požádáte Claude Code o provedení jednoho z těchto příkazů a ověřte, že ho hook zablokuje.
Nápověda
Hook čte stdin jako JSON s polem 'command'. Použijte jq -r '.command' pro extrakci příkazu a grep -qE pro pattern matching.
- Hooks automatizují opakované úkoly — linting, formátování, testování, bezpečnostní kontroly
- PreToolUse blokuje nebezpečné akce PŘED provedením, PostToolUse reaguje PO provedení
- Hook output se vrací Claude Code — může automaticky opravit chyby z linteru
- Notification hooks umožňují custom upozornění (desktop, Slack, zvuky)
- Hooks se konfigurují v .claude/settings.json (projektové) nebo ~/.claude/settings.json (globální)
- Kombinujte hooks pro kompletní automatizovaný workflow — lint + format + test + safety
V příští lekci se ponoříme do Permission modes: bezpečnost vs. rychlost — technika, která vám dá jasnou převahu. Odemkněte celý kurz a pokračujte hned.
2/8 hotovo — pokračujte!