Blog

Hooki v Claude Code 2026: nastavitev po korakih in 7 primerov za takojšnjo uporabo

Markdown

7 že pripravljenih hookov za .claude/settings.json, pripravljenih za kopiranje in lepljenje: zaščita .env, prettier, force-push v main, pomišljaji in razvojni strežnik. 4 vrste obravnavalnikov in 31 dogodkov.

Preberi celoten članek

Hooki v Claude Code so ukazi lupine, klici HTTP ali kratka preverjanja LLM, ki se samodejno izvedejo pred dejanjem Claude ali po njem. Dodajajo preverjanja določenim dogodkom orodij, oblikujejo kodo po urejanju in vstavijo svež kontekst ob začetku seje. Ujemajoči se kavelj PreToolUse lahko zavrne ta klic; primeri regularnih izrazov so priročna varovala, ne varnostna meja vseh datotečnih poti ali poti Git. Sledi pregled 4 vrst obravnavalnikov, 31 dogodkov življenjskega cikla, preizkus za vprašanje »kdaj sodi pravilo v hook«, 7 hookov za .claude/settings.json, pripravljenih za kopiranje, ter 3 pasti, na katere sem naletel sam.

Dokumentacija Ailoot: API, ključi in nastavitev.

Kaj so hooki v Claude Code?

Ključna ugotovitev

Hook je ukaz lupine, klic HTTP, kratek poziv LLM ali podagent, ki ga Claude Code izvede kot odziv na določen dogodek življenjskega cikla. Za razliko od navodil v CLAUDE.md, ki jih model lahko prezre ali pozabi, se hook vsakič izvede enako: je koda, ne predlog.

Pol leta sem pravilo »nikoli ne urejaj .env neposredno« hranil v CLAUDE.md. Claude ga je kršil enkrat na mesec. Ne zlonamerno; proti koncu dolge seje ga je preprosto pozabil. Enkrat je v .env končal dodaten žeton; drugič je spremenljivka z enakim imenom prepisala tisto, ki je bila v uporabi.

Pravilo sem premaknil v hook, tako da ga je nemogoče pozabiti. Ko ujemajoče se orodje za neposredno urejanje posreduje pot .env, nastavljeni kavelj zavrne ta klic. Preusmerjanje Bash, skripti, orodja MCP in druge poti potrebujejo ločene nadzore; primer datoteke ne naredi nespremenljive.

Hooki so ukazi lupine, končne točke HTTP ali pozivi LLM, ki jih določite in se samodejno izvajajo na določenih točkah življenjskega cikla Claude Code.

— Anthropic, https://code.claude.com/docs/en/hooks

Z drugimi besedami, hook je vaš ukaz, ki ga Claude Code izvede ob določenem dogodku. Vsako urejanje datoteke, zagon Basha, začetek seje ali zaključek podagenta je dogodek, na katerega lahko pripnete hook.

Zakaj je to pomembno za vibe coderja:

  • Zaščitite datoteke s skrivnostmi pred nenamernim urejanjem.
  • Po vsakem ustvarjanju kode samodejno zaženite prettier/eslint.
  • Brez izrecnega dovoljenja blokirajte git push --force v main.
  • Na začetku vsake seje vstavite svež kontekst.
  • Za potrebe revizije beležite Claudeova dejanja.

CLAUDE.md skrbi za kontekst. Hooki skrbijo za dejanja. To sta dve različni stvari in njuno mešanje je glavna začetniška napaka.

Kako se hooki razlikujejo od CLAUDE.md in skills?

Ključna ugotovitev

CLAUDE.md je besedilo, ki ga model prebere na začetku seje in se ga poskuša držati. Hook je ukaz lupine, ki ga proces Claude Code izvede ob dogodku, neodvisno od modela. Skill je poimenovan paket navodil, ki ga Claude lahko prikliče z orodjem Skill, podobno kot funkcijo. Vsi trije so namenjeni različnim vrstam opravil.

Anthropicova dokumentacija izrecno pojasnjuje razliko med CLAUDE.md in hooki:

Vsebina CLAUDE.md je po sistemskem pozivu posredovana kot uporabniško sporočilo, ne kot del sistemskega poziva. Claude jo prebere in se ji poskuša držati, vendar ni zagotovila za dosledno upoštevanje.

