Hooks dalam Claude Code 2026: persediaan langkah demi langkah dan 7 contoh sedia guna
Markdown7 hook sedia guna untuk .claude/settings.json yang boleh terus disalin dan ditampal: perlindungan .env, prettier, force-push ke main, tanda pisah panjang dan pelayan pembangunan. 4 jenis pengendali dan 31 peristiwa.
Baca artikel penuh
Hooks dalam Claude Code ialah arahan shell, panggilan HTTP atau semakan LLM ringkas yang berjalan secara automatik sebelum atau selepas tindakan Claude. Hook menambah pemeriksaan kepada peristiwa alat khusus, memformat kod selepas suntingan dan memasukkan konteks terkini pada permulaan sesi. Hook PreToolUse sepadan boleh menolak panggilan itu; contoh regex ini pengadang kemudahan, bukan sempadan keselamatan merentas setiap laluan akses fail atau Git. Berikut ialah penerangan tentang 4 jenis pengendali, 31 peristiwa kitar hayat, ujian untuk menentukan “bila sesuatu peraturan patut dijadikan hook”, 7 hook yang boleh terus disalin ke .claude/settings.json dan 3 masalah yang pernah saya hadapi sendiri.
Dokumentasi Ailoot: API, kunci dan persediaan.
Apakah hooks dalam Claude Code?
Perkara utama
Hook ialah arahan shell, panggilan HTTP, prompt LLM ringkas atau subagen yang dijalankan oleh Claude Code sebagai tindak balas kepada peristiwa kitar hayat tertentu. Tidak seperti arahan dalam CLAUDE.md, yang mungkin diabaikan atau dilupakan oleh model, hook berjalan dengan cara yang sama setiap kali: ia ialah kod, bukan cadangan.
Selama setengah tahun, saya meletakkan peraturan “jangan sekali-kali menyunting .env secara langsung” dalam CLAUDE.md. Claude melanggarnya sebulan sekali. Bukan dengan sengaja; ia sekadar terlupa pada penghujung sesi yang panjang. Pernah sekali token tambahan masuk ke dalam .env; pada masa lain, pemboleh ubah dengan nama pendua menggantikan pemboleh ubah yang sedang digunakan.
Saya memindahkan peraturan itu ke dalam hook, jadi peraturan tersebut mustahil dilupakan. Apabila alat suntingan langsung sepadan membekalkan laluan .env, hook dikonfigurasikan menolak panggilan itu. Pengalihan Bash, skrip, alat MCP dan laluan akses lain memerlukan kawalan berasingan; contoh ini tidak menjadikan fail tidak boleh diubah.
Hooks ialah arahan shell, endpoint HTTP atau prompt LLM yang anda tentukan dan berjalan secara automatik pada titik tertentu dalam kitar hayat Claude Code.
Dengan kata lain, hook ialah arahan anda yang dijalankan oleh Claude Code apabila peristiwa tertentu berlaku. Setiap suntingan fail, pelancaran Bash, permulaan sesi atau penyelesaian subagen ialah peristiwa yang boleh anda kaitkan dengan hook.
Mengapa ini penting untuk vibe coder:
- Lindungi fail yang mengandungi rahsia daripada suntingan tidak sengaja.
- Jalankan prettier/eslint secara automatik selepas setiap penjanaan kod.
- Sekat
git push --forceke main tanpa kebenaran jelas. - Masukkan konteks terkini pada permulaan setiap sesi.
- Catat tindakan Claude untuk tujuan audit.
CLAUDE.md mengendalikan konteks. Hooks mengendalikan tindakan. Kedua-duanya perkara yang berbeza, dan mengelirukannya ialah kesilapan utama pengguna baharu.
Apakah perbezaan hooks dengan CLAUDE.md dan skills?
Perkara utama
CLAUDE.md ialah teks yang dibaca oleh model pada permulaan sesi dan cuba dipatuhinya. Hook ialah arahan shell yang dijalankan oleh proses Claude Code sebagai tindak balas kepada peristiwa, tanpa bergantung pada model. Skill ialah pakej arahan bernama yang boleh dipanggil oleh Claude menggunakan alat Skill, seperti fungsi. Ketiga-tiganya menangani jenis tugas yang berbeza.
Dokumentasi Anthropic menerangkan dengan jelas perbezaan antara CLAUDE.md dengan hooks:
Kandungan CLAUDE.md disampaikan sebagai mesej pengguna selepas prompt sistem, bukannya sebagai sebahagian daripada prompt sistem. Claude membacanya dan cuba mematuhinya, tetapi tiada jaminan bahawa arahan itu akan dipatuhi dengan tegas.
Dengan kata lain, kandungan CLAUDE.md sampai kepada Claude sebagai mesej pertama daripada pengguna, bukannya arahan sistem. Model akan membacanya dan cuba mematuhinya. Namun, tiada jaminan, terutamanya pada penghujung sesi panjang apabila konteks bertambah dan arahan lama tersingkir.
Hook berfungsi dengan cara yang berbeza. Ia berada dalam settings.json, tidak bergantung pada model dan dijalankan oleh proses Claude Code apabila peristiwa tertentu berlaku: PreToolUse, PostToolUse, SessionStart dan lain-lain. Arahan itu berjalan sebelum Claude menerima hasilnya dan boleh menyekat tindakan secara fizikal (exit 2) atau mengubah suai fail selepas penyuntingan (exit 0).
Perbandingan:
| Ciri | CLAUDE.md | Hook | Skill |
|---|---|---|---|
| Lokasi | CLAUDE.md dalam direktori akar projek | .claude/settings.json | Folder .claude/skills/ |
| Pihak yang menjalankannya | Model membacanya sebagai sebahagian daripada mesej pengguna | Proses Claude Code apabila peristiwa berlaku | Model melalui alat Skill |
| Jaminan pelaksanaan | Tiada (usaha terbaik) | Hook arahan sepadan dikonfigurasikan melaksanakan kod; kegagalan dan tingkah laku keluar bergantung pada peristiwa | Melalui panggilan model (dengan kebenaran, tetapi bukan pada peringkat shell) |
| Kegunaan | Konteks projek, nada, gaya, penghalaan | Sekatan, pemformatan, semakan pada fail tertentu | Prosedur berbilang langkah yang rumit dengan parameter |
| Masa ia berjalan | Setiap mesej model dalam sesi | Apabila peristiwa kitar hayat berlaku | Apabila dipanggil oleh model |
| Bolehkah ia menyekat tindakan? | Tidak | Ya (exit 2) | Tidak |
Templat lengkap CLAUDE.md dan 6 peraturan untuk fail yang sentiasa dikemas kini terdapat dalam panduan Cara mengkonfigurasi CLAUDE.md pada 2026: templat sedia guna dan 6 peraturan. Ketahui tentang skills sebagai keupayaan bernama dalam Claude Code Skills: Cara membina pustaka anda sendiri.
Hook ialah tahap paling rendah: tiada model, tiada tafsiran, hanya shell.
Hooks ialah salah satu alat kejuruteraan konteks, bersama Plan Mode dan /compact.
4 jenis hook: Command, HTTP, Prompt, Agent — yang mana patut dipilih?
Perkara utama
Claude Code mempunyai 4 jenis pengendali. Command ialah skrip shell dan jenis yang paling lazim. HTTP menghantar permintaan POST ke URL anda, sesuai untuk pasukan dan integrasi. Prompt membuat panggilan Haiku ringkas untuk semakan semantik. Agent mencipta subagen dengan akses kepada alat untuk pengesahan mendalam. Pengguna baharu hanya memerlukan Command dan Prompt; kedua-duanya meliputi 90% tugas.
| Jenis | Fungsinya | Bila patut dipilih | Kerumitan |
|---|---|---|---|
| Command | Menjalankan arahan shell, menerima JSON melalui stdin dan membalas dengan kod keluar serta stdout | 90% kes: menyemak laluan, pemformatan, grep pada kandungan, lsof, operasi git | rendah |
| HTTP | Menghantar permintaan POST dengan isi JSON ke URL anda dan menerima JSON sebagai respons | Apabila peraturan perlu dikendalikan oleh pasukan/CI: pengesahan berpusat, papan pemuka status bersama, audit jauh | sederhana (memerlukan pelayan) |
| Prompt | Menghantar prompt ringkas kepada Haiku (secara lalai) dan mendapatkan jawapan ya/tidak untuk penilaian semantik | Apabila grep tidak mencukupi: “nilai sama ada teks ini kedengaran seperti bahasa korporat” | rendah |
| Agent | Mencipta subagen dengan akses Read/Grep/Glob untuk semakan berbilang langkah | Pengesahan berat: “cari semua fail yang diubah dan semak sama ada ujian yang sepadan wujud” | tinggi |
Kesilapan yang paling lazim ialah cuba menggunakan Command untuk tugas yang memerlukan Prompt. Contohnya, “jangan gunakan tanda pisah panjang dalam fail .md” ialah tugas grep, jadi Command sesuai. Namun, “jangan menulis dengan nada korporat” ialah perkara semantik, jadi ia memerlukan Prompt.
Jika anda baru bermula, gunakan Command. Ketujuh-tujuh hook sedia guna di bawah ialah jenis Command. HTTP/Prompt/Agent boleh digunakan kemudian, apabila anda sudah bersedia.
Di manakah settings.json, dan apakah 4 peringkat konfigurasi?
Perkara utama
Claude Code mencari konfigurasi di 4 tempat: enterprise (digunakan melalui MDM), pengguna (~/.claude/settings.json), projek (.claude/settings.json dalam direktori akar repositori) dan setempat (.claude/settings.local.json, tidak dimasukkan dalam git). Keempat-empat fail digabungkan pada permulaan sesi, dengan peringkat yang lebih rendah diberi keutamaan.
| Peringkat | Laluan | Bila digunakan | Dalam git? |
|---|---|---|---|
| Enterprise | /Library/Application Support/ClaudeCode/settings.json (Mac), /etc/claude-code/settings.json (Linux) | Untuk seluruh pasukan melalui MDM | tidak |
| Pengguna | ~/.claude/settings.json | Semua projek untuk seorang pengguna | tidak |
| Projek | .claude/settings.json dalam direktori akar repositori | Projek ini, untuk seluruh pasukan | ya |
| Setempat | .claude/settings.local.json | Projek ini sahaja, untuk pengguna ini sahaja | tidak (dalam .gitignore) |
Saya menyimpan 7 hook yang diterangkan di bawah dalam .claude/settings.json projek, supaya semuanya disertakan secara automatik apabila repositori diklon dan Claude mengikuti peraturan yang sama dalam tetingkap baharu. Hook eksperimen peribadi disimpan dalam .claude/settings.local.json supaya tidak mengganggu pasukan.
Keempat-empat fail digabungkan pada permulaan sesi. Jika peraturan bercanggah, peringkat yang lebih rendah diberi keutamaan (setempat mengatasi projek, projek mengatasi pengguna).
Cara terpantas untuk mencipta hook pertama anda ialah menggunakan menu interaktif /hooks dalam Claude Code. Pilih peristiwa daripada senarai, pilih matcher (contohnya Bash atau Edit) dan tampal arahan. Claude Code akan menulis JSON yang sah ke dalam settings.json untuk anda.
31 peristiwa kitar hayat: yang manakah diperlukan oleh pengguna baharu?
Perkara utama
Claude Code kini mempunyai 31 peristiwa kitar hayat yang dibahagikan kepada 3 kekerapan: sekali bagi setiap sesi (SessionStart/SessionEnd), sekali bagi setiap giliran (UserPromptSubmit/Stop) dan pada setiap panggilan alat (PreToolUse/PostToolUse). Pengguna baharu memerlukan 4 daripada 31 peristiwa: PreToolUse untuk sekatan, PostToolUse untuk suntingan automatik, SessionStart untuk konteks dan Stop untuk semakan akhir.
Peristiwa berlaku pada tiga kekerapan: sekali bagi setiap sesi (SessionStart, SessionEnd), sekali bagi setiap giliran (UserPromptSubmit, Stop, StopFailure) dan pada setiap panggilan alat dalam gelung agentik (PreToolUse, PostToolUse).
Penting untuk memahami ketiga-tiga kekerapan ini supaya anda tidak keliru:
- Sekali bagi setiap sesi -
SessionStart,SessionEnd,Setup. Peristiwa ini berjalan sekali apabila Claude Code dibuka dan ditutup. Gunakannya untuk memulakan konteks dan membersihkan fail sementara. - Sekali bagi setiap giliran -
UserPromptSubmit,UserPromptExpansion,Stop,StopFailure. Peristiwa ini dicetuskan untuk setiap mesej anda dan setiap kali model berhenti. Gunakannya untuk merekodkan perbualan dan membuat semakan akhir hasil. - Pada setiap panggilan alat -
PreToolUse,PostToolUse,PostToolUseFailure,PermissionRequest,PermissionDenied,PostToolBatch,SubagentStart,SubagentStop. Peristiwa ini dicetuskan pada setiap suntingan fail, pelancaran Bash, bacaan atau carian. Inilah lapisan paling sibuk, tempat sekatan, pemformatan dan pengesahan dijalankan.
Senarai penuh 31 peristiwa termasuk peristiwa tak segerak/reaktif: TeammateIdle, PreCompact, PostCompact, Elicitation, ElicitationResult, InstructionsLoaded, ConfigChange, CwdChanged, FileChanged, WorktreeCreate, WorktreeRemove, Notification. Peristiwa ini untuk senario lanjutan; abaikannya buat masa ini.
Ujian lima soalan: bila peraturan patut dijadikan hook, dan bila ia patut kekal dalam CLAUDE.md?
Perkara utama
Jika sesuatu peraturan berkaitan tindakan (bukan konteks), melibatkan keselamatan/wang/data, boleh disemak dengan grep/regex, sukar dibaiki jika dilanggar dan Claude pernah melanggarnya sekurang-kurangnya sekali, peraturan itu patut dijadikan hook. Jika kurang daripada tiga daripada lima jawapan ini ialah “ya”, peraturan itu kekal dalam CLAUDE.md. Saya menggunakan ujian ini pada 80 baris saya dan memindahkan 5 peraturan ke dalam hooks.
Bagi saya, ini berfungsi seperti undang-undang, bukan cadangan. Saya memudahkan pilihan antara CLAUDE.md dengan hook menjadi ujian lima soalan. Jika sekurang-kurangnya tiga jawapan ialah “ya”, peraturan itu dimasukkan ke dalam hook. Jika kurang daripada tiga, peraturan itu kekal dalam teks.
Ujian “bila peraturan patut dijadikan hook?”:
- Adakah peraturan ini berkaitan tindakan dan bukannya konteks? (“jangan jalankan
rm -rf” ialah tindakan; “saya mempunyai projek TypeScript” ialah konteks.) - Adakah peraturan ini berkaitan keselamatan, wang atau data? (“jangan sentuh
.env,” “jangan terbitkan kunci.”) - Bolehkah peraturan ini disemak dengan grep, regex atau kod keluar arahan shell? (“selepas menyunting
.md, pastikan tiada tanda pisah panjang.”) - Jika peraturan dilanggar, adakah akibatnya sukar dibaiki? (“force-push ke main” sukar dipulihkan; “terlupa noktah di hujung ayat” mudah.)
- Pernahkah anda melihat Claude terlupa peraturan ini sekurang-kurangnya sekali?
Contoh: “Jangan gunakan tanda pisah panjang; gunakan tanda sempang sahaja.” Tindakan? Ya. Keselamatan? Tidak. Boleh disemak dengan grep? Ya. Sukar dibaiki? Tidak. Pernah dilanggar? Ya. 3 daripada 5: jadikannya hook.
Contoh sebaliknya: “Saya bekerja dengan vibe coder, bukan pembangun; tulis tanpa bahasa slanga.” Tindakan? Lebih kepada konteks. Keselamatan? Tidak. Boleh disemak dengan regex? Terlalu sukar. Sukar dibaiki? Tidak. Pernah dilanggar? Ya. 1 daripada 5: kekalkan dalam CLAUDE.md.
Lima peraturan saya lulus ujian itu. Peraturan tersebut dipindahkan ke dalam hooks. Baki 75% kekal dalam fail teks.
7 hook yang sedia disalin
Perkara utama
Di bawah ialah 7 hook sedia guna untuk .claude/settings.json: sekat suntingan .env, jalankan prettier secara automatik, cegah force-push ke main, semak tanda pisah panjang, bebaskan port sebelum npm run dev, buat commit automatik selepas ujian berjaya dan masukkan konteks terkini pada permulaan sesi. Salin setiap satunya ke dalam fail, mulakan semula Claude Code dan semuanya akan berfungsi.
Ketujuh-tujuh hook disimpan dalam satu fail .claude/settings.json di direktori akar projek. Setiap entri mempunyai jenis peristiwa, penapis alat (matcher) dan arahan shell. Kod keluar 2 menolak panggilan PreToolUse sepadan sebelum pelaksanaan. Dalam PostToolUse, tindakan sudah berlaku: hook melaporkan maklum balas dan tidak boleh mengundurkannya.
Bagi kebanyakan peristiwa hook, hanya kod keluar 2 yang menyekat tindakan. Claude Code menganggap kod keluar 1 sebagai ralat yang tidak menyekat dan meneruskan tindakan, walaupun 1 lazimnya bermaksud kegagalan dalam Unix.
exit 0 bermaksud berjaya. exit 1 bermaksud ralat, tetapi Claude meneruskan tindakan (inilah antipola pertama di bawah). exit 2 mempunyai tingkah laku khusus peristiwa: ia boleh menyekat PreToolUse, sementara PostToolUse hanya melaporkan maklum balas tentang tindakan yang sudah diambil.
Hook 1. Kawal suntingan langsung .env (PreToolUse, exit 2)
Menyekat percubaan menyunting secara langsung mana-mana fail yang sepadan dengan .env, .env.local, .env.production dan sebagainya.
{
"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 'Do not edit `.env` directly. Tell me which variable to add, and I’ll open the file myself.' >&2; exit 2; } || exit 0"
}
]
}
]
}
}
Fungsinya: Sebelum setiap Edit/Write/MultiEdit, hook mendapatkan laluan fail, menyemak dengan grep sama ada laluan itu sepadan dengan corak .env dan, jika ya, memulangkan exit 2 bersama mesej. Claude melihat stderr dan memberitahu saya: “Saya cuba menyunting .env, tetapi hook menyekat saya; beritahu saya pemboleh ubah yang perlu ditambah.”
Hook 2. Jalankan prettier secara automatik selepas setiap suntingan kod (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"
}
]
}
]
}
}
Fungsinya: Selepas setiap Edit/Write, hook mendapatkan laluan dan, jika sambungannya .ts/.tsx/.js/.jsx/.json, menjalankan prettier di latar belakang dengan &. Hook sentiasa berakhir dengan exit 0 kerana ini pemformatan, bukannya sekatan. Jika prettier gagal, tidak mengapa; fail kekal seperti sediakala.
Perbezaan dengan hook 1 sangat ketara: PreToolUse + exit 2 ialah sekatan keras sebelum tindakan. PostToolUse + exit 0 ialah suntingan lembut selepas tindakan. Kedua-duanya mod yang berbeza untuk tugas yang berbeza.
Hook 3. Sekat git push --force ke cabang 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"
}
]
}
]
}
}
Fungsinya: Setiap kali Bash dilancarkan, hook menyemak sama ada arahan itu mengandungi push, mengandungi --force/--force-with-lease/-f dan menyebut main. Jika ketiga-tiga syarat dipenuhi, arahan disekat dengan mesej yang jelas.
Dulu saya meletakkan peraturan ini dalam CLAUDE.md dengan huruf besar. Claude tetap melanggarnya kira-kira sekali setiap dua minggu apabila saya memintanya “buat force-push untuk membatalkan commit saya yang salah”. Hook ini menangkap bentuk arahan literal ditunjukkan, tetapi alias, skrip, cabang destinasi tersirat atau klien Git lain boleh memintas pemeriksaan rentetan. Kuatkuasakan perlindungan main di remote dan hadkan kelayakan tersedia kepada ejen.
Hook 4. Sekat tanda pisah panjang dalam fail teks (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"
}
]
}
]
}
}
Fungsinya: PostToolUse dengan exit 2 melaporkan kegagalan semakan kepada Claude selepas suntingan. Ia tidak mengundur atau menghalang tulisan. Jika Claude menyunting fail dan meninggalkan tanda pisah panjang, hook gagal, Claude menerima maklum balas dan mencuba lagi. Selepas 2–3 sesi, Claude berhenti memasukkan aksara ini sama sekali.
Perhatikan bahawa grep mencari aksara tanda pisah panjang (U+2014) secara khusus menggunakan $'\xe2\x80\x94', iaitu notasi Bash untuk menulisnya sebagai bait UTF-8. Jika anda hanya menulis grep -q '-', arahan itu akan mengesan tanda sempang biasa dan berjalan pada setiap fail. Aksara yang tidak kelihatan boleh merosakkan keseluruhan logik.
Hook 5. Bebaskan port 3000 sebelum 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"
}
]
}
]
}
}
Fungsinya: Sebelum setiap npm run dev (atau pnpm/yarn), hook mematikan proses pada port 3000. Hook sentiasa berakhir dengan exit 0 kerana ini langkah persediaan, bukannya sekatan. Ini mengelakkan satu jenis perangkap apabila Claude melihat “port in use”, menyangka ada masalah kod lalu mula membaiki sesuatu, sedangkan pelayan lama sebenarnya cuma masih berjalan.
Hook 6. Buat commit secara automatik selepas ujian berjaya (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'"
}
]
}
]
}
}
Fungsinya: Ia membaca JSON stdin sekali dan menerima arahan ujian biasa tepat yang ditunjukkan sahaja. Ia meneruskan hanya apabila tool_response.exit_code dibekalkan jelas sifar; jika versi dipasang tidak mendedahkan medan itu, ia melangkau commit daripada meneka kejayaan. Gantikan src/orders.ts dan tests/orders.test.ts dengan fail tepat milik tugasan. Perubahan staged sedia ada menghentikan resipi supaya kerja tidak berkaitan tidak disertakan. Add gagal menghentikannya, diff kosong tidak mencipta commit dan hook commit biasa kekal aktif. Uji input berjaya, gagal serta hasil tiada secara luar talian sebelum mendayakan.
Antipola: menambah git commit --no-verify pada setiap Edit. Kekalkan pemeriksaan commit aktif. Jika pemeriksaan mencetuskan automasi ini secara rekursif, sempitkan pencetus atau reka semula pemeriksaan; jangan pintas pengesahan secara lalai. Semak diff staged dan pemilikan tugasan sebelum mendayakan commit automatik.
Hook 7. Masukkan konteks terkini pada permulaan sesi (SessionStart dengan 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\\\"}\""
}
]
}
]
}
}
Fungsinya: Pada permulaan sesi, hook mengumpulkan cabang Git semasa dan senarai perubahan yang belum di-commit, kemudian mengembalikan JSON dengan medan additionalContext. Claude Code memasukkan teks ini ke dalam mesej sistem pertama, supaya Claude tahu dari awal kedudukannya dan perkara yang masih berbaki daripada sesi sebelumnya.
Gunakan additionalContext untuk maklumat yang patut diketahui Claude tentang keadaan semasa persekitaran atau operasi yang baru selesai: keadaan persekitaran (cabang semasa, sasaran penggunaan, feature flag aktif), peraturan projek bersyarat (arahan ujian yang terpakai pada fail yang baru disunting), data luaran (isu terbuka yang diberikan kepada anda, keputusan CI terkini).
Pengembangan untuk hook ini: ambil commit terkini dan keterangannya, status GitHub Actions, sprint aktif dalam Linear/Jira dan isu terbuka untuk repositori semasa.
3 masalah hooks yang memerangkap hampir setiap orang kedua
Perkara utama
Masalah pertama: hook dengan exit 1 berjaya secara senyap, lalu Claude mengabaikan ralat itu. Kedua: kerja berat dalam hook dihentikan selepas tamat masa 60 saat. Ketiga: hook hanya melihat pemboleh ubah persekitaran daripada ~/.zshrc, bukan .env projek. Setiap masalah boleh dibaiki dengan satu baris, tetapi tanpa mengetahui perkara ini, anda mungkin menyangka “hooks tidak berfungsi”.
Masalah 1. Hook dengan exit 1 berjaya secara senyap
Inilah masalah paling berbahaya. Selama seminggu, saya menyangka pelindung .env saya berfungsi, tetapi rupa-rupanya saya menggunakan jq -r '.tool_input.file_path' dalam hook tanpa menyemak null. Apabila tool_input kosong, jq keluar dengan kod 1. Claude menganggap exit 1 sebagai “ralat hook, teruskan”, lalu tindakan diteruskan. Saya tidak faham mengapa .env masih disentuh. Saya hanya menemui puncanya apabila menjalankan hook itu secara manual dalam terminal dengan input kosong.
Penyelesaiannya satu peraturan: mulakan setiap hook dengan menyemak null dan tamatkan dengan || exit 0. Sebarang keluar yang tidak dijangka akan menghasilkan keluar yang “selamat”, bukannya dilepaskan secara senyap.
# Safe start and end template:
FILE=$(jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0
# ... your logic ...
exit 0 # or || exit 0 on one line
Masalah 2. Hook yang perlahan dihentikan apabila tamat masa
Saya mempunyai hook yang menjalankan eslint --fix pada keseluruhan fail selepas Edit. Fail besar (1000+ baris) mengambil masa 8–10 saat untuk diproses. Tamat masa lalai hook Claude Code ialah 60 saat, jadi saya menyangka saya masih dalam had. Tetapi apabila beberapa suntingan berlaku dalam seminit, hooks bertimbun dan beratur, lalu sesetengahnya dilangkau begitu sahaja. Saya hanya menyedarinya apabila log menunjukkan “hook timed out”.
Penyelesaian: jika hook memerlukan kerja berat, jalankannya di latar belakang. Gunakan eslint --fix "$FILE" & tanpa menunggu hasilnya. Hook akan memulangkan exit 0 dalam beberapa milisaat sementara kerja sebenar berjalan di latar belakang.
# Heavy operation in background:
npx eslint --fix "$FILE" &
exit 0
Masalah 3. Hook tidak dapat melihat pemboleh ubah persekitaran projek
Saya menyangka process.env akan tersedia dalam hook seperti dalam aplikasi Node.js. Sebenarnya tidak. Hook berjalan dalam shell yang dimulakan oleh proses induk Claude Code dan hanya melihat perkara dalam ~/.zshrc atau ~/.bashrc, serta perkara yang disalurkan secara khusus oleh Claude Code. Jika hook anda bergantung pada OPENAI_API_KEY daripada .env, anda perlu membaca .env secara manual.
Penyelesaian: baca .env secara jelas dalam arahan hook.
# Passing project env into hook:
cd "$PWD" && source .env && curl -H "Authorization: Bearer $OPENAI_API_KEY" ...
# Or with dotenv:
dotenv -e .env -- node my-validator.js
Perkara ini amat menyusahkan dalam monorepo, yang mana pakej berlainan mempunyai fail .env masing-masing. Selesaikannya dengan menyalurkan PWD dan menjalankan cd "$PWD" secara jelas pada permulaan arahan.
Bagaimanakah hooks diuji sebelum commit?
Perkara utama
Hook ialah arahan shell. Anda boleh menjalankannya secara manual dalam terminal dengan stdin palsu, menyemak kod keluar dan stderr, dan melakukan semuanya sebelum Claude Code menjalankannya. Ini menjimatkan masa penyahpepijatan berjam-jam dan melindungi anda daripada hooks yang menyekat operasinya sendiri.
Senario ujian asas. Ambil arahan hook daripada JSON, buka terminal dan salurkan JSON yang akan dihantar oleh Claude Code:
# Test hook 1 (protect .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: $?"
Anda sepatutnya melihat BLOCKED dalam stderr dan Exit code: 2. Jika anda mendapat exit 0, regex anda tidak berfungsi; betulkan grep.
Senario yang perlu disemak:
- Laluan berjaya - fail sepatutnya disekat.
.envuntuk hook 1,git push --force mainuntuk hook 3. - Laluan negatif - fail tidak sepatutnya disekat.
README.mduntuk hook 1,git push origin feature-branchuntuk hook 3. - Kes pinggir - input kosong, nilai null, aksara yang tidak dijangka. Hook sepatutnya memulangkan exit 0 atau gagal dengan ralat yang jelas, bukannya melepaskan tindakan secara senyap.
Tempat untuk meletakkan hooks eksperimen. Bukan dalam .claude/settings.json, tetapi dalam .claude/settings.local.json (tidak dimasukkan dalam git). Letakkan hooks baharu di situ di bawah PostToolUse dengan echo sebagai ganti tindakan sebenar, semak sama ada hooks itu dicetuskan, kemudian pindahkannya ke settings.json produksi.
// Experiment in settings.local.json - writes to /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"
}
]
}
]
}
}
Selepas 5–10 suntingan dalam Claude Code, buka /tmp/hook-debug.log untuk melihat fail yang mencetuskan hook. Jika fail itu kosong, matcher tidak sepadan; betulkan regex.
Apa langkah seterusnya?
Perkara utama
Mulakan dengan hooks PostToolUse yang berakhir dengan exit 0; hooks ini paling selamat dan tidak menyekat apa-apa. Selepas seminggu, tambah hook PreToolUse pertama anda dengan exit 2 untuk melindungi .env atau mencegah force-push. Selepas dua minggu, CLAUDE.md akan mengecil daripada kontrak 200 baris kepada penerangan konteks ringkas sepanjang 50–80 baris, dengan pemeriksaan peristiwa terpilih dipindahkan ke hook dan had akses tegas dikuatkuasakan secara berasingan melalui kebenaran, sandbox serta perlindungan remote.
5 langkah untuk minggu akan datang:
- Cari dalam
CLAUDE.mdanda perkataan seperti “jangan sekali-kali”, “dilarang”, “sentiasa” dan “mesti”. Setiap peraturan sebegini ialah calon untuk dijadikan hook. Jika sesuatu peraturan berbentuk arahan, fail teks tidak akan menguatkuasakannya. - Mulakan dengan PostToolUse + exit 0. Ini pilihan paling selamat: ia membuat perubahan tetapi tidak menyekat apa-apa. Prettier (hook 2), mematikan pelayan dev (hook 5), commit automatik selepas ujian (hook 6).
- Tambah PreToolUse + exit 2 pertama anda hanya apabila sudah yakin. Contohnya, lindungi
.env(hook 1) atau cegah force-push (hook 3). Ini sekatan keras, dan kesilapan dalam arahan grep boleh menyekat anda sendiri. - Uji hooks secara manual sebelum commit (lihat bahagian di atas). Langkah ini menjimatkan masa penyahpepijatan berjam-jam.
- Gunakan
settings.local.jsonuntuk eksperimen. Letakkan hooks baharu di situ dengan echo sebagai ganti tindakan sebenar.
Selepas mengkonfigurasi hooks, langkah seterusnya dalam siri ini ialah cara membuat asal perubahan dalam Claude Code, sekiranya hook membiarkan sesuatu yang berbahaya terlepas. Jika anda mahu Claude mengingati struktur projek antara sesi, bina Otak Kedua dalam Claude Code (folder business/ + pangkalan pengetahuan yang dipautkan). Untuk memberikan nama kepada skills projek supaya boleh digunakan semula, lihat Claude Code Skills.
Sumber
Jika anda memerlukan akses kepada rangkaian neural melalui Ailoot, lihat Ailoot.
Butiran lanjut
Soalan lazim: Hooks dalam Claude Code 2026: persediaan langkah demi langkah dan 7 contoh sedia guna
Mengapakah hook mesti membaca input JSON sekali sahaja?
Stdin ialah strim: proses jq pertama menghabiskannya, meninggalkan bacaan kemudian pada EOF. Simpan input sekali, kemudian ekstrak medan arahan serta hasil daripada nilai disimpan. Anggap hasil tiada atau tidak diketahui sebagai belum disahkan dan langkau auto-commit.
Adakah hook regex contoh mencipta sempadan keselamatan?
Tidak. Ia memeriksa peristiwa khusus dan rentetan arahan dikenal pasti. Pengalihan shell, alias, skrip, alat MCP atau laluan tulis lain mungkin memintasnya; gunakan kelayakan terhad, kebenaran sistem fail, sandbox dan cabang dilindungi untuk had tegas.