476| `async` | tidak | Jika `true`, dijalankan di latar belakang tanpa memblokir. Lihat [Run hooks in the background](#run-hooks-in-the-background) |476| `async` | tidak | Jika `true`, dijalankan di latar belakang tanpa memblokir. Lihat [Run hooks in the background](#run-hooks-in-the-background) |
477| `asyncRewake` | tidak | Jika `true`, dijalankan di latar belakang dan membangunkan Claude pada kode keluar 2. Hook stderr, atau stdout jika stderr kosong, ditampilkan ke Claude sebagai [system reminder](/docs/id/glossary#system-reminder) sehingga dapat bereaksi terhadap kegagalan latar belakang yang berjalan lama |477| `asyncRewake` | tidak | Jika `true`, dijalankan di latar belakang dan membangunkan Claude pada kode keluar 2. Hook stderr, atau stdout jika stderr kosong, ditampilkan ke Claude sebagai [system reminder](/docs/id/glossary#system-reminder) sehingga dapat bereaksi terhadap kegagalan latar belakang yang berjalan lama |
478| `shell` | tidak | Shell untuk digunakan untuk hook ini. Menerima `"bash"` atau `"powershell"`. Default ke `"bash"`, atau ke `"powershell"` di Windows ketika Git Bash tidak diinstal. Menetapkan `"powershell"` menjalankan perintah melalui PowerShell di Windows. Tidak memerlukan `CLAUDE_CODE_USE_POWERSHELL_TOOL` karena hooks spawn PowerShell secara langsung. Diabaikan ketika `args` diatur |478| `shell` | tidak | Shell untuk digunakan untuk hook ini. Menerima `"bash"` atau `"powershell"`. Default ke `"bash"`, atau ke `"powershell"` di Windows ketika Git Bash tidak diinstal. Menetapkan `"powershell"` menjalankan perintah melalui PowerShell di Windows. Tidak memerlukan `CLAUDE_CODE_USE_POWERSHELL_TOOL` karena hooks spawn PowerShell secara langsung. Diabaikan ketika `args` diatur |
479| `onFailure` | tidak | Apa yang terjadi pada tindakan ketika hook gagal: `"continue"`, yang merupakan default, atau `"block"`. Lihat [Blokir tindakan ketika hook gagal](#block-the-action-when-a-hook-fails). Memerlukan Claude Code v2.1.295 atau lebih baru |
479 480
480<a id="exec-form-and-shell-form" />481<a id="exec-form-and-shell-form" />
481 482
533| `url` | ya | URL untuk mengirimkan permintaan POST ke |534| `url` | ya | URL untuk mengirimkan permintaan POST ke |
534| `headers` | tidak | Header HTTP tambahan sebagai pasangan kunci-nilai. Nilai mendukung interpolasi variabel lingkungan menggunakan sintaks `$VAR_NAME` atau `${VAR_NAME}`. Hanya variabel yang tercantum dalam `allowedEnvVars` yang diselesaikan |535| `headers` | tidak | Header HTTP tambahan sebagai pasangan kunci-nilai. Nilai mendukung interpolasi variabel lingkungan menggunakan sintaks `$VAR_NAME` atau `${VAR_NAME}`. Hanya variabel yang tercantum dalam `allowedEnvVars` yang diselesaikan |
535| `allowedEnvVars` | tidak | Daftar nama variabel lingkungan yang dapat diinterpolasi ke nilai header. Referensi ke variabel yang tidak tercantum diganti dengan string kosong. Diperlukan untuk interpolasi variabel env apa pun untuk bekerja |536| `allowedEnvVars` | tidak | Daftar nama variabel lingkungan yang dapat diinterpolasi ke nilai header. Referensi ke variabel yang tidak tercantum diganti dengan string kosong. Diperlukan untuk interpolasi variabel env apa pun untuk bekerja |
537| `onFailure` | tidak | Apa yang terjadi pada tindakan ketika hook gagal: `"continue"`, yang merupakan default, atau `"block"`. Lihat [Blokir tindakan ketika hook gagal](#block-the-action-when-a-hook-fails). Memerlukan Claude Code v2.1.295 atau lebih baru |
536 538
537Claude Code mengirimkan [JSON input](#hook-input-and-output) hook sebagai badan permintaan POST dengan `Content-Type: application/json`. Badan respons menggunakan [format JSON output](#json-output) yang sama seperti command hooks.539Claude Code mengirimkan [JSON input](#hook-input-and-output) hook sebagai badan permintaan POST dengan `Content-Type: application/json`. Badan respons menggunakan [format JSON output](#json-output) yang sama seperti command hooks.
538 540
821 Output exit code823 Output exit code
822</h3>824</h3>
823 825
824Exit code dari perintah hook Anda memberi tahu Claude Code apakah tindakan harus dilanjutkan, diblokir, atau diabaikan. Exit code tidak bekerja sendiri. Claude Code membaca [field output JSON](#json-output) dari stdout pada setiap exit code, bukan hanya 0, dan untuk event yang menggunakan model keputusan standar, objek yang berhasil di-parse dan lolos validasi skema berlaku bersamaan dengan kode tersebut. Pemblokiran oleh exit 2 adalah satu-satunya hasil yang tidak dapat ditimpa oleh JSON.826Exit code hook Anda memberi tahu Claude Code apakah akan melanjutkan tindakan yang memicu hook, seperti panggilan tool atau prompt. Eksekusi yang selesai memiliki salah satu dari tiga hasil:
825 827
826Dua tabel memuat pengecualian per event: [Perilaku exit code 2 per event](#exit-code-2-behavior-per-event) menjelaskan apa yang dilakukan exit code untuk setiap event, dan [Kontrol keputusan](#decision-control) menjelaskan field keputusan mana yang dihormati setiap event. Field universal seperti `systemMessage` berfungsi di sebagian besar event dan tercantum dalam tabel [output JSON](#json-output).828* **Berhasil**: hook Anda keluar dengan 0. Claude Code menerapkan field [output JSON](#json-output) apa pun yang dicetak hook Anda, dan tindakan dilanjutkan kecuali field tersebut memblokir atau menolaknya.
829* **Error blocking**: hook Anda keluar dengan 2. Pada [event yang dapat memblokir](#exit-code-2-behavior-per-event), Claude Code menghentikan tindakan.
830* **Error non-blocking**: hook Anda keluar dengan kode lain, atau gagal dengan cara lain, seperti tidak dapat dimulai atau mencetak JSON yang tidak valid. Tindakan dilanjutkan, dan pada event seperti `PreToolUse` Anda melihat pemberitahuan `<hook name> hook error` di transkrip. Jika Anda ingin hook yang gagal memblokir tindakan, atur [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
831
832Apa yang dicetak hook Anda ke stdout dapat mengubah hasilnya. Misalnya, jika hook `PreToolUse` keluar dengan 1 tetapi mencetak JSON yang lolos validasi, eksekusi dianggap berhasil dan field JSON menentukan apa yang terjadi. Untuk menemukan hasil hook Anda pada event seperti `PreToolUse`, cocokkan apa yang dicetaknya ke stdout di kolom pertama dengan exit code-nya di bagian atas:
833
834| Stdout | Exit 0 | Exit 2 | Exit code lainnya |
835| :- | :- | :- | :- |
836| Objek JSON yang lolos [validasi skema](#json-output) | Berhasil. Field diterapkan | Error blocking. Claude Code tetap membaca field, tetapi field tersebut tidak dapat menimpa pemblokiran | Berhasil. Claude Code mengabaikan exit code, dan hanya field yang menentukan. Dengan [`onFailure: "block"`](#block-the-action-when-a-hook-fails), ini dihitung sebagai kegagalan |
837| JSON yang [tidak dapat di-parse](#exit-code-0) atau gagal validasi skema | Error non-blocking. Pemberitahuan memuat pesan parse atau validasi | Error blocking. Stderr Anda menjadi alasannya | Error non-blocking. Pemberitahuan memuat pesan parse atau validasi |
838| [Teks biasa](#exit-code-0), atau tidak ada apa pun | Berhasil | Error blocking. Stderr Anda menjadi alasannya | Error non-blocking. Pemberitahuan memuat baris pertama stderr Anda |
839
840Beberapa event memiliki aturannya sendiri:
841
842* **`WorktreeCreate`**: exit code bukan nol apa pun membuat pembuatan worktree gagal, apa pun isi JSON Anda.
843* **`WorktreeRemove`**: exit code bukan nol apa pun membuat penghapusan worktree gagal jika direktori masih ada setelahnya.
844* **`Stop`, `SubagentStop`, `TaskCompleted`, dan hook `UserPromptSubmit` dari plugin**: ketika hook Anda keluar dengan 2 tanpa apa pun di stdout dan stderr-nya menyatakan bahwa suatu file tidak ada, seperti `No such file or directory`, Claude Code memperlakukan eksekusi tersebut sebagai error non-blocking.
845* **`Elicitation` dan `ElicitationResult`**: Claude Code menerapkan `hookSpecificOutput` Anda ketika hook Anda keluar dengan 0, dan mengabaikannya pada exit code lainnya.
846* **Event yang membuang output hook, seperti `StopFailure`**: Claude Code mengabaikan JSON Anda pada setiap exit code, kecuali field efek samping seperti `terminalSequence`, yang tetap dijalankan.
847
848Untuk memeriksa apa yang dilakukan exit code 2 pada event Anda, lihat [Perilaku exit code 2 per event](#exit-code-2-behavior-per-event). Untuk memeriksa field keputusan mana yang dihormatinya, lihat [Kontrol keputusan](#decision-control).
827 849
828<h4 id="exit-code-0">850<h4 id="exit-code-0">
829 Exit code 0851 Exit code 0
835 857
836Apakah Claude Code membaca stdout Anda sebagai [output JSON](#json-output) atau sebagai teks biasa bergantung pada bagaimana stdout diawali dan diakhiri, dengan mengabaikan whitespace di sekitarnya:858Apakah Claude Code membaca stdout Anda sebagai [output JSON](#json-output) atau sebagai teks biasa bergantung pada bagaimana stdout diawali dan diakhiri, dengan mengabaikan whitespace di sekitarnya:
837 859
838* **Diawali dengan `{` dan diakhiri dengan `}`**: Claude Code mem-parse-nya sebagai JSON. Ketika output terdiri dari dua baris atau lebih yang masing-masing dapat di-parse sebagai JSON secara terpisah, dan tidak ada baris yang merupakan objek [output JSON](#json-output) yang mengatur suatu field, Claude Code memperlakukan seluruh output sebagai teks biasa. Ketika salah satu baris tersebut mengatur suatu field, seluruh output dianggap gagal di-parse, seperti dijelaskan di bawah.860* **Diawali dengan `{` dan diakhiri dengan `}`**: Claude Code mem-parse-nya sebagai JSON. Ketika output terdiri dari dua baris atau lebih yang masing-masing dapat di-parse sebagai JSON secara terpisah, dan tidak ada baris yang merupakan objek [output JSON](#json-output) yang mengatur suatu field, Claude Code memperlakukan seluruh output sebagai teks biasa. Ketika salah satu baris tersebut mengatur suatu field, seluruh output dianggap gagal di-parse.
839* **Diawali dengan `{` tetapi tidak diakhiri dengan `}`**: Claude Code memperlakukannya sebagai teks biasa.861* **Diawali dengan `{` tetapi tidak diakhiri dengan `}`**: Claude Code memperlakukannya sebagai teks biasa.
840* **Diawali dengan hal lain**: Claude Code memperlakukannya sebagai teks biasa, termasuk array JSON atau string JSON yang diberi tanda kutip.862* **Diawali dengan hal lain**: Claude Code memperlakukannya sebagai teks biasa, termasuk array JSON atau string JSON yang diberi tanda kutip.
841 863
842Untuk event yang menggunakan model keputusan standar, exit 0 dengan objek yang berhasil di-parse tetapi gagal validasi skema adalah error non-blocking: tindakan dilanjutkan, dan transkrip menampilkan pemberitahuan `<hook name> hook error` dengan pesan validasi. Hal yang sama terjadi pada exit code apa pun selain 2, sementara [exit 2 tetap memblokir](#exit-code-2).864Ketika Claude Code mencoba mem-parse stdout Anda sebagai JSON dan gagal, atau objek yang di-parse gagal [validasi skema](#json-output), eksekusi tersebut adalah [error non-blocking](#exit-code-output). Pemberitahuan `<hook name> hook error` memuat pesan parse atau validasi. Pada event yang menambahkan stdout teks biasa sebagai konteks, Claude Code tidak menambahkan stdout yang gagal di-parse.
843
844Untuk event yang menggunakan model keputusan standar, ketika Claude Code mencoba mem-parse stdout Anda sebagai JSON dan gagal, Claude Code melaporkan error non-blocking pada setiap exit code selain 2. Transkrip menampilkan pemberitahuan `<hook name> hook error` dengan pesan parse. Pada event yang menambahkan stdout teks biasa sebagai konteks, Claude Code tidak menambahkan teks tersebut. Sebelum v2.1.248, Claude Code memperlakukan stdout tersebut sebagai teks biasa.
845 865
846Stderr dari hook yang keluar dengan 0 hanya masuk ke log debug, tidak pernah ke transkrip, dan Claude tidak pernah melihatnya. Untuk membacanya sendiri, aktifkan [logging debug](#debug-hooks). Untuk menyampaikan peringatan kepada Claude dari hook `PostToolUse` atau `PostToolUseFailure`, gunakan exit 2 sehingga [Claude melihat stderr](#exit-code-2-behavior-per-event) meskipun tool sudah berjalan.866Claude tidak pernah melihat stderr dari hook yang keluar dengan 0. Untuk membacanya sendiri pada event seperti `PreToolUse`, aktifkan [logging debug](#debug-hooks). Untuk menyampaikan peringatan kepada Claude dari hook `PostToolUse` atau `PostToolUseFailure`, gunakan exit 2 sehingga [Claude melihat stderr](#exit-code-2-behavior-per-event) meskipun tool sudah berjalan.
847 867
848<h4 id="exit-code-2">868<h4 id="exit-code-2">
849 Exit code 2869 Exit code 2
850</h4>870</h4>
851 871
852Exit 2 berarti error blocking. Pada [event yang dapat memblokir](#exit-code-2-behavior-per-event), exit 2 memblokir terlepas dari apakah Anda mencetak JSON atau tidak: bahkan `permissionDecision` JSON bernilai `"allow"` tidak dapat menimpanya. Claude Code tetap membaca [output JSON](#json-output) yang valid di stdout. Pada `Elicitation` dan `ElicitationResult`, `hookSpecificOutput` dari hook yang keluar dengan exit 2 diabaikan.872Keluar dengan kode 2 untuk memblokir tindakan. Pada [event yang dapat memblokir](#exit-code-2-behavior-per-event), Claude Code menghentikan tindakan: misalnya, hook `PreToolUse` memblokir panggilan tool, dan hook `UserPromptSubmit` menolak prompt.
853 873
854Pesan pemblokiran adalah alasan dari keputusan pemblokiran dalam JSON Anda jika ada, dan teks stderr Anda jika tidak. Apa yang dilakukan pemblokiran bervariasi menurut event: `PreToolUse` memblokir panggilan tool, `UserPromptSubmit` menolak prompt, dan seterusnya. [Perilaku exit code 2 per event](#exit-code-2-behavior-per-event) mencantumkan efek untuk setiap event, dan bagian setiap event menjelaskan ke mana pesan tersebut dikirim.874Pesan yang menyertai pemblokiran adalah stderr hook Anda. Jika hook Anda juga mencetak JSON yang membuat keputusan pemblokiran, Claude Code menggunakan alasan dari keputusan tersebut sebagai gantinya.
855 875
856Hook yang keluar dengan 2 sambil mencetak JSON yang gagal validasi skema [output JSON](#json-output) tetap memblokir: Claude Code menggunakan stderr sebagai alasan pemblokiran dan mencatat kegagalan validasi di log debug. Sebelum v2.1.214, Claude Code memperlakukan kombinasi tersebut sebagai error non-blocking dan tindakan dilanjutkan.876Exit 2 memblokir bahkan ketika hook Anda mencetak JSON:
877
878* **JSON yang lolos validasi skema**: Claude Code tetap membaca field [output JSON](#json-output), tetapi field tersebut tidak dapat menimpa pemblokiran. Bahkan `permissionDecision` bernilai `"allow"` tidak membuat tindakan diloloskan. Pada `Elicitation` dan `ElicitationResult`, `hookSpecificOutput` dari hook yang keluar dengan exit 2 diabaikan.
879* **JSON yang gagal validasi skema**: hook tetap memblokir. Claude Code menggunakan stderr Anda sebagai alasan pemblokiran dan mencatat kegagalan validasi di log debug.
857 880
858Skrip ini memblokir perintah `rm` dengan keluar menggunakan 2 dan menyerahkan setiap perintah lain ke alur izin normal:881Skrip ini memblokir perintah `rm` dengan keluar menggunakan 2 dan menyerahkan setiap perintah lain ke alur izin normal:
859 882
871exit 0 # No decision: the normal permission flow applies894exit 0 # No decision: the normal permission flow applies
872```895```
873 896
897Dengan skrip ini terdaftar sebagai hook `PreToolUse` pada `Bash`, perintah yang diawali dengan `rm` diblokir, dan Claude menerima stderr hook sebagai error tool, dengan awalan nama event, nama tool, dan perintah hook:
898
899```text theme={null}
900PreToolUse:Bash hook error: [${CLAUDE_PROJECT_DIR}/.claude/hooks/no-rm.sh]: Blocked: rm commands are not allowed
901```
902
874<h4 id="other-exit-codes">903<h4 id="other-exit-codes">
875 Exit code lainnya904 Exit code lainnya
876</h4>905</h4>
877 906
878Exit code lainnya tidak memblokir dengan sendirinya untuk sebagian besar event hook. Apa yang terjadi bergantung pada stdout Anda:907Ketika hook Anda keluar dengan kode selain 0 atau 2 dan mencetak teks biasa atau tidak mencetak apa pun ke stdout, eksekusi tersebut adalah [error non-blocking](#exit-code-output). Anda melihat pemberitahuan `<hook name> hook error` di transkrip dengan `Failed with non-blocking status code:` dan baris pertama stderr hook Anda. Misalnya, ketika hook `PreToolUse` pada `Bash` mencetak `something broke` ke stderr dan keluar dengan 1, pemberitahuan `PreToolUse:Bash hook error` memuat baris ini:
879 908
880* Dengan objek yang berhasil di-parse dan lolos validasi skema, untuk event yang menggunakan model keputusan standar, Claude Code mengabaikan exit code dan hanya JSON yang menentukan hasilnya:909```text theme={null}
881 * Setiap field yang didukung event dihormati, termasuk `permissionDecision`, `additionalContext`, `updatedInput`, dan `systemMessage`, dan hook tidak dilaporkan sebagai error.910Failed with non-blocking status code: something broke
882 * [Kontrol keputusan](#decision-control) mencantumkan field keputusan per event; field universal seperti `systemMessage` mengikuti tabel [output JSON](#json-output).911```
883* Dengan objek yang berhasil di-parse tetapi gagal validasi skema, untuk event yang menggunakan model keputusan standar, hasilnya adalah error non-blocking yang sama seperti [pada exit 0](#exit-code-0): tindakan dilanjutkan, dan pemberitahuan `<hook name> hook error` memuat pesan validasi.
884* Dengan stdout yang [dicoba di-parse sebagai JSON](#exit-code-0) oleh Claude Code tetapi gagal, Claude Code melaporkan error non-blocking yang sama seperti pada exit 0 untuk event yang menggunakan model keputusan standar. Tindakan dilanjutkan, dan pemberitahuan memuat pesan parse.
885* Dengan stdout yang [diperlakukan sebagai teks biasa](#exit-code-0) oleh Claude Code, atau dengan stdout kosong, hasilnya adalah error non-blocking untuk sebagian besar event hook: tindakan dilanjutkan, dan transkrip menampilkan pemberitahuan `<hook name> hook error` diikuti baris pertama stderr, dengan awalan `Failed with non-blocking status code:`. Untuk menangkap stderr lengkap, aktifkan [logging debug](#debug-hooks).
886 912
887Event di luar model keputusan standar memiliki barisnya sendiri dalam [tabel per event](#exit-code-2-behavior-per-event): `WorktreeCreate` menggagalkan pembuatan pada exit bukan nol apa pun, apa pun isi JSON Anda, dan event yang membuang output hook sepenuhnya, seperti `StopFailure`, mengabaikan JSON Anda pada setiap exit code, kecuali field efek samping seperti `terminalSequence`, yang tetap dijalankan.913Untuk menangkap stderr lengkap alih-alih hanya baris pertamanya, aktifkan [logging debug](#debug-hooks).
888 914
889Hook yang tidak dapat dimulai masuk ke kategori non-blocking yang sama. Ketika path skrip tidak ada atau tidak dapat dieksekusi, shell keluar dengan kode seperti 127 dan Anda melihat pemberitahuan yang sama dengan pesan interpreter, misalnya `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. Untuk sebagian besar event hook, tindakan dilanjutkan. Saat Anda menyiapkan hook kebijakan, perhatikan pemberitahuan ini pada eksekusi pertamanya: path yang salah ketik di `settings.json` membuat gerbang tersebut nonaktif tanpa pemberitahuan.915Hook yang tidak dapat dimulai juga merupakan error non-blocking. Dalam bentuk shell, ketika path skrip tidak ada atau tidak dapat dieksekusi, shell keluar dengan kode seperti 127 dan pemberitahuan memuat pesan interpreter, misalnya `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. Saat Anda menyiapkan hook kebijakan, perhatikan pemberitahuan ini pada eksekusi pertamanya, karena path yang salah ketik di `settings.json` berarti hook tidak pernah berjalan. Untuk memblokir tindakan sebagai gantinya, atur [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
890 916
891<Warning>917<Warning>
892 Untuk sebagian besar event hook, exit code 2 adalah satu-satunya exit code yang memblokir hanya melalui kode tersebut. Tanpa JSON yang valid di stdout, Claude Code memperlakukan exit code 1 sebagai error non-blocking dan melanjutkan tindakan, meskipun 1 adalah kode kegagalan Unix yang konvensional. Jika hook Anda dimaksudkan untuk menegakkan kebijakan, gunakan `exit 2`. Event worktree berbeda: exit code bukan nol apa pun dari `WorktreeCreate` membatalkan pembuatan worktree, dan exit code bukan nol apa pun dari `WorktreeRemove` membuat penghapusan worktree gagal jika direktori masih ada setelahnya.918 Tanpa JSON yang valid di stdout, Claude Code memperlakukan exit code 1 sebagai error non-blocking, meskipun 1 adalah kode kegagalan Unix yang konvensional. Jika hook Anda dimaksudkan untuk menegakkan kebijakan, gunakan `exit 2`.
893</Warning>919</Warning>
894 920
895<h4 id="timeouts">921<h4 id="timeouts">
900 926
901Pada [`PreModelSwitch`](#premodelswitch), hook yang dibatalkan karena timeout memblokir pergantian model. Pada `PreToolUse`, kedua keluarga hook berbeda:927Pada [`PreModelSwitch`](#premodelswitch), hook yang dibatalkan karena timeout memblokir pergantian model. Pada `PreToolUse`, kedua keluarga hook berbeda:
902 928
903* Hook `command`, `http`, atau `mcp_tool` yang mengalami timeout tidak memblokir panggilan tool. Panggilan berlanjut melalui [alur izin](/docs/id/permissions) normal, jadi jangan mengandalkan hook yang macet untuk berfungsi sebagai gerbang.929* Hook `command`, `http`, atau `mcp_tool` yang mengalami timeout tidak memblokir panggilan tool. Panggilan berlanjut melalui [alur izin](/docs/id/permissions) normal, jadi jangan mengandalkan hook yang macet untuk berfungsi sebagai gerbang. Untuk memblokir panggilan ketika hook `command` atau `http` mengalami timeout, atur [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
904* [Callback hook Agent SDK](/docs/id/agent-sdk/hooks) yang melebihi timeout-nya [memblokir panggilan tool](#pretooluse).930* [Callback hook Agent SDK](/docs/id/agent-sdk/hooks) yang melebihi timeout-nya [memblokir panggilan tool](#pretooluse).
905 931
932<h4 id="block-the-action-when-a-hook-fails">
933 Memblokir tindakan ketika hook gagal
934</h4>
935
936Pada sebagian besar event, ketika hook gagal atau mengalami timeout, Claude Code tetap menjalankan tindakan, sehingga hook kebijakan dengan path yang salah atau skrip yang crash meloloskan semuanya. Untuk memblokir tindakan sebagai gantinya, atur `"onFailure": "block"` pada hook `command` atau `http`. Nilai default-nya adalah `"continue"`. Memerlukan Claude Code v2.1.295 atau lebih baru.
937
938Hook `PreToolUse` di `.claude/settings.json` ini menjalankan skrip proyek sebelum setiap perintah Bash, dan memblokir perintah jika skrip gagal:
939
940```json theme={null}
941{
942 "hooks": {
943 "PreToolUse": [
944 {
945 "matcher": "Bash",
946 "hooks": [
947 {
948 "type": "command",
949 "command": "node",
950 "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js"],
951 "onFailure": "block"
952 }
953 ]
954 }
955 ]
956 }
957}
958```
959
960Untuk mengujinya, biarkan `check-command.js` tidak ada dan minta Claude menjalankan perintah Bash seperti `ls`. Claude Code memblokir panggilan, dan error-nya menyertakan `failed; blocking because onFailure is "block"` diikuti output error node itu sendiri, yang dipangkas di sini menjadi satu baris:
961
962```text theme={null}
963PreToolUse:Bash hook error: [node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js]: failed; blocking because onFailure is "block"
964Error: Cannot find module '/path/to/project/.claude/hooks/check-command.js'
965```
966
967Setelah timeout, pesan menyatakan `timed out` alih-alih `failed`. Tanpa `onFailure` diatur, skrip yang sama yang tidak ada adalah error non-blocking dan `ls` berjalan.
968
969Setiap hal berikut dihitung sebagai kegagalan:
970
971* **Tidak dapat dimulai**: hook perintah gagal dimulai, misalnya karena skrip atau executable tidak ada
972* **Exit code selain 0 atau 2**: berlaku untuk hook perintah meskipun hook tersebut mencetak JSON yang mengizinkan tindakan, seperti `permissionDecision: "allow"`. Untuk mengembalikan keputusan JSON, keluar dengan 0
973* **Error HTTP**: koneksi hook HTTP gagal, atau status respons bukan 2xx
974* **Timeout**: hook mencapai [`timeout`](#common-fields)-nya
975* **Output tidak valid**: output JSON [tidak dapat di-parse](#exit-code-0) atau gagal [validasi skema](#json-output). Untuk hook HTTP, body 2xx yang bukan kosong dan bukan objek JSON juga dihitung. Stdout teks biasa dari hook perintah bukan kegagalan
976
977Dengan `"block"` diatur, kegagalan melakukan apa yang [dilakukan exit code 2 pada event tersebut](#exit-code-2-behavior-per-event), kecuali pada `PermissionRequest`, di mana kegagalan menolak permintaan. Misalnya, kegagalan `PreToolUse` memblokir panggilan tool dan kegagalan `UserPromptSubmit` memblokir prompt.
978
979Field ini tidak berpengaruh pada hook berikut:
980
981* **Hook `Stop`, `SubagentStop`, `TaskCompleted`, dan `TeammateIdle`**: exit code 2 pada event ini mengirim Claude kembali untuk terus bekerja, dan Claude tidak dapat memperbaiki hook yang tidak mau berjalan
982* **Hook perintah latar belakang**: hook perintah yang mengatur [`async` atau `asyncRewake`](#run-hooks-in-the-background)
983
906<h4 id="exit-code-2-behavior-per-event">984<h4 id="exit-code-2-behavior-per-event">
907 Perilaku exit code 2 per event985 Perilaku exit code 2 per event
908</h4>986</h4>
960* **Kegagalan koneksi**: error non-blocking, eksekusi berlanjut1038* **Kegagalan koneksi**: error non-blocking, eksekusi berlanjut
961* **Timeout**: hook dibatalkan, seperti dijelaskan di bagian [Timeout](#timeouts)1039* **Timeout**: hook dibatalkan, seperti dijelaskan di bagian [Timeout](#timeouts)
962 1040
963Tidak seperti hook perintah, hook HTTP tidak dapat memberi sinyal error blocking hanya melalui kode status. Untuk memblokir panggilan tool atau menolak izin, kembalikan respons 2xx dengan body JSON yang berisi field keputusan yang sesuai.1041Hook HTTP tidak dapat memberi sinyal error blocking hanya melalui kode status: status non-2xx atau koneksi yang gagal adalah [error non-blocking](#exit-code-output). Untuk memblokir panggilan tool atau menolak izin, kembalikan respons 2xx dengan body JSON yang berisi field keputusan yang sesuai. Untuk memblokir tindakan ketika permintaan gagal atau mengembalikan status non-2xx, atur [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
964 1042
965<h3 id="json-output">1043<h3 id="json-output">
966 Output JSON1044 Output JSON
1237 Kontrol keputusan SessionStart1315 Kontrol keputusan SessionStart
1238</h4>1316</h4>
1239 1317
1240Claude Code menambahkan stdout yang [diperlakukannya sebagai teks biasa](#exit-code-0) ke konteks Claude. Selain [field output JSON](#json-output) yang tersedia untuk semua hook, Anda dapat mengembalikan field khusus event berikut:1318Hook SessionStart dapat menambahkan konteks untuk Claude, menyediakan pesan pengguna pertama, menetapkan judul sesi, memantau file, dan memuat ulang skill. Kembalikan field untuk masing-masing, selain [field output JSON](#json-output) yang tersedia untuk semua hook:
1241 1319
1242| Field | Deskripsi |1320| Field | Deskripsi |
1243| :- | :- |1321| :- | :- |
1244| `additionalContext` | String yang ditambahkan ke konteks Claude di awal percakapan, sebelum prompt pertama. Lihat [Menambahkan konteks untuk Claude](#add-context-for-claude) untuk cara teks dikirimkan dan apa yang perlu dimasukkan ke dalamnya |1322| `additionalContext` | String yang ditambahkan ke konteks Claude di awal percakapan, sebelum prompt pertama. Lihat [Menambahkan konteks untuk Claude](#add-context-for-claude) untuk cara teks dikirimkan dan apa yang perlu dimasukkan ke dalamnya |
1245| `initialUserMessage` | String yang digunakan sebagai pesan pengguna pertama dalam sesi. Berlaku dalam [mode non-interaktif](/docs/id/headless) dengan flag `-p`, tempat string ini menjadi giliran pertama bahkan jika tidak ada prompt yang diberikan. Jika prompt diberikan, prompt tersebut menyusul sebagai giliran berikutnya. Tidak seperti `additionalContext`, yang melekat pada giliran yang sudah ada, field ini membuat giliran tersebut |1323| `initialUserMessage` | String yang digunakan sebagai pesan pengguna pertama dari sesi, dalam [mode non-interaktif](/docs/id/headless) dengan flag `-p`. String ini menjadi giliran pertama meskipun Anda tidak memberikan prompt. Prompt yang Anda berikan akan mengikuti sebagai giliran berikutnya |
1246| `sessionTitle` | Menetapkan judul sesi, dengan efek yang sama seperti `/rename`. Gunakan untuk memberi nama sesi secara otomatis dari folder peluncuran, branch git, atau nama worktree. Berlaku saat `source` bernilai `"startup"`, `"resume"`, atau `"fork"`; diabaikan pada `"clear"` dan `"compact"` |1324| `sessionTitle` | Menetapkan judul sesi, dengan efek yang sama seperti `/rename`. Berlaku ketika `source` bernilai `"startup"`, `"resume"`, atau `"fork"` |
1247| `watchPaths` | Array path absolut yang dipantau untuk event [FileChanged](#filechanged) selama sesi ini |1325| `watchPaths` | Array path absolut yang dipantau untuk event [FileChanged](#filechanged) selama sesi ini |
1248| `reloadSkills` | Boolean. Saat `true`, Claude Code memindai ulang direktori [skill](/docs/id/skills) dan perintah setelah hook SessionStart selesai, sehingga skill yang dipasang oleh hook tersedia dalam sesi yang sama, dimulai dari prompt pertama |1326| `reloadSkills` | Boolean. Ketika `true`, Claude Code memindai ulang direktori [skill](/docs/id/skills) dan perintah setelah hook SessionStart selesai. Lihat [Memuat ulang skill yang dipasang hook](#reload-skills-that-a-hook-installs) |
1327
1328Output ini menambahkan konteks dan memberi nama sesi:
1249 1329
1250```json theme={null}1330```json theme={null}
1251{1331{
1257}1337}
1258```1338```
1259 1339
1260Karena stdout biasa sudah sampai ke Claude untuk event ini, hook yang hanya memuat konteks dapat langsung mencetak ke stdout tanpa membuat JSON. Gunakan bentuk JSON saat Anda perlu menggabungkan konteks dengan field lain seperti `sessionTitle`.1340Hook yang hanya menambahkan konteks dapat mencetaknya tanpa membangun JSON, karena Claude Code menambahkan [stdout teks biasa](#exit-code-0) dari hook SessionStart ke konteks Claude.
1341
1342Jika hook SessionStart dari plugin Anda menyediakan `initialUserMessage` atau `sessionTitle`, pasang plugin tersebut sebelum sesi dimulai. Claude Code mengabaikan kedua field tersebut dari plugin yang selesai dipasang setelah hook SessionStart berjalan.
1343
1344<h4 id="reload-skills-that-a-hook-installs">
1345 Memuat ulang skill yang dipasang hook
1346</h4>
1347
1348Agar skill yang dipasang oleh hook SessionStart tersedia dalam sesi yang sama, kembalikan `reloadSkills`. Penemuan skill biasanya berjalan sebelum hook SessionStart selesai, sehingga tanpanya, file yang ditulis hook ke `~/.claude/skills/` atau `.claude/skills/` bisa belum ada ketika prompt pertama berjalan.
1261 1349
1262Gunakan `reloadSkills` saat hook SessionStart memasang atau memperbarui skill. Penemuan skill biasanya berjalan sebelum hook SessionStart selesai, sehingga file yang ditulis hook ke `~/.claude/skills/` atau `.claude/skills/` jika tidak demikian hanya akan muncul di sesi berikutnya. Contoh ini menyinkronkan repositori skill bersama dan meminta pemindaian ulang:1350Contoh ini menyinkronkan repositori skill bersama dan meminta pemindaian ulang:
1263 1351
1264```bash theme={null}1352```bash theme={null}
1265#!/bin/bash1353#!/bin/bash
1270echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1358echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1271```1359```
1272 1360
1273URL repositori tersebut adalah placeholder; ganti dengan repositori skill Anda sendiri. Dengan placeholder tersebut, clone gagal dan mencetak pesan `fatal:` ke stderr. Stderr dari hook SessionStart yang keluar dengan 0 hanya bersifat informasional, sehingga permintaan `reloadSkills` tetap berlaku.1361URL repositori tersebut adalah placeholder. Ganti dengan repositori skill Anda sendiri.
1274 1362
1275<h4 id="persist-environment-variables">1363<h4 id="persist-environment-variables">
1276 Mempertahankan environment variable1364 Mempertahankan environment variable
1419 1507
1420Hook `UserPromptSubmit` memiliki timeout default 30 detik untuk jenis `command`, `http`, dan `mcp_tool`, lebih pendek daripada default 600 detik untuk jenis tersebut pada sebagian besar event lain. Karena hook ini berjalan sebelum setiap prompt dan memblokir pemrosesan model hingga selesai, hook yang macet akan menghentikan sesi. Jika hook Anda memerlukan waktu lebih lama, tetapkan field `timeout` dalam entri hook.1508Hook `UserPromptSubmit` memiliki timeout default 30 detik untuk jenis `command`, `http`, dan `mcp_tool`, lebih pendek daripada default 600 detik untuk jenis tersebut pada sebagian besar event lain. Karena hook ini berjalan sebelum setiap prompt dan memblokir pemrosesan model hingga selesai, hook yang macet akan menghentikan sesi. Jika hook Anda memerlukan waktu lebih lama, tetapkan field `timeout` dalam entri hook.
1421 1509
1422Selain hook perintah yang Anda jalankan dengan [`async: true`](#run-hooks-in-the-background), hook perintah, HTTP, atau tool MCP `UserPromptSubmit` yang mencapai timeout-nya dibatalkan dan output-nya, termasuk `additionalContext` apa pun, dibuang. Prompt tetap sampai ke Claude tanpa konteks tersebut. Transkrip menampilkan pemberitahuan yang menyebutkan nama hook, timeout yang dipicu, dan bahwa output telah dibuang.1510Selain hook perintah yang Anda jalankan dengan [`async: true`](#run-hooks-in-the-background), hook perintah, HTTP, atau tool MCP `UserPromptSubmit` yang mencapai timeout-nya akan dibatalkan dan output-nya, termasuk `additionalContext` apa pun, dibuang. Prompt tetap sampai ke Claude tanpa konteks tersebut. Untuk memblokir prompt sebagai gantinya, tetapkan [`onFailure: "block"`](#block-the-action-when-a-hook-fails) pada hook perintah atau HTTP. Transkrip menampilkan pemberitahuan yang menyebutkan hook, timeout yang dipicu, dan bahwa output telah dibuang.
1423 1511
1424[Hook callback Agent SDK](/docs/id/agent-sdk/hooks) pada `UserPromptSubmit` yang mencapai timeout-nya memblokir prompt dengan pesan yang menyebutkan nama hook dan timeout-nya, karena callback di sana dapat berfungsi sebagai gerbang kebijakan yang tidak boleh gagal dalam keadaan terbuka. Sesi tetap berlanjut. Sebelum v2.1.208, timeout callback pada event tersebut mengakhiri giliran dengan error eksekusi.1512[Hook callback Agent SDK](/docs/id/agent-sdk/hooks) pada `UserPromptSubmit` yang mencapai timeout-nya memblokir prompt dengan pesan yang menyebutkan nama hook dan timeout-nya, karena callback di sana dapat berfungsi sebagai gerbang kebijakan yang tidak boleh gagal dalam keadaan terbuka. Sesi tetap berlanjut. Sebelum v2.1.208, timeout callback pada event tersebut mengakhiri giliran dengan error eksekusi.
1425 1513
1860| :- | :- | :- | :- |1948| :- | :- | :- | :- |
1861| `url` | string | `"https://example.com/api"` | URL tempat konten diambil |1949| `url` | string | `"https://example.com/api"` | URL tempat konten diambil |
1862| `prompt` | string | `"Extract the API endpoints"` | Prompt yang dijalankan pada konten yang diambil |1950| `prompt` | string | `"Extract the API endpoints"` | Prompt yang dijalankan pada konten yang diambil |
1951| `offset` | number | `100000` | Jumlah karakter opsional yang dilewati dari awal halaman. Claude menetapkannya untuk terus membaca halaman yang panjang. Memerlukan Claude Code v2.1.290 atau yang lebih baru |
1863 1952
1864<h5 id="websearch">1953<h5 id="websearch">
1865 WebSearch1954 WebSearch
2112| `message` | Hanya untuk `"deny"`: memberi tahu Claude mengapa izin ditolak |2201| `message` | Hanya untuk `"deny"`: memberi tahu Claude mengapa izin ditolak |
2113| `interrupt` | Hanya untuk `"deny"`: jika `true`, menghentikan Claude |2202| `interrupt` | Hanya untuk `"deny"`: jika `true`, menghentikan Claude |
2114 2203
2115Hook yang keluar dengan 2 tanpa objek `decision` membiarkan alur izin tidak berubah, dan stderr-nya dibuang. Hanya objek `decision` yang dapat memberikan atau menolak permintaan.2204Hook yang keluar dengan kode 2 tanpa objek `decision` membiarkan alur izin tidak berubah, dan stderr-nya dibuang. Untuk memberikan atau menolak permintaan, kembalikan objek `decision`.
2116 2205
2117```json theme={null}2206```json theme={null}
2118{2207{
2678 Kontrol keputusan TaskCreated2767 Kontrol keputusan TaskCreated
2679</h4>2768</h4>
2680 2769
2681Hook TaskCreated dapat memblokir pembuatan dengan dua cara. Dengan cara mana pun, Claude Code menghapus tugas dan mengembalikan pesan Anda kepada Claude sebagai error tool. Claude Code mengabaikan `continue: false` dari event ini dan Claude tetap bekerja.2770Hook TaskCreated dapat memblokir pembuatan dengan exit code 2 atau dengan keputusan JSON. Apa pun caranya, Claude Code menghapus tugas dan mengembalikan pesan Anda kepada Claude sebagai error tool. Claude Code mengabaikan `continue: false` dari event ini dan Claude terus bekerja.
2682 2771
2683* **Exit code 2**: Claude Code mengembalikan teks stderr sebagai pesan.2772* **Exit code 2**: Claude Code mengembalikan teks stderr sebagai pesan.
2684* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code mengembalikan `reason` sebagai pesan.2773* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code mengembalikan `reason` sebagai pesan.
3561 3650
3562Claude Code menampilkan kepada pengguna `systemMessage` apa pun yang dikembalikan hook Anda terlepas dari keputusannya, sehingga hook pelaporan biaya dapat mengembalikan `{"systemMessage": "..."}` dan keluar dengan 0.3651Claude Code menampilkan kepada pengguna `systemMessage` apa pun yang dikembalikan hook Anda terlepas dari keputusannya, sehingga hook pelaporan biaya dapat mengembalikan `{"systemMessage": "..."}` dan keluar dengan 0.
3563 3652
3564Hook PreModelSwitch yang tidak merespons sebelum timeout-nya akan memblokir peralihan. Sebaliknya, pada [PreToolUse](#timeouts), hook perintah yang mengalami timeout membiarkan panggilan tool berlanjut. Timeout default untuk event ini adalah 30 detik. `PreModelSwitch` hanya menjalankan hook `command`, `http`, dan `mcp_tool`, sehingga default `prompt` dan `agent` tidak berlaku.3653Hook PreModelSwitch yang tidak merespons sebelum timeout-nya akan memblokir pergantian. Untuk apa yang dilakukan timeout pada event lain, lihat [Timeout](#timeouts). Timeout default untuk event ini adalah 30 detik. `PreModelSwitch` hanya menjalankan hook `command`, `http`, dan `mcp_tool`, sehingga default `prompt` dan `agent` tidak berlaku.
3565 3654
3566Hook yang keluar dengan kode selain 0 atau 2 dan tidak mencetak keputusan JSON tidak memblokir: Claude Code menampilkan stderr-nya dan menerapkan peralihan, seperti yang dijelaskan di [Exit code lainnya](#other-exit-codes).3655Hook yang keluar dengan kode selain 0 atau 2 dan tidak mencetak keputusan JSON merupakan error yang tidak memblokir, seperti yang dijelaskan di [Exit code lainnya](#other-exit-codes).
3567 3656
3568<h3 id="postmodelswitch">3657<h3 id="postmodelswitch">
3569 PostModelSwitch3658 PostModelSwitch
4279Async hooks memiliki batasan tambahan dibandingkan dengan hooks sinkron:4368Async hooks memiliki batasan tambahan dibandingkan dengan hooks sinkron:
4280 4369
4281* Output hook disampaikan pada turn percakapan berikutnya. Jika sesi idle, respons menunggu sampai interaksi pengguna berikutnya. Pengecualian: hook `asyncRewake` yang keluar dengan kode 2 membangunkan Claude segera bahkan ketika sesi idle.4370* Output hook disampaikan pada turn percakapan berikutnya. Jika sesi idle, respons menunggu sampai interaksi pengguna berikutnya. Pengecualian: hook `asyncRewake` yang keluar dengan kode 2 membangunkan Claude segera bahkan ketika sesi idle.
4282* Setiap eksekusi membuat proses latar belakang terpisah. Tidak ada deduplikasi di seluruh beberapa penjalankan hook async yang sama.4371* Setiap eksekusi membuat proses latar belakang terpisah.
4283 4372
4284<h2 id="security-considerations">4373<h2 id="security-considerations">
4285 Pertimbangan keamanan4374 Pertimbangan keamanan