— Anthropic, dokumentacija o pomnilniku, https://code.claude.com/docs/en/memory

Povedano drugače: vsebina CLAUDE.md pride do Claudea kot prvo uporabniško sporočilo, ne kot sistemsko navodilo. Model jo prebere in se ji poskuša držati. Zagotovil pa ni, zlasti proti koncu dolge seje, ko se kontekst poveča in starejša navodila izrinejo.

Hook deluje drugače. Nahaja se v settings.json, ni odvisen od modela in ga proces Claude Code izvede ob določenem dogodku: PreToolUse, PostToolUse, SessionStart in drugih. Ukaz se izvede, preden Claude prejme rezultat, ter lahko fizično blokira dejanje (exit 2) ali spremeni datoteko po urejanju (exit 0).

Primerjava:

ZnačilnostCLAUDE.mdHookSkill
Kje se nahajaCLAUDE.md v korenski mapi projekta.claude/settings.jsonMapa .claude/skills/
Kdo ga izvajaModel ga prebere kot del uporabniškega sporočilaProces Claude Code ob dogodkuModel prek orodja Skill
Zagotovilo izvajanjaNe (po najboljših močeh)Nastavljen ujemajoči se ukazni kavelj izvede kodo; napake in izhodno vedenje so odvisni od dogodkaPrek klica modela (z dovoljenjem, vendar ne na ravni lupine)
NamenKontekst projekta, ton, slog, usmerjanjeOmejitve, oblikovanje, preverjanja določenih datotekKompleksni večstopenjski postopki s parametri
Kdaj se izvedeOb vsakem sporočilu modela v sejiOb dogodku življenjskega ciklaKo ga prikliče model
Ali lahko blokira dejanje?NeDa (exit 2)Ne

Celotna predloga CLAUDE.md in 6 pravil za živo datoteko sta v vodniku Kako konfigurirati CLAUDE.md leta 2026: predloga za takojšnjo uporabo in 6 pravil. O skills kot poimenovanih zmožnostih preberite v vodniku Claude Code Skills: kako zgraditi lastno knjižnico.

Hook je najnižja raven: brez modela, brez interpretacije, samo lupina.

Hooki so eno od orodij za inženiring konteksta, poleg Plan Mode in /compact.

4 vrste hookov: Command, HTTP, Prompt, Agent — katerega izbrati?

Ključna ugotovitev

Claude Code ima 4 vrste obravnavalnikov. Command je skript lupine in najpogostejša vrsta. HTTP pošlje zahtevo POST na vaš URL, namenjeno ekipam in integracijam. Prompt izvede kratek klic Haiku za semantično preverjanje. Agent ustvari podagenta z dostopom do orodij za poglobljeno preverjanje. Začetniki potrebujejo Command in Prompt; pokrijeta 90 % opravil.

VrstaKaj počneKdaj jo izbratiZahtevnost
CommandIzvede ukaz lupine, prejme JSON prek stdin ter odgovori z izhodno kodo in stdoutV 90 % primerov: preverjanje poti, oblikovanje, grep vsebine, lsof, operacije gitnizka
HTTPPošlje POST na vaš URL z JSON-telesom in prejme JSON-odgovorKo pravilo velja za ekipo/CI: centralizirano preverjanje, skupna nadzorna plošča stanja, oddaljeno revidiranjesrednja (potreben je strežnik)
PromptPošlje kratek poziv Haiku (privzeto) in prejme da/ne za semantično ocenoKo grep ni dovolj: »oceni, ali to besedilo zveni korporativno«nizka
AgentUstvari podagenta z dostopom Read/Grep/Glob za večstopenjska preverjanjaZahtevno preverjanje: »poišči vse spremenjene datoteke in preveri, ali zanje obstajajo ustrezni testi«visoka

Najpogostejša napaka je uporaba ukaza Command za nalogo, ki zahteva Prompt. »Ne uporabljaj pomišljajev v datotekah .md« je na primer naloga za grep, zato je Command idealen. »Ne piši v korporativnem tonu« pa je semantično vprašanje in zahteva Prompt.

