Siapkan hook pertama Anda
Untuk membuat hook, tambahkan blokhooks ke file pengaturan. Panduan ini membuat hook notifikasi desktop, sehingga Anda mendapat peringatan kapan pun Claude menunggu input Anda daripada menonton terminal.
1
Tambahkan hook ke pengaturan Anda
Buka Jika file pengaturan Anda sudah memiliki kunci Anda juga dapat meminta Claude untuk menulis hook untuk Anda dengan mendeskripsikan apa yang Anda inginkan di CLI.
~/.claude/settings.json dan tambahkan hook Notification. Jika file tidak ada, buatlah. Contoh di bawah menggunakan osascript untuk macOS; lihat Dapatkan notifikasi ketika Claude memerlukan input untuk perintah Linux dan Windows.hooks, tambahkan Notification sebagai sibling dari kunci acara yang ada daripada mengganti seluruh objek. Setiap nama acara adalah kunci di dalam objek hooks tunggal:2
Verifikasi konfigurasi
Ketik
/hooks untuk membuka browser hooks. Anda akan melihat daftar semua acara hook yang tersedia, dengan hitungan di sebelah setiap acara yang memiliki hooks yang dikonfigurasi. Pilih Notification untuk mengonfirmasi hook baru Anda muncul dalam daftar. Memilih hook menampilkan detailnya: acara, matcher, jenis, file sumber, dan perintah.3
Uji hook
Tekan
Esc untuk kembali ke CLI. Tekan Shift+Tab hingga bilah status menunjukkan ⏸ manual mode on, minta Claude untuk melakukan sesuatu yang memerlukan izin, kemudian beralih dari terminal. Anda harus menerima notifikasi desktop.Apa yang dapat Anda otomatisasi
Hooks memungkinkan Anda menjalankan kode pada titik-titik kunci dalam siklus hidup Claude Code: format file setelah edit, blokir perintah sebelum dijalankan, kirim notifikasi ketika Claude memerlukan input, injeksi konteks saat awal sesi, dan banyak lagi. Untuk daftar lengkap acara hook, lihat Hooks reference. Setiap contoh mencakup blok konfigurasi siap pakai yang Anda tambahkan ke file pengaturan. Untuk contoh produksi hooks yang menjalankan review model terpisah dan mengirimkan temuan kembali ke sesi, lihat bagaimana pluginsecurity-guidance terintegrasi dengan Claude Code.
Dapatkan notifikasi ketika Claude memerlukan input
Dapatkan notifikasi desktop kapan pun Claude selesai bekerja dan memerlukan input Anda, sehingga Anda dapat beralih ke tugas lain tanpa memeriksa terminal. Hook ini menggunakan acaraNotification, yang Claude Code aktifkan ketika Claude menunggu input atau izin. Lihat kapan setiap jenis notifikasi aktif untuk waktu yang tepat. Setiap tab di bawah menggunakan perintah notifikasi asli platform. Tambahkan ini ke ~/.claude/settings.json:
- macOS
- Linux
- Windows (PowerShell)
Jika tidak ada notifikasi yang muncul
Jika tidak ada notifikasi yang muncul
osascript merutekan notifikasi melalui aplikasi Script Editor bawaan. Jika Script Editor tidak memiliki izin notifikasi, perintah gagal diam-diam, dan macOS tidak akan meminta Anda untuk memberikannya. Jalankan ini di Terminal sekali untuk membuat Script Editor muncul di pengaturan notifikasi Anda:matcher aktif pada semua jenis notifikasi. Untuk aktif hanya pada acara tertentu, atur ke salah satu nilai berikut:
Claude Code mengatur waktu
permission_prompt berbeda di terminal dan di Claude Desktop, ekstensi VS Code, dan host lain yang menjawab permintaan izin melalui Agent SDK. Lihat kapan setiap jenis notifikasi aktif untuk kedua waktu.
Matcher agent_needs_input dan agent_completed memerlukan Claude Code v2.1.198 atau lebih baru.
Matcher quota_auto_resume_fired, quota_auto_resume_stale, dan quota_auto_resume_disabled memerlukan Claude Code v2.1.234 atau lebih baru.
Dalam sesi terminal, permission_prompt untuk permintaan jaringan perintah sandboxed memerlukan Claude Code v2.1.246 atau lebih baru.
agent_needs_input untuk pertanyaan terminal setup teammate memerlukan Claude Code v2.1.248 atau lebih baru.
Ketik /hooks dan pilih Notification untuk mengonfirmasi hook terdaftar. Untuk skema acara lengkap, lihat Notification reference.
Auto-format kode setelah edit
Jalankan Prettier secara otomatis pada setiap file yang Claude edit, sehingga pemformatan tetap konsisten tanpa intervensi manual. Hook ini menggunakan acaraPostToolUse dengan matcher Edit|Write, sehingga hanya berjalan setelah alat pengeditan file. Perintah mengekstrak jalur file yang diedit dengan jq dan meneruskannya ke Prettier. Tambahkan ini ke .claude/settings.json di root proyek Anda:
Bash menulis ulangnya, gunakan hook FileChanged sebagai gantinya.
Contoh Bash di halaman ini menggunakan
jq untuk parsing JSON. Instal dengan brew install jq di macOS, apt-get install jq di Debian dan Ubuntu, atau lihat jq downloads.Blokir edit ke file yang dilindungi
Cegah Claude dari memodifikasi file sensitif seperti.env, package-lock.json, atau apa pun di .git/. Claude menerima umpan balik yang menjelaskan mengapa edit diblokir, sehingga dapat menyesuaikan pendekatannya.
Contoh ini menggunakan file skrip terpisah yang dipanggil hook. Skrip memeriksa jalur file target terhadap daftar pola yang dilindungi dan keluar dengan kode 2 untuk memblokir edit.
1
Buat skrip hook
Simpan ini ke
.claude/hooks/protect-files.sh:2
Buat skrip dapat dieksekusi di macOS dan Linux
Skrip hook harus dapat dieksekusi agar Claude Code dapat menjalankannya:
3
Daftarkan hook
Tambahkan hook
PreToolUse ke .claude/settings.json yang menjalankan skrip sebelum panggilan alat Edit atau Write:4
Uji hook
Minta Claude untuk menambahkan komentar ke file
.env Anda. Claude Code memblokir edit sebelum dijalankan dan meneruskan pesan Blocked: skrip ke Claude sebagai umpan balik.Re-inject konteks setelah compaction
Ketika jendela konteks Claude penuh, compaction merangkum percakapan untuk membebaskan ruang. Ini dapat kehilangan detail penting. Gunakan hookSessionStart dengan matcher compact untuk re-inject konteks kritis setelah setiap compaction.
Claude Code menambahkan teks biasa yang ditulis perintah Anda ke stdout ke konteks Claude. Contoh ini mengingatkan Claude tentang konvensi proyek dan pekerjaan terbaru. Tambahkan ini ke .claude/settings.json di root proyek Anda:
echo dengan perintah apa pun yang menghasilkan output dinamis, seperti git log --oneline -5 untuk menampilkan commit terbaru. Untuk injeksi konteks pada setiap awal sesi, pertimbangkan menggunakan CLAUDE.md sebagai gantinya. Untuk variabel lingkungan, lihat CLAUDE_ENV_FILE dalam referensi.
Audit perubahan konfigurasi
Lacak ketika file pengaturan atau skills berubah selama sesi. AcaraConfigChange aktif ketika proses eksternal atau editor memodifikasi file konfigurasi, sehingga Anda dapat mencatat perubahan untuk kepatuhan atau memblokir modifikasi yang tidak sah.
Contoh ini menambahkan setiap perubahan ke log audit. Tambahkan ini ke ~/.claude/settings.json:
user_settings, project_settings, local_settings, policy_settings, atau skills. Untuk memblokir perubahan agar tidak berlaku, keluar dengan kode 2 atau kembalikan {"decision": "block"}. Lihat ConfigChange reference untuk skema input lengkap.
Untuk mengonfirmasi hook mencatat perubahan, edit file pengaturan di editor lain saat sesi berjalan, kemudian buka ~/claude-config-audit.log: hook menambahkan satu baris JSON per perubahan dengan timestamp, sumber, dan jalur file.
Muat ulang lingkungan ketika direktori atau file berubah
Beberapa proyek menetapkan variabel lingkungan berbeda tergantung pada direktori mana Anda berada. Alat seperti direnv melakukan ini secara otomatis di shell Anda, tetapi alat Bash Claude tidak mengambil perubahan itu sendiri. Memasangkan hookSessionStart dengan hook CwdChanged memperbaiki ini. SessionStart memuat variabel untuk direktori tempat Anda meluncurkan, dan CwdChanged memuat ulang variabel setiap kali Claude mengubah direktori. Keduanya menulis ke CLAUDE_ENV_FILE, yang Claude Code jalankan sebagai preamble skrip sebelum setiap perintah Bash. Tambahkan ini ke ~/.claude/settings.json:
direnv allow sekali di setiap direktori yang memiliki .envrc sehingga direnv diizinkan untuk memuatnya. Jika Anda menggunakan devbox atau nix sebagai gantinya direnv, pola yang sama berfungsi dengan devbox shellenv atau devbox global shellenv sebagai pengganti direnv export bash.
Untuk bereaksi terhadap file spesifik daripada setiap perubahan direktori, gunakan FileChanged dengan matcher yang mencantumkan nama file yang akan dipantau, dipisahkan dengan |. Ketika membangun daftar pantau, Claude Code membagi nilai ini menjadi nama file literal daripada mengevaluasinya sebagai regex. Lihat FileChanged untuk cara nilai yang sama juga memfilter hook mana yang berjalan ketika file berubah. Contoh ini memantau .envrc dan .env di direktori kerja:
watchPaths, dan detail CLAUDE_ENV_FILE.
Auto-approve prompt izin tertentu
Lewati dialog persetujuan untuk panggilan alat yang selalu Anda izinkan. Contoh ini auto-approveExitPlanMode, alat yang Claude panggil ketika selesai menyajikan rencana dan meminta untuk melanjutkan, sehingga Anda tidak diminta setiap kali rencana siap.
Tidak seperti contoh kode keluar di atas, auto-approval memerlukan hook Anda untuk menulis keputusan JSON ke stdout. Claude Code menjalankan hook PermissionRequest ketika akan menanyakan Anda untuk izin, dan jika hook Anda mengembalikan "behavior": "allow", Claude Code menjawab permintaan atas nama Anda.
Matcher membatasi hook ke ExitPlanMode saja, sehingga tidak ada prompt lain yang terpengaruh. Tambahkan ini ke ~/.claude/settings.json:
updatedPermissions dengan entri setMode. Nilai mode adalah mode izin apa pun seperti default, acceptEdits, atau bypassPermissions, dan destination: "session" menerapkannya hanya untuk sesi saat ini.
bypassPermissions hanya berlaku jika Anda memulai sesi dengan mode bypass sudah tersedia: --dangerously-skip-permissions, --permission-mode bypassPermissions, --allow-dangerously-skip-permissions, atau permissions.defaultMode: "bypassPermissions" dalam pengaturan pengguna, --settings, atau pengaturan terkelola. Ini tidak berlaku jika mode bypass dinonaktifkan oleh permissions.disableBypassPermissionsMode, atau jika Anda memulai sesi dalam mode terbatas.Claude Code tidak pernah menyimpannya sebagai defaultMode.acceptEdits, hook Anda menulis JSON ini ke stdout:
.* atau membiarkan matcher kosong akan auto-approve setiap prompt izin alat, termasuk penulisan file dan perintah shell. Lihat PermissionRequest reference untuk set lengkap bidang keputusan.
Cara kerja hooks
Claude Code menjalankan acara hook pada titik-titik spesifik dalam siklus hidupnya. Ketika acara aktif, Claude Code menjalankan semua hook yang cocok secara paralel; lihat Hook handler fields untuk cara handler duplikat ditangani. Tabel di bawah menunjukkan setiap acara dan kapan dipicu:
Setiap hook memiliki
type yang menentukan cara menjalankannya. Sebagian besar hooks menggunakan "type": "command", yang menjalankan perintah shell. Empat jenis lain tersedia:
"type": "http": POST data acara ke URL. Lihat HTTP hooks."type": "mcp_tool": panggil alat pada server MCP yang sudah terhubung. Lihat MCP tool hooks."type": "prompt": evaluasi LLM single-turn. Lihat Prompt-based hooks."type": "agent": verifikasi multi-turn dengan akses alat. Agent hooks bersifat eksperimental dan mungkin berubah. Lihat Agent-based hooks.
Gabungkan hasil dari beberapa hooks
Ketika beberapa hooks cocok dengan acara yang sama, setiap perintah hook berjalan hingga selesai sebelum Claude Code menggabungkan hasilnya. Satu hook yang mengembalikandeny tidak menghentikan hook sibling dari eksekusi. Jangan andalkan deny dari satu hook untuk menekan efek samping di hook lain.
Setelah semua hooks yang cocok selesai, Claude Code menggabungkan output mereka. Untuk keputusan izin PreToolUse, jawaban yang paling ketat menang, dalam urutan deny, defer, ask, allow. Teks dari additionalContext disimpan dari setiap hook dan diteruskan ke Claude bersama-sama.
Contoh di bawah mendaftarkan dua hooks PreToolUse pada Bash. Yang pertama menambahkan setiap perintah ke file log dan keluar 0. Yang kedua menjalankan skrip yang keluar 2 untuk menolak ketika perintah berisi rm -rf:
rm -rf /tmp/build, kedua hooks dieksekusi secara paralel. Hook logging menulis perintah ke ~/.claude/bash.log dan keluar 0, yang melaporkan tidak ada keputusan. Hook guardrail keluar 2, yang menolak panggilan alat. Deny menang, jadi Claude Code memblokir perintah dan menunjukkan stderr guardrail kepada Claude. Entri log masih ditulis karena hook logging sudah berjalan.
Baca input dan kembalikan output
Hooks berkomunikasi dengan Claude Code melalui stdin, stdout, stderr, dan kode keluar. Ketika acara aktif, Claude Code meneruskan data spesifik acara sebagai JSON ke stdin skrip Anda. Skrip Anda membaca data itu, melakukan pekerjaan, dan memberi tahu Claude Code apa yang harus dilakukan selanjutnya melalui kode keluar.Hook input
Setiap acara mencakup bidang umum sepertisession_id, ID unik untuk sesi, dan cwd, direktori kerja ketika acara aktif, tetapi setiap jenis acara menambahkan data berbeda. Ketika Claude menjalankan perintah Bash, hook PreToolUse menerima bidang-bidang ini di stdin:
hook_event_name: acara yang memicu hooktool_name: alat yang akan digunakan Claudetool_input: argumen yang Claude teruskan ke alat. Untuk Bash, bidangcommandmenyimpan perintah shell.
npm test terlihat seperti ini:
UserPromptSubmit mendapatkan teks prompt sebagai gantinya, hook SessionStart mendapatkan source dari startup, resume, clear, compact, atau fork, dan seterusnya. Lihat Common input fields dalam referensi untuk bidang bersama, dan bagian setiap acara untuk skema spesifik acara.
Hook output
Skrip Anda memberi tahu Claude Code apa yang harus dilakukan selanjutnya dengan menulis ke stdout atau stderr dan keluar dengan kode spesifik. HookPreToolUse berikut memblokir perintah:
- Exit 0: hook Anda melaporkan tidak ada keberatan melalui kode keluarnya.
- Untuk hook
PreToolUseini tidak menyetujui panggilan alat: alur izin normal masih berlaku. - Untuk hook
UserPromptSubmit,UserPromptExpansion,SessionStart, danPostModelSwitch, Claude Code menambahkan stdout yang diperlakukan sebagai teks biasa ke konteks Claude.
- Untuk hook
- Exit 2: Claude Code memblokir tindakan. Tulis alasan ke stderr. Di mana itu mendarat tergantung pada acara: beberapa acara memberinya ke Claude sebagai umpan balik sehingga dapat menyesuaikan, yang lain menampilkannya kepada pengguna, dan beberapa, seperti
ConfigChangedanElicitation, tidak menampilkan pesan. Beberapa acara tidak dapat diblokir: untukSessionStartdan lainnya, exit 2 menampilkan stderr kepada pengguna dan eksekusi berlanjut. Lihat exit code 2 behavior per event untuk daftar lengkap. - Kode keluar lainnya: untuk sebagian besar acara, hasilnya tergantung pada apa yang dicetak hook Anda ke stdout:
- Objek yang diurai yang lulus validasi skema: Claude Code mengabaikan kode keluar, JSON saja yang menentukan hasilnya, dan hook tidak dilaporkan sebagai kesalahan. Pengecualian per-acara, seperti
WorktreeCreategagal pada kode keluar nonzero apa pun, tercantum di bagian Exit code output referensi. - Objek yang diurai yang gagal validasi skema, atau stdout yang Claude Code coba parse sebagai JSON tetapi bukan JSON yang valid: kesalahan non-blocking; pemberitahuan membawa pesan validasi atau parse.
- Stdout yang Claude Code diperlakukan sebagai teks biasa, atau stdout kosong: tindakan berlanjut sebagai kesalahan non-blocking. Transkrip menunjukkan pemberitahuan
<hook name> hook error, kemudian baris pertama stderr dengan awalanFailed with non-blocking status code:. Untuk menangkap stderr lengkap, aktifkan debug logging denganclaude --debugatau dengan menjalankan/debugdi tengah sesi.
- Objek yang diurai yang lulus validasi skema: Claude Code mengabaikan kode keluar, JSON saja yang menentukan hasilnya, dan hook tidak dilaporkan sebagai kesalahan. Pengecualian per-acara, seperti
Structured JSON output
Kode keluar hanya memberi Anda cara untuk memblokir atau tetap diam. Untuk kontrol lebih, keluar 0 dan cetak objek JSON ke stdout sebagai gantinya.Gunakan exit 2 untuk memblokir dengan pesan stderr, atau exit 0 dengan JSON untuk kontrol terstruktur. Pilih satu pendekatan per hook. Untuk apa yang terjadi ketika Anda mencampurnya, lihat Exit code output.
PreToolUse dapat menolak panggilan alat dan memberi tahu Claude mengapa, atau meningkatkannya ke pengguna untuk persetujuan:
"deny", Claude Code membatalkan panggilan alat dan memberi makan permissionDecisionReason kembali ke Claude.
Pada PreToolUse, Claude Code menangani setiap nilai permissionDecision sebagai berikut:
"allow": lewati prompt izin interaktif. Aturan deny dan ask, termasuk daftar deny yang dikelola perusahaan, masih berlaku, seperti juga prompt untuk MCP tools yang ditandairequiresUserInteractiondan untuk connector tools yang organisasi Anda atur keaskdalam sesi di mana pengaturan itu mencapai Claude Code"deny": batalkan panggilan alat dan kirim alasan ke Claude"ask": tampilkan prompt izin kepada pengguna seperti biasa
"defer", tersedia dalam non-interactive mode dengan flag -p. Ini keluar dari proses dengan panggilan alat yang dipertahankan sehingga pembungkus Agent SDK dapat mengumpulkan input dan melanjutkan. Lihat Defer a tool call for later dalam referensi.
Hook PreModelSwitch mengembalikan bidang permissionDecision yang sama: "allow" membiarkan switch model berlanjut, dan "deny" membatalkannya. "ask" membuat Anda mengonfirmasi switch ketika Anda menjalankan /model dalam sesi interaktif; di tempat lain, Claude Code memperlakukan "ask" sebagai penolakan. Lihat PreModelSwitch decision control.
Acara lain menggunakan pola keputusan berbeda. Misalnya, hook PostToolUse dan Stop menggunakan bidang decision: "block" tingkat atas, sementara PermissionRequest menggunakan hookSpecificOutput.decision.behavior. Lihat summary table dalam referensi untuk rincian lengkap berdasarkan acara.
Untuk hook UserPromptSubmit, gunakan hookSpecificOutput.additionalContext sebagai gantinya untuk menyuntikkan teks ke dalam konteks Claude. Sarangkan additionalContext di dalam hookSpecificOutput; jika Anda menempatkannya di tingkat atas JSON, Claude Code diam-diam mengabaikannya. Misalnya, output ini menambahkan status cabang saat ini ke setiap prompt:
type: "prompt" menangani output secara berbeda: lihat Prompt-based hooks.
Filter hooks dengan matchers
Tanpa matcher, hook aktif pada setiap kemunculan acaranya. Matchers memungkinkan Anda mempersempit itu. Misalnya, jika Anda ingin menjalankan formatter hanya setelah edit file, bukan setelah setiap panggilan alat, tambahkan matcher ke hookPostToolUse Anda:
"Edit|Write" aktif hanya ketika Claude menggunakan alat Edit atau Write, bukan ketika menggunakan Bash, Read, atau alat lainnya. Koma memisahkan alternatif dengan cara yang sama, jadi "Edit, Write" setara. Lihat Matcher patterns untuk cara nama biasa dan ekspresi reguler dievaluasi.
Claude juga dapat membuat atau memodifikasi file dengan menjalankan perintah shell. Jika hook Anda harus melihat setiap perubahan file, seperti untuk pemindaian kepatuhan atau pencatatan audit, tambahkan hook
Stop yang memindai pohon kerja sekali per giliran. Untuk cakupan per-panggilan sebagai gantinya, juga cocokkan Bash|PowerShell dan buat skrip Anda mencantumkan file yang dimodifikasi dan tidak dilacak dengan git status --porcelain. Bagian PowerShell hook input menjelaskan mengapa mencocokkan Bash saja tidak cukup. Untuk menjalankan hook ketika file spesifik berubah di disk, apa pun yang menulisnya, gunakan hook FileChanged.
Tab di bawah menunjukkan beberapa matchers lagi pada jenis acara berbeda.
- Catat setiap perintah Bash
- Cocokkan alat MCP
- Bersihkan saat akhir sesi
Cocokkan hanya panggilan alat
Bash dan catat setiap perintah ke file. Acara PostToolUse aktif setelah perintah selesai, jadi tool_input.command berisi apa yang berjalan. Hook menerima data acara sebagai JSON di stdin, dan jq -r '.tool_input.command' mengekstrak hanya string perintah, yang >> tambahkan ke file log:Filter berdasarkan nama alat dan argumen dengan bidang if
Bidang if menggunakan sintaks aturan izin untuk memfilter hooks berdasarkan nama alat dan argumen bersama-sama, sehingga proses hook hanya muncul ketika panggilan alat cocok. Ini melampaui matcher, yang memfilter pada tingkat grup berdasarkan nama alat saja.
Misalnya, konfigurasi ini menjalankan hook hanya ketika Claude menggunakan perintah git daripada semua perintah Bash:
if Anda dan perintah Bash yang Claude panggil:
Ketika Claude Code tidak dapat menentukan perintah mana yang dijalankan input Bash, itu menjalankan hook Anda terlepas dari pola. Tabel pencocokan Bash mencakup bentuk perintah yang dapat dan tidak dapat dipersempit Claude Code berdasarkan subperintah. Karena filter adalah best-effort, gunakan sistem izin daripada hook untuk memberlakukan allow atau deny yang keras.
Bidang
if menerima pola yang sama seperti aturan izin: "Bash(git *)", "Edit(*.ts)", dan seterusnya. Untuk mencocokkan beberapa nama alat, gunakan handler terpisah masing-masing dengan nilai if sendiri, atau cocokkan pada tingkat matcher di mana alternasi pipa didukung.
if hanya bekerja pada acara alat: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, dan PermissionDenied. Menambahkannya ke acara lain mencegah hook dari berjalan.
Konfigurasi lokasi hook
Di mana Anda menambahkan hook menentukan cakupannya:
Jalankan
/hooks di Claude Code untuk menjelajahi semua hooks yang dikonfigurasi dikelompokkan berdasarkan acara.
Untuk menonaktifkan hooks, atur "disableAllHooks": true dalam file pengaturan Anda. Claude Code membaca nilai yang tersisa setelah settings precedence diterapkan, jadi file pengaturan proyek dapat mengesampingkan milik Anda. Hooks yang dikonfigurasi dalam pengaturan terkelola masih berjalan kecuali disableAllHooks juga diatur di sana. Untuk jangkauan penuh setiap level, lihat disableAllHooks.
Jika Anda mengedit file pengaturan secara langsung saat Claude Code berjalan, file watcher biasanya mengambil perubahan hook secara otomatis.
Prompt-based hooks
Untuk keputusan yang memerlukan penilaian daripada aturan deterministik, gunakan hooktype: "prompt". Daripada menjalankan perintah shell, Claude Code mengirim prompt Anda dan data input hook ke model Claude untuk membuat keputusan. Anda dapat menentukan model berbeda dengan bidang model jika Anda memerlukan kemampuan lebih.
Satu-satunya pekerjaan model adalah mengembalikan keputusannya sebagai JSON:
"ok": true: tindakan berlanjut"ok": false: apa yang terjadi tergantung pada peristiwa:StopdanSubagentStop:reasondiberi makan kembali ke Claude sehingga terus bekerja, kecuali respons juga menetapkan"impossible": trueuntuk menandai kondisi sebagai salah satu yang tidak dapat pernah dipenuhi, dalam hal ini Claude Code memungkinkan stop dan giliran berakhirPreToolUse: panggilan alat ditolak; secara default giliran berakhir danreasonpenolakan muncul dalam obrolan sebagai baris peringatan. AturcontinueOnBlock: truepada hook untuk sebagai gantinya mengembalikanreasonke Claude sebagai kesalahan alat, sehingga dapat menyesuaikan dan melanjutkan. Sebelum v2.1.210,reasonpenolakan dikembalikan ke Claude sebagai kesalahan alat dan giliran berlanjutPostToolUse: secara default giliran berakhir danreasonmuncul dalam obrolan sebagai baris peringatan. AturcontinueOnBlock: trueuntuk memberi makanreasonkembali ke Claude dan melanjutkan giliran sebagai gantinyaPostToolBatch,UserPromptSubmit, danUserPromptExpansion: giliran berakhir danreasonmuncul dalam obrolan sebagai baris peringatan
Stop untuk menanyakan kepada model apakah semua tugas yang diminta selesai. Jika model mengembalikan "ok": false karena kondisi belum terpenuhi, Claude terus bekerja dan menggunakan reason sebagai instruksi berikutnya:
Agent-based hooks
Ketika verifikasi memerlukan inspeksi file atau menjalankan perintah, gunakan hooktype: "agent". Tidak seperti hook prompt yang membuat panggilan LLM tunggal, hook agent menelurkan subagent yang dapat membaca file, mencari kode, dan menggunakan alat lain untuk memverifikasi kondisi sebelum mengembalikan keputusan.
Hook agent menggunakan format respons "ok" / "reason" dengan timeout default lebih lama 60 detik dan hingga 50 putaran penggunaan alat. Mereka tidak mendukung bidang impossible dari hook prompt. Pada ok: false, Claude Code menangani hook agent dengan cara yang sama seperti menangani hook prompt dengan continueOnBlock: true pada acara yang sama, jadi pada PreToolUse dan PostToolUse giliran berlanjut; hook agent tidak memiliki bidang continueOnBlock. Lihat konfigurasi agent hook untuk bidang-bidangnya, termasuk placeholder $ARGUMENTS yang Claude Code ganti dengan input JSON hook.
Contoh ini memverifikasi bahwa tes lulus sebelum memungkinkan Claude berhenti:
HTTP hooks
Gunakan hooktype: "http" untuk POST data acara ke endpoint HTTP daripada menjalankan perintah shell. Endpoint menerima JSON yang sama yang diterima hook perintah di stdin, dan mengembalikan hasil melalui badan respons HTTP menggunakan format JSON yang sama.
HTTP hooks berguna ketika Anda ingin server web, fungsi cloud, atau layanan eksternal menangani logika hook: misalnya, layanan audit bersama yang mencatat acara penggunaan alat di seluruh tim.
Contoh ini memposting setiap penggunaan alat ke layanan logging lokal:
hookSpecificOutput yang sesuai. Kode status HTTP saja tidak dapat memblokir tindakan.
Nilai header mendukung interpolasi variabel lingkungan menggunakan sintaks $VAR_NAME atau ${VAR_NAME}. Hanya variabel yang tercantum dalam array allowedEnvVars yang diselesaikan; semua referensi $VAR lainnya tetap kosong.
Untuk opsi konfigurasi lengkap dan penanganan respons, lihat HTTP hooks dalam referensi.
Keterbatasan dan troubleshooting
Keterbatasan
Pertimbangkan batasan-batasan ini saat merancang hooks:- Command hooks berkomunikasi melalui stdout, stderr, dan kode keluar saja. Mereka tidak dapat memicu perintah
/atau panggilan alat. Teks yang dikembalikan melaluiadditionalContextdisuntikkan sebagai pengingat sistem yang Claude baca sebagai teks biasa. HTTP hooks berkomunikasi melalui badan respons sebagai gantinya. - Timeout hook bervariasi menurut jenis. Timpa per hook dengan bidang
timeoutdalam detik.command,http,mcp_tool: 10 menit. Claude Code menurunkan default ini menjadi 30 detik untuk hookUserPromptSubmit,PreModelSwitch, danPostModelSwitch, dan menjadi 10 detik untuk hookMessageDisplay.prompt: 30 detik.agent: 60 detik.- Hook
SessionEnddari jenis apa pun berbagi anggaran 1,5 detik. Jika pengaturan Anda menetapkantimeoutper-hook yang lebih lama, Claude Code menaikkan anggaran untuk cocok, hingga 60 detik.
- Hook
PostToolUsetidak dapat membatalkan tindakan karena alat sudah dieksekusi. - Hook
PermissionRequestaktif ketika Claude Code akan meminta Anda untuk izin.- Dalam mode non-interaktif dengan flag
-p, prompt itu hanya ada ketika callbackcanUseToolAgent SDK menyediakannya. Dalam menjalankan-pbiasa atau dengan--permission-prompt-tool, gunakan hookPreToolUseuntuk keputusan izin otomatis sebagai gantinya. - Subagen latar belakang tidak dapat menampilkan prompt dalam mode non-interaktif. Claude Code masih menjalankan hook untuk panggilan alat mereka, dan jika tidak ada hook yang mengembalikan keputusan, itu menolak panggilan. Dalam sesi interaktif, prompt subagen latar belakang muncul di sesi utama Anda dan hook aktif seperti biasa.
- Dalam mode non-interaktif dengan flag
- Hook
Stopaktif kapan pun Claude selesai merespons, bukan hanya pada penyelesaian tugas. Mereka tidak aktif pada interupsi pengguna. Kesalahan API menjalankan StopFailure sebagai gantinya. - Ketika beberapa hook
PreToolUsemengembalikanupdatedInputuntuk menulis ulang argumen alat, yang terakhir selesai menang. Karena hooks berjalan secara paralel, urutannya tidak deterministik. Hindari memiliki lebih dari satu hook memodifikasi input alat yang sama.
Hooks dan mode izin
HookPreToolUse aktif sebelum pemeriksaan mode izin apa pun, dalam setiap mode izin, termasuk dontAsk. Hook yang mengembalikan permissionDecision: "deny" memblokir alat bahkan dalam mode bypassPermissions atau dengan --dangerously-skip-permissions. Ini memungkinkan Anda menegakkan kebijakan yang pengguna tidak dapat lewati dengan mengubah mode izin mereka.
Kebalikannya tidak benar: hook yang mengembalikan "allow" tidak melewati aturan deny dari pengaturan, dan tidak dapat menekan prompt untuk alat MCP yang ditandai requiresUserInteraction atau untuk alat konektor organisasi Anda atur ke ask dalam sesi di mana pengaturan itu mencapai Claude Code. Hooks dapat mengetatkan pembatasan tetapi tidak melonggarkan mereka melampaui apa yang aturan izin izinkan.
Hook tidak aktif
Hook dikonfigurasi tetapi tidak pernah dieksekusi.- Jalankan
/hooksdan konfirmasi hook muncul di bawah acara yang benar - Periksa bahwa pola matcher cocok dengan nama alat dengan tepat. Matchers peka huruf besar-kecil
- Verifikasi Anda memicu jenis acara yang benar:
PreToolUseaktif sebelum eksekusi alat,PostToolUseaktif setelah. HookPermissionRequestaktif ketika Claude Code akan meminta Anda untuk izin; lihat keterbatasan untuk kasus non-interaktif
Hook error dalam output
Anda melihat pesan seperti “PreToolUse hook error: …” dalam transkrip.-
Skrip Anda keluar dengan kode non-nol secara tidak terduga. Uji secara manual dengan menyalurkan JSON sampel:
-
Jika Anda melihat “command not found”, gunakan jalur absolut atau
${CLAUDE_PROJECT_DIR}untuk mereferensikan skrip. Untuk menghindari quoting shell sepenuhnya, tambahkan"args": []untuk beralih ke exec form, yang menelurkan skrip secara langsung tanpa shell -
Jika Anda melihat “jq: command not found”, instal
jqatau gunakan Python/Node.js untuk parsing JSON -
Jika pemberitahuan menampilkan pesan validasi JSON, stdout hook Anda diurai sebagai JSON tetapi gagal validasi skema. Jika menampilkan pesan parsing JSON, stdout terlihat seperti objek JSON tetapi bukan JSON yang valid. Keduanya terjadi bahkan pada exit 0.
Untuk memperbaiki kegagalan parsing, bangun payload dengan encoder JSON seperti
jqdaripada penggabungan string, sehingga tanda kutip dan garis miring terbalik di dalam nilai diloloskan. Bagian Exit code output referensi mencakup kombinasi kode keluar dan JSON -
Jika skrip tidak berjalan sama sekali, buat dapat dieksekusi:
chmod +x ./my-hook.sh
/hooks menunjukkan tidak ada hooks yang dikonfigurasi
Anda mengedit file pengaturan tetapi hooks tidak muncul dalam menu.
- Edit file biasanya diambil secara otomatis. Jika belum muncul setelah beberapa detik, file watcher mungkin melewatkan perubahan: mulai ulang sesi Anda untuk memaksa reload.
- Verifikasi JSON Anda valid: trailing commas dan comments tidak diizinkan
- Konfirmkan file pengaturan berada di lokasi yang benar:
.claude/settings.jsonuntuk hook proyek,~/.claude/settings.jsonuntuk hook global
Stop hook mencapai batas blokir
Claude terus bekerja daripada berhenti, kemudian mengakhiri giliran dengan peringatan bahwa Stop hook memblokir terlalu banyak kali berturut-turut. Claude Code menimpa Stop hook setelah memblokir delapan kali berturut-turut tanpa kemajuan. Skrip hook Anda perlu memeriksa apakah sudah memicu kelanjutan. Parse bidangstop_hook_active dari input JSON dan keluar lebih awal jika true:
CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.
Hook JSON tidak memiliki efek
Hook Anda mencetak JSON yang valid, tetapi keputusan tidak berlaku dan tidak ada kesalahan yang muncul dalam transkrip. Periksa penyebab mana yang berlaku:- Output tambahan sebelum JSON: sesuatu yang lain menulis ke stdout terlebih dahulu, biasanya
echotanpa syarat dalam profil shell Anda, sehingga output tidak lagi dimulai dengan{dan Claude Code tidak menguraikannya sebagai JSON. Penyebab dan perbaikan mengikuti daftar ini. - Bidang di level yang salah: bandingkan penempatan setiap bidang terhadap format JSON output. Misalnya,
permissionDecisionmilik di dalamhookSpecificOutput, bukan di level atas.
args, ia menelurkan sh -c pada macOS dan Linux, Git Bash pada Windows, atau PowerShell ketika Git Bash tidak diinstal secara default. Shell ini non-interaktif, tetapi Git Bash dan beberapa konfigurasi, seperti BASH_ENV menunjuk ke ~/.bashrc, masih bersumber dari profil Anda. Jika profil itu berisi pernyataan echo tanpa syarat, output itu ditambahkan ke JSON hook Anda:
{, jadi Claude Code memperlakukan semua stdout sebagai teks biasa dan mengabaikan JSON. Pada exit 0 tidak ada yang dilaporkan dalam transkrip; upaya parsing hanya dicatat dalam debug log. Untuk memperbaiki ini, bungkus pernyataan echo dalam profil shell Anda sehingga hanya berjalan di shell interaktif:
$- berisi flag shell, dan i berarti interaktif. Hooks berjalan di shell non-interaktif, jadi echo dilewati.
Ketika hook Anda mengembalikan permissionDecision atau additionalContext di level atas daripada di dalam hookSpecificOutput, JSON masih diurai, dan Claude Code mengabaikan bidang yang salah tempat tanpa melaporkan kesalahan. Untuk melihat bidang mana yang diabaikannya, mulai Claude Code dengan claude --debug dan cari debug log untuk Hook JSON output had unrecognized keys.
Teknik debug
TekanCtrl+O untuk membuka tampilan transkrip untuk memeriksa hasil dari jalankan hook:
- Jalankan berhasil: Anda tidak melihat apa pun, kecuali JSON hook muncul sesuatu, seperti
systemMessageatau umpan balik Stop hook.- Untuk mengonfirmasi hook berjalan, periksa efeknya, seperti file yang diformat ulang, atau aktifkan debug logging seperti dijelaskan di bawah dan picu hook lagi
- Kesalahan pemblokiran: pada sebagian besar acara Anda melihat umpan balik hook. Ketika JSON hook membuat keputusan pemblokiran, umpan balik adalah alasan dari keputusan itu; jika tidak, itu adalah stderr hook. Pada beberapa acara, seperti
ConfigChangedanElicitation, blok tidak menampilkan pesan. - Kesalahan non-pemblokiran: tindakan dilanjutkan, dan Anda melihat pemberitahuan
<hook name> hook errordengan penjelasan singkat, seperti baris pertama stderr dengan awalanFailed with non-blocking status code:, atau pesan validasi JSON atau parsing.
claude --debug-file /tmp/claude.log untuk menulis ke jalur yang diketahui, kemudian tail -f /tmp/claude.log di terminal lain. Jika Anda memulai tanpa flag itu, jalankan /debug di tengah sesi untuk mengaktifkan logging dan temukan jalur log.
Pelajari lebih lanjut
- Hooks reference: skema acara lengkap, format output JSON, async hooks, dan MCP tool hooks
- Security considerations: tinjau sebelum menerapkan hooks dalam lingkungan bersama atau produksi
- Bash command validator example: implementasi referensi lengkap