Če šele začenjate, uporabite Command. Vseh 7 hookov za takojšnjo uporabo spodaj je vrste Command. HTTP/Prompt/Agent pridejo na vrsto pozneje, ko boste pripravljeni.

Kje je settings.json in katere so 4 ravni konfiguracije?

Ključna ugotovitev

Claude Code išče konfiguracijo na 4 mestih: na ravni podjetja (uvedeno prek MDM), uporabniški ravni (~/.claude/settings.json), ravni projekta (.claude/settings.json v korenski mapi repozitorija) in lokalni ravni (.claude/settings.local.json, ni v git). Vse 4 datoteke se združijo ob začetku seje, pri čemer ima nižja raven prednost.

RavenPotKdaj veljaV git?
Podjetje/Library/Application Support/ClaudeCode/settings.json (Mac), /etc/claude-code/settings.json (Linux)Za celotno ekipo prek MDMne
Uporabnik~/.claude/settings.jsonVsi projekti enega uporabnikane
Projekt.claude/settings.json v korenski mapi repozitorijaTa projekt, za celotno ekipoda
Lokalno.claude/settings.local.jsonSamo ta projekt in ta uporabnikne (v .gitignore)

Vseh 7 spodaj opisanih hookov hranim v projektnem .claude/settings.json, zato so samodejno vključeni ob kloniranju repozitorija in Claude uporablja enaka pravila v novem oknu. Osebni eksperimentalni hooki so v .claude/settings.local.json, da ne ovirajo ekipe.

Vse 4 datoteke se združijo ob začetku seje. Če so pravila v sporu, ima prednost nižja raven (lokalna pred projektno, projektna pred uporabniško).

Najhitrejši način za ustvarjanje prvega hooka je interaktivni meni /hooks neposredno v Claude Code. Na seznamu izberite dogodek, izberite matcher (na primer Bash ali Edit) in prilepite ukaz. Claude Code bo v settings.json zapisal veljaven JSON.

31 dogodkov življenjskega cikla: katere potrebujejo začetniki?

Ključna ugotovitev

Claude Code trenutno ponuja 31 dogodkov življenjskega cikla, razdeljenih v 3 pogostosti: enkrat na sejo (SessionStart/SessionEnd), enkrat na potezo (UserPromptSubmit/Stop) in ob vsakem klicu orodja (PreToolUse/PostToolUse). Začetniki potrebujejo 4 od 31 dogodkov: PreToolUse za omejitve, PostToolUse za samodejno urejanje, SessionStart za kontekst in Stop za končna preverjanja.

Dogodki se pojavljajo v treh pogostostih: enkrat na sejo (SessionStart, SessionEnd), enkrat na potezo (UserPromptSubmit, Stop, StopFailure) in ob vsakem klicu orodja znotraj agentne zanke (PreToolUse, PostToolUse).

— Anthropic, referenca za hooks, https://code.claude.com/docs/en/hooks

Pomembno je razumeti tri pogostosti, da se ne boste zmedli:

  1. Enkrat na sejo - SessionStart, SessionEnd, Setup. Izvedejo se enkrat, ko se Claude Code odpre in zapre. Uporabite jih za pripravo konteksta in čiščenje začasnih datotek.
  2. Enkrat na potezo - UserPromptSubmit, UserPromptExpansion, Stop, StopFailure. Sprožijo se ob vsakem vašem sporočilu in vsakič, ko se model ustavi. Uporabite jih za beleženje pogovora in končno preverjanje rezultatov.
  3. Ob vsakem klicu orodja - PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied, PostToolBatch, SubagentStart, SubagentStop. Sprožijo se ob vsakem urejanju datoteke, zagonu Basha, branju ali iskanju. To je najbolj obremenjena plast, kjer se izvajajo omejitve, oblikovanje in preverjanja.

Celoten seznam 31 dogodkov vključuje asinhrone/reaktivne dogodke: TeammateIdle, PreCompact, PostCompact, Elicitation, ElicitationResult, InstructionsLoaded, ConfigChange, CwdChanged, FileChanged, WorktreeCreate, WorktreeRemove, Notification. Namenjeni so naprednim scenarijem; za zdaj jih preskočite.

Preizkus s petimi vprašanji: kdaj sodi pravilo v hook in kdaj ostane v CLAUDE.md?

Ključna ugotovitev

Če pravilo zadeva dejanje (ne konteksta), varnost/denar/podatke, ga je mogoče preveriti z grep/regexom, ga je težko popraviti, če je kršeno, in ga je Claude že vsaj enkrat prekršil, sodi v hook. Če so manj kot trije od petih odgovorov »da«, ostane v CLAUDE.md. Preizkusil sem svojih 80 vrstic in 5 pravil premaknil v hooke.

Zame to deluje kot zakon, ne kot predlog. Izbiro med CLAUDE.md in hookom sem poenostavil v preizkus s petimi vprašanji. Če so vsaj trije odgovori »da«, gre pravilo v hook. Če jih je manj, ostane v besedilu.

Preizkus »kdaj sodi pravilo v hook?«:

  1. Ali pravilo zadeva dejanje in ne konteksta? (»ne zaženi rm -rf« je dejanje; »Imam projekt TypeScript« je kontekst.)
  2. Ali zadeva varnost, denar ali podatke? (»ne dotikaj se .env«, »ne objavljaj ključev«.)
  3. Ali ga lahko preverite z grepom, regexom ali izhodno kodo ukaza lupine? (»po urejanju .md preveri, da v njem ni pomišljaja.«)
  4. Bi bilo posledice težko popraviti, če bi bilo pravilo kršeno? (»force-push v main« je težko razveljaviti; »pozabil sem piko na koncu« je lahko.)
  5. Ste že vsaj enkrat videli, da je Claude pozabil to pravilo?

Primer: »Ne uporabljaj pomišljajev; uporabljaj samo vezaje.« Dejanje? Da. Varnost? Ne. Preverljivo z grepom? Da. Težko popraviti? Ne. Ste že videli kršitev? Da. 3 od 5: dodajte ga v hook.

Protiprimer: »Imam vibe coderje, ne razvijalcev; piši brez slenga.« Dejanje? Bolj kontekst. Varnost? Ne. Preverljivo z regexom? Pretežko. Težko popraviti? Ne. Ste že videli kršitev? Da. 1 od 5: pustite v CLAUDE.md.

Pet mojih pravil je prestalo preizkus. Premaknil sem jih v hooke. Preostalih 75 % je ostalo v besedilni datoteki.

7 hookov za takojšnje kopiranje

Ključna ugotovitev

Spodaj je 7 hookov za takojšnjo uporabo v .claude/settings.json: blokirajo urejanje .env, samodejno zaženejo prettier, preprečijo force-push v main, preverijo pomišljaje, sprostijo vrata pred npm run dev, samodejno ustvarijo commit po uspešnih testih in na začetku seje vstavijo svež kontekst. Vsakega kopirajte v datoteko, znova zaženite Claude Code in deloval bo.

Vseh 7 hookov je shranjenih v eni datoteki .claude/settings.json v korenski mapi projekta. Vsak vnos ima vrsto dogodka, filter orodja (matcher) in ukaz lupine. Izhodna koda 2 pred izvedbo zavrne ujemajoči se klic PreToolUse. Pri PostToolUse se je dejanje že zgodilo: kavelj poda povratne informacije in ga ne more razveljaviti.

Pri večini dogodkov hooka dejanje blokira samo izhodna koda 2. Claude Code obravnava izhodno kodo 1 kot neblokirajočo napako in nadaljuje dejanje, čeprav v Unixu 1 običajno pomeni neuspeh.

— Anthropic, referenca za hooks, https://code.claude.com/docs/en/hooks

exit 0 pomeni uspeh. exit 1 pomeni napako, vendar Claude nadaljuje (to je prvi antipattern spodaj). Vedenje exit 2 je odvisno od dogodka: lahko blokira PreToolUse, PostToolUse pa poda le povratno informacijo o že izvedenem dejanju.

Hook 1. Varujte neposredna urejanja .env (PreToolUse, exit 2)

Blokira poskuse neposrednega urejanja katere koli datoteke, ki se ujema z .env, .env.local, .env.production in podobnimi imeni.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '(^|/)\\.env(\\.|$)' && { echo 'Ne urejaj `.env` neposredno. Povej mi, katero spremenljivko naj dodam, pa bom datoteko odprl sam.' >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}

Kaj počne: Pred vsakim Edit/Write/MultiEdit pridobi pot do datoteke, z grepom preveri, ali se ujema z vzorcem .env, in v tem primeru vrne exit 2 ter sporočilo. Claude vidi stderr in mi pove: »Poskušal sem urediti .env, vendar me je hook blokiral; povej mi, katero spremenljivko naj dodam.«

Hook 2. Po vsakem urejanju kode samodejno zaženite prettier (PostToolUse, exit 0)

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '\\.(ts|tsx|js|jsx|json)$' && npx prettier --write \"$FILE\" 2>/dev/null & exit 0"
          }
        ]
      }
    ]
  }
}

Kaj počne: Po vsakem Edit/Write pridobi pot; če ima datoteka končnico .ts/.tsx/.js/.jsx/.json, v ozadju zažene prettier z &. Vedno se konča z exit 0, ker gre za oblikovanje, ne omejitev. Če prettier odpove, nič hudega; datoteka ostane nespremenjena.

Razlika od hooka 1 je bistvena: PreToolUse + exit 2 je stroga blokada pred dejanjem. PostToolUse + exit 0 je mehka sprememba po dejanju. Gre za dva različna načina za različni nalogi.

Hook 3. Blokirajte git push --force v vejo main (PreToolUse, exit 2)

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "CMD=$(jq -r '.tool_input.command // empty'); [ -z \"$CMD\" ] && exit 0; echo \"$CMD\" | grep -qE 'git[[:space:]]+push' && echo \"$CMD\" | grep -qE '(\\-\\-force|\\-\\-force-with-lease|[[:space:]]-f([[:space:]]|$))' && echo \"$CMD\" | grep -qE '([[:space:]/:])main([[:space:]/:]|$)' && { echo 'Force push to main is forbidden. Create a new branch or ask me to do it manually.' >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}

Kaj počne: Ob vsakem zagonu Basha preveri, ali ukaz vsebuje push, --force/--force-with-lease/-f in omenja main. Če se ujemajo vsi trije pogoji, ga blokira z jasnim sporočilom.

To pravilo sem nekoč zapisal z velikimi tiskanimi črkami v CLAUDE.md. Claude ga je kljub temu prekršil približno enkrat na dva tedna, ko sem ga prosil za »force-push za razveljavitev mojega slabega commita«. Kavelj zajame prikazane dobesedne oblike ukaza, vzdevki, skripti, implicitna ciljna veja ali drug odjemalec Git pa lahko pregled niza obidejo. Zaščito glavne veje uveljavite na oddaljenem strežniku in omejite agentove poverilnice.

Hook 4. Blokirajte pomišljaje v besedilnih datotekah (PostToolUse, exit 2)

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '\\.(md|mdx|tsx?)$' && grep -q $'\\xe2\\x80\\x94' \"$FILE\" && { echo \"File $FILE contains an em dash (U+2014). Replace it with a regular hyphen (U+002D).\" >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}

Kaj počne: PostToolUse z exit 2 Claudu po spremembi sporoči neuspeh naknadnega preverjanja. Zapisa ne razveljavi ali prepreči. Če Claude uredi datoteko in v njej pusti pomišljaj, hook odpove, Claude prejme povratne informacije in poskusi znova. Po 2–3 sejah Claude povsem preneha vstavljati ta znak.

Upoštevajte, da grep izrecno išče znak pomišljaja (U+2014) z uporabo $'\xe2\x80\x94', kar je zapis Bash za njegove bajte UTF-8. Če preprosto napišete grep -q '-', bo ukaz ujel navadne vezaje in se zagnal za vsako datoteko. Nevidni znak pokvari celotno logiko.

Hook 5. Sprostite vrata 3000 pred npm run dev (PreToolUse, exit 0)

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "CMD=$(jq -r '.tool_input.command // empty'); [ -z \"$CMD\" ] && exit 0; echo \"$CMD\" | grep -qE '(npm|pnpm|yarn)[[:space:]]+run[[:space:]]+dev' && { lsof -ti:3000 | xargs -r kill -9 2>/dev/null; echo 'Port 3000 freed before launch' >&2; }; exit 0"
          }
        ]
      }
    ]
  }
}

Kaj počne: Pred vsakim npm run dev (ali pnpm/yarn) ustavi proces na vratih 3000. Vedno se konča z exit 0, ker gre za pripravo, ne omejitev. S tem prepreči vrsto pasti, ko Claude vidi »vrata so zasedena«, misli, da je težava v kodi, in začne odpravljati napake, čeprav je v resnici ostal zagnan stari strežnik.

Hook 6. Samodejno ustvarite commit po uspešnih testih (PostToolUse, exit 0)

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); CMD=$(printf '%s' \"$INPUT\" | jq -r '.tool_input.command // empty') || exit 1; EXIT=$(printf '%s' \"$INPUT\" | jq -r '.tool_response.exit_code // empty') || exit 1; case \"$CMD\" in 'npm test'|'pnpm test'|'yarn test') ;; *) exit 0 ;; esac; [ \"$EXIT\" = \"0\" ] || exit 0; git diff --cached --quiet || { echo 'Existing staged changes: review manually' >&2; exit 0; }; git add -- src/orders.ts tests/orders.test.ts || exit 1; git diff --cached --quiet && exit 0; git commit -m 'tests: checkpoint after successful run'"
          }
        ]
      }
    ]
  }
}

Kaj počne: Vhodni JSON prebere enkrat in sprejme samo prikazane točne preproste testne ukaze. Nadaljuje samo ob izrecni ničli v tool_response.exit_code; če nameščena različica tega polja ne ponuja, commit preskoči, ne ugiba uspeha. src/orders.ts in tests/orders.test.ts zamenjajte s točnimi datotekami naloge. Obstoječe pripravljene spremembe ustavijo recept, da ne vključi tujega dela. Neuspešen add ustavi izvajanje, prazen diff ne ustvari commita, običajni commit hooki pa ostanejo omogočeni. Pred vklopom brez omrežja preizkusite uspešen, neuspešen in manjkajoč rezultat.

Antipattern: dodajanje git commit --no-verify vsakemu Editu. Preverjanja commita pustite omogočena. Če preverjanje rekurzivno sproži avtomatizacijo, zožite sprožilec ali preoblikujte preverjanje; preverjanja ne obidite privzeto. Pred samodejnimi commiti preglejte pripravljeni diff in lastništvo naloge.

Hook 7. Vstavite svež kontekst ob začetku seje (SessionStart z additionalContext)

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo 'no-branch'); STATUS=$(git status --short 2>/dev/null | head -10); echo \"{\\\"additionalContext\\\":\\\"Current branch: $BRANCH. Uncommitted changes:\\n$STATUS\\\"}\""
          }
        ]
      }
    ]
  }
}

Kaj počne: Ob začetku seje zbere trenutno vejo Git in seznam sprememb, ki še niso v commitu, nato vrne JSON s poljem additionalContext. Claude Code to besedilo vstavi v prvo sistemsko sporočilo, zato Claude že od začetka ve, kje je in kaj je ostalo od prejšnje seje.

Uporabite additionalContext za informacije o trenutnem stanju okolja ali pravkar končanem opravilu, ki bi jih moral Claude poznati: stanje okolja (trenutna veja, cilj uvajanja, aktivne zastavice funkcij), pogojna pravila projekta (kateri ukaz za teste velja za pravkar urejeno datoteko), zunanji podatki (odprte naloge, dodeljene vam, nedavni rezultati CI).

— Anthropic, referenca za hooks, https://code.claude.com/docs/en/hooks

Razširitve tega hooka: pridobite zadnji commit in njegov opis, stanje GitHub Actions, aktivni sprint v Linear/Jira ter odprte naloge za trenutni repozitorij.

3 pasti hookov, na katere naleti vsak drugi človek

Ključna ugotovitev

Prva past: hook z exit 1 gre tiho naprej, Claude pa prezre napako. Druga: zahtevno opravilo v hooku se po 60-sekundni časovni omejitvi prekine. Tretja: hook vidi le spremenljivke okolja iz ~/.zshrc, ne pa projektove datoteke .env. Vsako od teh težav odpravi ena vrstica, vendar brez poznavanja pasti se lahko zdi, da »hooki ne delujejo«.

Past 1. Hook z exit 1 gre tiho naprej

To je najnevarnejša past. Teden dni sem mislil, da moja zaščita .env deluje, a izkazalo se je, da sem v hooku uporabil jq -r '.tool_input.file_path' brez preverjanja vrednosti null. Ko je bil tool_input prazen, je jq končal s kodo 1. Claude je exit 1 razumel kot »napaka hooka, nadaljuj«, zato se je dejanje izvedlo. Nisem razumel, zakaj se je .env še vedno urejal. Vzrok sem opazil šele, ko sem hook ročno zagnal v terminalu s praznim vhodom.

Rešitev je eno pravilo: vsak hook začnite s preverjanjem null in ga končajte z || exit 0. Vsak nepričakovan izhod se tako konča z »varnim« izhodom, namesto da bi tiho spustil dejanje skozi.

# Predloga za varen začetek in konec:
FILE=$(jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0
# ... vaša logika ...
exit 0   # ali || exit 0 v eni vrstici

Past 2. Počasni hooki se prekinejo zaradi časovne omejitve

Imel sem hook, ki je po Edit zagnal eslint --fix nad celotno datoteko. Obdelava velikih datotek (1000+ vrstic) je trajala 8–10 sekund. Privzeta časovna omejitev hooka v Claude Code je 60 sekund, zato sem mislil, da sem znotraj omejitve. Toda ko se v eni minuti zgodi več urejanj, se hooki kopičijo v čakalni vrsti in nekateri se preprosto izpustijo. To sem ugotovil šele, ko se je v dnevniku pojavilo sporočilo »hook timed out«.

Rešitev: če hook zahteva veliko dela, ga zaženite v ozadju. Uporabite eslint --fix "$FILE" &, ne da bi čakali na rezultat. Hook se nato v nekaj milisekundah konča z exit 0, medtem ko se dejansko delo izvaja v ozadju.

# Zahtevno opravilo v ozadju:
npx eslint --fix "$FILE" &
exit 0

Past 3. Hook ne vidi projektovih spremenljivk okolja

Mislil sem, da bo process.env v hooku na voljo tako kot v aplikaciji Node.js. Ni. Hook se izvaja v lupini, ki jo zažene nadrejeni proces Claude Code, in vidi samo vsebino ~/.zshrc ali ~/.bashrc ter tisto, kar mu Claude Code izrecno posreduje. Če je hook odvisen od OPENAI_API_KEY iz .env, morate .env prebrati ročno.

Rešitev: v ukazu hooka izrecno preberite .env.

# Posredovanje projektovega okolja hooku:
cd "$PWD" && source .env && curl -H "Authorization: Bearer $OPENAI_API_KEY" ...
# Ali z dotenv:
dotenv -e .env -- node my-validator.js

To je še posebej neprijetno v monorepu, kjer imajo različni paketi lastne datoteke .env. Težavo odpravite tako, da posredujete PWD in na začetku ukaza izrecno izvedete cd "$PWD".

Kako preizkusiti hooke pred commitom?

Ključna ugotovitev

Hook je ukaz lupine. Ročno ga lahko zaženete v terminalu z lažnim stdin-vhodom, preverite njegovo izhodno kodo in stderr ter vse to opravite, še preden ga zažene Claude Code. Tako prihranite ure odpravljanja napak in se zaščitite pred hooki, ki blokirajo lastno delovanje.

Osnovni testni scenarij. Vzemite ukaz hooka iz JSON-a, odprite terminal in mu podajte JSON, ki bi ga poslal Claude Code:

# Preizkus hooka 1 (zaščita .env):
echo '{"tool_input":{"file_path":".env"}}' | bash -c '
FILE=$(jq -r ".tool_input.file_path // empty")
[ -z "$FILE" ] && exit 0
echo "$FILE" | grep -qE "(^|/)\.env(\.|$)" && {
  echo "BLOCKED" >&2
  exit 2
} || exit 0
'
echo "Exit code: $?"

V stderr bi morali videti BLOCKED, izhod pa bi moral vsebovati Exit code: 2. Če dobite exit 0, regex ne deluje; popravite grep.

Scenariji za preverjanje:

  1. Pozitivni primer - datoteka bi morala biti blokirana. .env za hook 1, git push --force main za hook 3.
  2. Negativni primer - datoteka ne bi smela biti blokirana. README.md za hook 1, git push origin feature-branch za hook 3.
  3. Robni primeri - prazen vhod, vrednosti null, nepričakovani znaki. Hook mora vrniti exit 0 ali jasno napako, ne pa tiho spustiti dejanja skozi.

Kam namestiti eksperimentalne hooke. Ne v .claude/settings.json, temveč v .claude/settings.local.json (ni v git). Pod PostToolUse dodajte nove hooke z echo namesto dejanskega dejanja, preverite, ali se sprožijo, nato pa jih premaknite v produkcijski settings.json.

// Poskus v settings.local.json - zapis v /tmp/hook-debug.log:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"[hook fired] $(date) $(jq -r '.tool_input.file_path // \"?\"')\" >> /tmp/hook-debug.log"
          }
        ]
      }
    ]
  }
}

Po 5–10 urejanjih v Claude Code odprite /tmp/hook-debug.log in preverite, katere datoteke so sprožile hook. Če je datoteka prazna, se matcher ne ujema; popravite regex.

Kaj sledi?

Ključna ugotovitev

Začnite s hooki PostToolUse, ki se končajo z exit 0; ti so najvarnejši in ničesar ne blokirajo. Po enem tednu dodajte prvi hook PreToolUse z exit 2 za zaščito .env ali preprečevanje force-pusha. Po dveh tednih se bo CLAUDE.md iz pogodbe z 200 vrsticami skrčil na kratek opis konteksta s 50–80 vrsticami, izbrana preverjanja dogodkov pa bodo v hookih, trde meje dostopa pa ločeno uveljavljene z dovoljenji, peskovnikom in oddaljenimi zaščitami.

5 korakov za prihodnji teden:

  1. Z grepom preiščite CLAUDE.md in poiščite besede, kot so »nikoli«, »prepovedano«, »vedno« in »mora«. Vsako tako pravilo je kandidat za hook. Če je pravilo zapovedno, ga besedilna datoteka ne bo uveljavila.
  2. Začnite s PostToolUse + exit 0. To je najvarnejša možnost: nekaj spremeni, vendar ničesar ne blokira. Prettier (hook 2), ustavitev razvojnega strežnika (hook 5), samodejni commit po testih (hook 6).
  3. Ko boste prepričani, dodajte prvi PreToolUse + exit 2. Zaščitite na primer .env (hook 1) ali preprečite force-push (hook 3). Gre za strogo blokado, napaka v ukazu grep pa lahko blokira tudi vas.
  4. Pred commitom hooke preizkusite ročno (glejte zgornji razdelek). S tem prihranite ure odpravljanja napak.
  5. Za poskuse uporabljajte settings.local.json. Nove hooke dodajte z echo namesto dejanskega dejanja.

Ko so hooki nastavljeni, je naslednji korak v skupini vodnikov kako razveljaviti spremembe v Claude Code, če hook spusti skozi kaj nevarnega. Če želite, da si Claude med sejami zapomni strukturo projekta, ustvarite Second Brain v Claude Code (mapa business/ + povezana zbirka znanja). Če želite spretnostim svojega projekta dodeliti imena, da jih lahko znova uporabite, si oglejte Claude Code Skills.

Če potrebujete dostop do nevronskih mrež prek Ailoota, si oglejte Ailoot.

Več podrobnosti

Vprašanja in odgovori: Hooki v Claude Code 2026: nastavitev po korakih in 7 primerov za takojšnjo uporabo

Zakaj mora kavelj vhod JSON prebrati samo enkrat?

Standardni vhod je tok: prvi proces jq ga porabi, poznejša branja pa dobijo EOF. Vhod shranite enkrat, nato iz shranjene vrednosti izvlecite ukaz in rezultat. Odsoten ali neznan rezultat obravnavajte kot nepreverjen in samodejni commit preskočite.

Ali vzorčni kavlji z regularnimi izrazi ustvarijo varnostno mejo?

Ne. Preverjajo določene dogodke in prepoznavne nize ukazov. Preusmerjanje lupine, vzdevki, skripti, orodja MCP ali druga pot pisanja jih lahko obidejo; za trde meje uporabite omejene poverilnice, datotečna dovoljenja, peskovnik in zaščitene veje.

Vsi članki