16 Siklus hidup hook16 Siklus hidup hook
17</h2>17</h2>
18 18
19Hooks dijalankan pada titik-titik tertentu selama sesi Claude Code. Ketika event dijalankan dan matcher cocok, Claude Code meneruskan konteks JSON tentang event ke handler hook Anda. Untuk command hooks, input tiba di stdin. Untuk HTTP hooks, input tiba sebagai badan permintaan POST. Handler Anda kemudian dapat memeriksa input, mengambil tindakan, dan secara opsional mengembalikan keputusan. Events jatuh ke dalam tiga cadence: sekali per sesi (`SessionStart`, `SessionEnd`), sekali per turn (`UserPromptSubmit`, `Stop`, `StopFailure`), dan pada setiap pemanggilan tool di dalam loop agentic (`PreToolUse`, `PostToolUse`):19Hooks dijalankan pada titik-titik tertentu selama sesi Claude Code. Ketika event dijalankan dan matcher cocok, Claude Code meneruskan konteks JSON tentang event ke handler hook Anda. Untuk command hooks, input tiba di stdin. Untuk HTTP hooks, input tiba sebagai badan permintaan POST. Handler Anda kemudian dapat memeriksa input, mengambil tindakan, dan secara opsional mengembalikan keputusan.
20
21Events jatuh ke dalam tiga cadence:
22
23* sekali per sesi: `SessionStart` dan `SessionEnd`
24* sekali per turn: `UserPromptSubmit`, `Stop`, dan `StopFailure`
25* pada setiap pemanggilan tool di dalam loop agentic: `PreToolUse` dan `PostToolUse`
20 26
21<div style={{maxWidth: "500px", margin: "0 auto"}}>27<div style={{maxWidth: "500px", margin: "0 auto"}}>
22 <Frame>28 <Frame>
214| `SessionStart` | bagaimana sesi dimulai | `startup`, `resume`, `clear`, `compact` |220| `SessionStart` | bagaimana sesi dimulai | `startup`, `resume`, `clear`, `compact` |
215| `Setup` | flag CLI mana yang memicu setup | `init`, `maintenance` |221| `Setup` | flag CLI mana yang memicu setup | `init`, `maintenance` |
216| `SessionEnd` | mengapa sesi berakhir | `clear`, `resume`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |222| `SessionEnd` | mengapa sesi berakhir | `clear`, `resume`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |
217| `Notification` | tipe notifikasi | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_complete`, `elicitation_response` |223| `Notification` | tipe notifikasi | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed` |
218| `SubagentStart` | tipe agent | `general-purpose`, `Explore`, `Plan`, nama agent kustom, atau nama dengan cakupan plugin seperti `^my-plugin:reviewer$` |224| `SubagentStart` | tipe agent | `general-purpose`, `Explore`, `Plan`, nama agent kustom, atau nama dengan cakupan plugin seperti `^my-plugin:reviewer$` |
219| `PreCompact`, `PostCompact` | apa yang memicu compaction | `manual`, `auto` |225| `PreCompact`, `PostCompact` | apa yang memicu compaction | `manual`, `auto` |
220| `SubagentStop` | tipe agent | nilai yang sama seperti `SubagentStart` |226| `SubagentStop` | tipe agent | nilai yang sama seperti `SubagentStart` |
317 323
318Semua matching hooks dijalankan secara paralel, dan handler identik dideduplikasi secara otomatis. Command hooks dideduplikasi berdasarkan string perintah dan `args`, dan HTTP hooks dideduplikasi berdasarkan URL.324Semua matching hooks dijalankan secara paralel, dan handler identik dideduplikasi secara otomatis. Command hooks dideduplikasi berdasarkan string perintah dan `args`, dan HTTP hooks dideduplikasi berdasarkan URL.
319 325
320Handlers dijalankan di direktori saat ini dengan lingkungan Claude Code. Variabel lingkungan `$CLAUDE_CODE_REMOTE` diatur ke `"true"` di lingkungan web jarak jauh dan tidak diatur di CLI lokal.326Handlers dijalankan di direktori saat ini dengan lingkungan Claude Code. Variabel lingkungan `$CLAUDE_CODE_REMOTE` diatur ke `"true"` di lingkungan web jarak jauh dan tidak diatur di CLI lokal. {/* min-version: 2.1.199 */}Mulai dari v2.1.199, [`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/id/env-vars) diatur ke [Remote Control](/id/remote-control) session ID saat sesi lokal memiliki koneksi Remote Control yang aktif.
321 327
322<h4 id="common-fields">328<h4 id="common-fields">
323 Bidang umum329 Bidang umum
704Kode keluar 2 adalah cara hook menandakan "berhenti, jangan lakukan ini." Efeknya tergantung pada event, karena beberapa event mewakili tindakan yang dapat diblokir (seperti pemanggilan tool yang belum terjadi) dan yang lain mewakili hal-hal yang sudah terjadi atau tidak dapat dicegah.710Kode keluar 2 adalah cara hook menandakan "berhenti, jangan lakukan ini." Efeknya tergantung pada event, karena beberapa event mewakili tindakan yang dapat diblokir (seperti pemanggilan tool yang belum terjadi) dan yang lain mewakili hal-hal yang sudah terjadi atau tidak dapat dicegah.
705 711
706| Hook event | Dapat diblokir? | Apa yang terjadi pada exit 2 |712| Hook event | Dapat diblokir? | Apa yang terjadi pada exit 2 |
707| :-------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |713| :-------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
708| `PreToolUse` | Ya | Memblokir pemanggilan tool |714| `PreToolUse` | Ya | Memblokir pemanggilan tool |
709| `PermissionRequest` | Ya | Menolak izin |715| `PermissionRequest` | Ya | Menolak izin |
710| `UserPromptSubmit` | Ya | Memblokir pemrosesan prompt dan menghapus prompt |716| `UserPromptSubmit` | Ya | Memblokir pemrosesan prompt dan menghapus prompt |
711| `UserPromptExpansion` | Ya | Memblokir ekspansi |717| `UserPromptExpansion` | Ya | Memblokir ekspansi |
712| `Stop` | Ya | Mencegah Claude berhenti, melanjutkan percakapan |718| `Stop` | Ya | Mencegah Claude berhenti, melanjutkan percakapan |
713| `SubagentStop` | Ya | Mencegah subagent berhenti |719| `SubagentStop` | Ya | Mencegah subagent berhenti |
714| `TeammateIdle` | Ya | Mencegah teammate menjadi idle (teammate terus bekerja) |720| `TeammateIdle` | Ya | Mencegah teammate menjadi idle, jadi terus bekerja |
715| `TaskCreated` | Ya | Membatalkan pembuatan tugas |721| `TaskCreated` | Ya | Membatalkan pembuatan tugas |
716| `TaskCompleted` | Ya | Mencegah tugas ditandai sebagai selesai |722| `TaskCompleted` | Ya | Mencegah tugas ditandai sebagai selesai |
717| `ConfigChange` | Ya | Memblokir perubahan konfigurasi dari berlaku (kecuali `policy_settings`) |723| `ConfigChange` | Ya | Memblokir perubahan konfigurasi dari berlaku (kecuali `policy_settings`) |
718| `StopFailure` | Tidak | Output dan kode keluar diabaikan |724| `StopFailure` | Tidak | Output dan kode keluar diabaikan |
719| `PostToolUse` | Tidak | Menampilkan stderr ke Claude (tool sudah dijalankan) |725| `PostToolUse` | Tidak | Menampilkan stderr ke Claude; tool sudah dijalankan |
720| `PostToolUseFailure` | Tidak | Menampilkan stderr ke Claude (tool sudah gagal) |726| `PostToolUseFailure` | Tidak | Menampilkan stderr ke Claude; tool sudah gagal |
721| `PostToolBatch` | Ya | Menghentikan loop agentic sebelum pemanggilan model berikutnya |727| `PostToolBatch` | Ya | Menghentikan loop agentic sebelum pemanggilan model berikutnya |
722| `PermissionDenied` | Tidak | Kode keluar dan stderr diabaikan (penolakan sudah terjadi). Gunakan JSON `hookSpecificOutput.retry: true` untuk memberitahu model itu dapat mencoba lagi |728| `PermissionDenied` | Tidak | Kode keluar dan stderr diabaikan karena penolakan sudah terjadi. Gunakan JSON `hookSpecificOutput.retry: true` untuk memberitahu model itu dapat mencoba lagi |
723| `Notification` | Tidak | Menampilkan stderr ke pengguna saja |729| `Notification` | Tidak | Menampilkan stderr ke pengguna saja |
724| `SubagentStart` | Tidak | Menampilkan stderr ke pengguna saja |730| `SubagentStart` | Tidak | Menampilkan stderr ke pengguna saja |
725| `SessionStart` | Tidak | Menampilkan stderr ke pengguna saja |731| `SessionStart` | Tidak | Menampilkan stderr ke pengguna saja |
736| `InstructionsLoaded` | Tidak | Kode keluar diabaikan |742| `InstructionsLoaded` | Tidak | Kode keluar diabaikan |
737| `MessageDisplay` | Tidak | Teks asli ditampilkan |743| `MessageDisplay` | Tidak | Teks asli ditampilkan |
738 744
745Untuk `SessionStart`, `Setup`, dan `SubagentStart`, stderr kode keluar 2 dirender dalam transkrip sebagai pemberitahuan `<hook name> hook error`, dengan cara yang sama seperti [kesalahan non-blocking](#exit-code-output). Claude tidak melihatnya, dan sesi atau subagent berlanjut. Untuk `SubagentStart`, pemberitahuan muncul dalam transkrip subagent itu sendiri, bukan dalam percakapan induk.
746
747Sejak Claude Code v2.1.199, `SessionStart`, `Setup`, dan `SubagentStart` menampilkan stderr kode keluar 2 dalam transkrip. Versi sebelumnya menulisnya ke debug log saja.
748
739<h3 id="http-response-handling">749<h3 id="http-response-handling">
740 Penanganan respons HTTP750 Penanganan respons HTTP
741</h3>751</h3>
963 SessionStart input973 SessionStart input
964</h4>974</h4>
965 975
966Selain [bidang input umum](#common-input-fields), SessionStart hooks menerima `source` dan secara opsional `model`, `agent_type`, dan `session_title`. Bidang `source` menunjukkan bagaimana sesi dimulai: `"startup"` untuk sesi baru, `"resume"` untuk sesi yang dilanjutkan, `"clear"` setelah `/clear`, atau `"compact"` setelah compaction. Bidang `model` berisi pengenal model aktif. Itu dapat dihilangkan, misalnya setelah `/clear` atau ketika sesi dipulihkan melalui conversation recovery, jadi periksa bidang sebelum membacanya. Jika Anda memulai Claude Code dengan `claude --agent <name>`, bidang `agent_type` berisi nama agent. Bidang `session_title` membawa judul sesi saat ini jika sudah ditetapkan, misalnya melalui `--name` atau `/rename`. Hook yang memancarkan `sessionTitle` dapat memeriksa `session_title` terlebih dahulu untuk menghindari menimpa judul yang ditetapkan pengguna secara eksplisit.976Selain [bidang input umum](#common-input-fields), SessionStart hooks menerima `source` dan secara opsional `model`, `agent_type`, dan `session_title`:
977
978| Bidang | Deskripsi |
979| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
980| `source` | Bagaimana sesi dimulai: `"startup"` untuk sesi baru, `"resume"` untuk sesi yang dilanjutkan, `"clear"` setelah `/clear`, atau `"compact"` setelah compaction |
981| `model` | Pengenal model aktif. Itu dapat dihilangkan, misalnya setelah `/clear` atau ketika sesi dipulihkan melalui conversation recovery, jadi periksa bidang sebelum membacanya |
982| `agent_type` | Nama agent, hadir ketika Anda memulai Claude Code dengan `claude --agent <name>` |
983| `session_title` | Judul sesi saat ini jika sudah ditetapkan, misalnya melalui `--name` atau `/rename`. Hook yang memancarkan `sessionTitle` dapat memeriksa `session_title` terlebih dahulu untuk menghindari menimpa judul yang ditetapkan pengguna secara eksplisit |
967 984
968```json theme={null}985```json theme={null}
969{986{
983Teks apa pun yang dicetak skrip hook ke stdout ditambahkan sebagai konteks untuk Claude. Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, Anda dapat mengembalikan bidang spesifik event ini:1000Teks apa pun yang dicetak skrip hook ke stdout ditambahkan sebagai konteks untuk Claude. Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, Anda dapat mengembalikan bidang spesifik event ini:
984 1001
985| Bidang | Deskripsi |1002| Bidang | Deskripsi |
986| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1003| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
987| `additionalContext` | String ditambahkan ke konteks Claude pada awal percakapan, sebelum prompt pertama. Lihat [Tambahkan konteks untuk Claude](#add-context-for-claude) untuk cara teks disampaikan dan apa yang harus dimasukkan |1004| `additionalContext` | String ditambahkan ke konteks Claude pada awal percakapan, sebelum prompt pertama. Lihat [Tambahkan konteks untuk Claude](#add-context-for-claude) untuk cara teks disampaikan dan apa yang harus dimasukkan |
988| `initialUserMessage` | String digunakan sebagai pesan pengguna pertama sesi. Berlaku dalam [mode non-interaktif](/id/headless) (`-p`), di mana itu menjadi giliran pertama bahkan jika tidak ada prompt yang disediakan. Jika prompt disediakan, itu mengikuti sebagai giliran berikutnya. Tidak seperti `additionalContext`, yang menempel pada giliran yang ada, ini membuat giliran |1005| `initialUserMessage` | String digunakan sebagai pesan pengguna pertama sesi. Berlaku dalam [mode non-interaktif](/id/headless) dengan flag `-p`, di mana itu menjadi giliran pertama bahkan jika tidak ada prompt yang disediakan. Jika prompt disediakan, itu mengikuti sebagai giliran berikutnya. Tidak seperti `additionalContext`, yang menempel pada giliran yang ada, ini membuat giliran |
989| `sessionTitle` | Menetapkan judul sesi, dengan efek yang sama seperti `/rename`. Gunakan untuk memberi nama sesi secara otomatis dari folder peluncuran, cabang git, atau nama worktree. Berlaku hanya ketika `source` adalah `"startup"` atau `"resume"`; diabaikan pada `"clear"` dan `"compact"` |1006| `sessionTitle` | Menetapkan judul sesi, dengan efek yang sama seperti `/rename`. Gunakan untuk memberi nama sesi secara otomatis dari folder peluncuran, cabang git, atau nama worktree. Berlaku hanya ketika `source` adalah `"startup"` atau `"resume"`; diabaikan pada `"clear"` dan `"compact"` |
990| `watchPaths` | Array path absolut untuk menonton untuk event [FileChanged](#filechanged) selama sesi ini |1007| `watchPaths` | Array path absolut untuk menonton untuk event [FileChanged](#filechanged) selama sesi ini |
991| `reloadSkills` | Boolean. Ketika `true`, Claude Code memindai ulang direktori [skill](/id/skills) dan command setelah SessionStart hooks selesai, jadi skills yang diinstal hook tersedia dalam sesi yang sama, dimulai dengan prompt pertama |1008| `reloadSkills` | Boolean. Ketika `true`, Claude Code memindai ulang direktori [skill](/id/skills) dan command setelah SessionStart hooks selesai, jadi skills yang diinstal hook tersedia dalam sesi yang sama, dimulai dengan prompt pertama |
1062 Setup1079 Setup
1063</h3>1080</h3>
1064 1081
1065Dijalankan hanya ketika Anda meluncurkan Claude Code dengan `--init-only`, atau dengan `--init` atau `--maintenance` dalam mode print (`-p`). Itu tidak dijalankan pada startup normal. Gunakan untuk instalasi dependensi satu kali atau pembersihan terjadwal yang Anda picu secara eksplisit dari CI atau skrip, terpisah dari startup sesi normal. Untuk inisialisasi per-sesi, gunakan [SessionStart](#sessionstart) sebagai gantinya.1082Dijalankan hanya ketika Anda meluncurkan Claude Code dengan `--init-only`, atau dengan `--init` atau `--maintenance` dalam [mode non-interaktif](/id/headless) dengan flag `-p`. Itu tidak dijalankan pada startup normal. Gunakan untuk instalasi dependensi satu kali atau pembersihan terjadwal yang Anda picu secara eksplisit dari CI atau skrip, terpisah dari startup sesi normal. Untuk inisialisasi per-sesi, gunakan [SessionStart](#sessionstart) sebagai gantinya.
1066 1083
1067Nilai matcher sesuai dengan flag CLI yang memicu hook:1084Nilai matcher sesuai dengan flag CLI yang memicu hook:
1068 1085
1071| `init` | `claude --init-only` atau `claude -p --init` |1088| `init` | `claude --init-only` atau `claude -p --init` |
1072| `maintenance` | `claude -p --maintenance` |1089| `maintenance` | `claude -p --maintenance` |
1073 1090
1074`--init-only` menjalankan Setup hooks dan SessionStart hooks dengan matcher `startup`, kemudian keluar tanpa memulai percakapan. `--init` dan `--maintenance` menjalankan Setup hooks hanya ketika digabungkan dengan `-p` (mode print); dalam sesi interaktif dua flag itu saat ini tidak menjalankan Setup hooks.1091`--init-only` menjalankan Setup hooks dan SessionStart hooks dengan matcher `startup`, kemudian keluar tanpa memulai percakapan. `--init` dan `--maintenance` menjalankan Setup hooks hanya ketika digabungkan dengan `-p`; dalam sesi interaktif dua flag itu saat ini tidak menjalankan Setup hooks.
1075 1092
1076Karena Setup tidak dijalankan pada setiap peluncuran, plugin yang memerlukan dependensi yang diinstal tidak dapat mengandalkan Setup saja. Pola praktis adalah memeriksa dependensi pada penggunaan pertama dan menginstal jika tidak ada, misalnya hook atau skill yang menguji `${CLAUDE_PLUGIN_DATA}/node_modules` dan menjalankan `npm install` jika tidak ada. Lihat [direktori data persisten](/id/plugins-reference#persistent-data-directory) untuk tempat menyimpan dependensi yang diinstal.1093Karena Setup tidak dijalankan pada setiap peluncuran, plugin yang memerlukan dependensi yang diinstal tidak dapat mengandalkan Setup saja. Pola praktis adalah memeriksa dependensi pada penggunaan pertama dan menginstal jika tidak ada, misalnya hook atau skill yang menguji `${CLAUDE_PLUGIN_DATA}/node_modules` dan menjalankan `npm install` jika tidak ada. Lihat [direktori data persisten](/id/plugins-reference#persistent-data-directory) untuk tempat menyimpan dependensi yang diinstal.
1077 1094
1095 Setup decision control1112 Setup decision control
1096</h4>1113</h4>
1097 1114
1098Setup hooks tidak dapat memblokir. Pada kode keluar 2, stderr ditampilkan kepada pengguna; pada kode keluar non-nol lainnya, stderr muncul hanya ketika Anda meluncurkan dengan `--verbose`. Dalam kedua kasus eksekusi berlanjut. Untuk meneruskan informasi ke konteks Claude, kembalikan `additionalContext` dalam output JSON; plain stdout ditulis ke debug log saja. Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, Anda dapat mengembalikan bidang spesifik event ini:1115Setup hooks tidak dapat memblokir. Kode keluar non-nol apa pun, termasuk 2, menampilkan stderr ke pengguna sebagai pemberitahuan `<hook name> hook error`, dan eksekusi berlanjut. Dalam [mode non-interaktif](/id/headless), output hook muncul hanya ketika Anda meluncurkan dengan `--verbose`.
1116
1117Untuk meneruskan informasi ke konteks Claude, kembalikan `additionalContext` dalam output JSON; plain stdout ditulis ke debug log saja. Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, Anda dapat mengembalikan bidang spesifik event ini:
1099 1118
1100| Bidang | Deskripsi |1119| Bidang | Deskripsi |
1101| :------------------ | :-------------------------------------------------------------------------- |1120| :------------------ | :-------------------------------------------------------------------------- |
1191* **Plain text stdout**: teks non-JSON apa pun yang ditulis ke stdout ditambahkan sebagai konteks1210* **Plain text stdout**: teks non-JSON apa pun yang ditulis ke stdout ditambahkan sebagai konteks
1192* **JSON dengan `additionalContext`**: gunakan format JSON di bawah untuk kontrol lebih. Bidang `additionalContext` ditambahkan sebagai konteks1211* **JSON dengan `additionalContext`**: gunakan format JSON di bawah untuk kontrol lebih. Bidang `additionalContext` ditambahkan sebagai konteks
1193 1212
1194Plain stdout ditampilkan sebagai output hook dalam transkrip. Bidang `additionalContext` ditambahkan lebih diskrit.1213Plain stdout ditampilkan sebagai output hook dalam transkrip. Nilai `additionalContext` disuntikkan sebagai pengingat sistem yang dibaca Claude tanpa entri transkrip yang terlihat.
1195 1214
1196Untuk memblokir prompt, kembalikan objek JSON dengan `decision` diatur ke `"block"`:1215Untuk memblokir prompt, kembalikan objek JSON dengan `decision` diatur ke `"block"`:
1197 1216
1215}1234}
1216```1235```
1217 1236
1218<Note>
1219 Format JSON tidak diperlukan untuk kasus penggunaan sederhana. Untuk menambahkan konteks, Anda dapat mencetak teks biasa ke stdout dengan kode keluar 0. Gunakan JSON ketika Anda perlu memblokir prompts atau menginginkan kontrol yang lebih terstruktur.
1220</Note>
1221
1222<h3 id="userpromptexpansion">1237<h3 id="userpromptexpansion">
1223 UserPromptExpansion1238 UserPromptExpansion
1224</h3>1239</h3>
1545Dalam `PostToolUse`, `tool_response` untuk panggilan Agent yang selesai membawa teks akhir subagent bersama dengan telemetri penggunaan. Baca bidang-bidang ini untuk mencatat biaya per-subagent dari hook:1560Dalam `PostToolUse`, `tool_response` untuk panggilan Agent yang selesai membawa teks akhir subagent bersama dengan telemetri penggunaan. Baca bidang-bidang ini untuk mencatat biaya per-subagent dari hook:
1546 1561
1547| Bidang | Tipe | Contoh | Deskripsi |1562| Bidang | Tipe | Contoh | Deskripsi |
1548| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |1563| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1549| `status` | string | `"completed"` | `"completed"` untuk panggilan sinkron, `"async_launched"` untuk `run_in_background: true` |1564| `status` | string | `"completed"` | `"completed"` untuk panggilan foreground subagents, `"async_launched"` untuk background subagents. {/* min-version: 2.1.198 */}Mulai dari v2.1.198, subagents berjalan di latar belakang secara default, jadi `run_in_background` yang dihilangkan juga menghasilkan `"async_launched"` |
1550| `agentId` | string | `"a4d2c8f1e0b3a297"` | Pengenal untuk run subagent |1565| `agentId` | string | `"a4d2c8f1e0b3a297"` | Pengenal untuk run subagent |
1551| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | Blok teks akhir subagent |1566| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | Blok teks akhir subagent |
1552| `resolvedModel` | string | `"claude-sonnet-4-5"` | Model yang dijalankan subagent, yang mungkin berbeda dari model yang diminta. {/* min-version: 2.1.174 */}Memerlukan Claude Code v2.1.174 atau lebih baru |1567| `resolvedModel` | string | `"claude-sonnet-4-5"` | Model yang dijalankan subagent, yang mungkin berbeda dari model yang diminta. {/* min-version: 2.1.174 */}Memerlukan Claude Code v2.1.174 atau lebih baru |
1555| `totalToolUseCount` | number | `7` | Jumlah pemanggilan tool yang dibuat subagent |1570| `totalToolUseCount` | number | `7` | Jumlah pemanggilan tool yang dibuat subagent |
1556| `usage` | object | `{"input_tokens": 8320, ...}` | Breakdown token per-tipe: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |1571| `usage` | object | `{"input_tokens": 8320, ...}` | Breakdown token per-tipe: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |
1557 1572
1558Untuk panggilan `run_in_background: true`, tool mengembalikan segera setelah meluncurkan subagent, jadi `tool_response` tidak membawa bidang penggunaan. Itu memiliki `status: "async_launched"`, `agentId`, `description`, `prompt`, `outputFile`, dan `resolvedModel`.1573Untuk background subagents, tool mengembalikan segera setelah meluncurkan, jadi `tool_response` tidak membawa bidang penggunaan. Itu memiliki `status: "async_launched"`, `agentId`, `description`, `prompt`, `outputFile`, dan `resolvedModel`.
1559 1574
1560Bidang `resolvedModel` menamai model yang sebenarnya dijalankan subagent, yang dapat berbeda dari nilai `model` dalam `tool_input`. Itu memerlukan Claude Code v2.1.174 atau lebih baru.1575Bidang `resolvedModel` menamai model yang sebenarnya dijalankan subagent, yang dapat berbeda dari nilai `model` dalam `tool_input`. Itu memerlukan Claude Code v2.1.174 atau lebih baru.
1561 1576
1593Hooks `PreToolUse` dapat mengontrol apakah pemanggilan tool dilanjutkan. Tidak seperti hooks lain yang menggunakan bidang `decision` tingkat atas, PreToolUse mengembalikan keputusannya di dalam objek `hookSpecificOutput`. Ini memberikannya kontrol yang lebih kaya: empat hasil (izinkan, tolak, tanya, atau tunda) ditambah kemampuan untuk memodifikasi input tool sebelum eksekusi.1608Hooks `PreToolUse` dapat mengontrol apakah pemanggilan tool dilanjutkan. Tidak seperti hooks lain yang menggunakan bidang `decision` tingkat atas, PreToolUse mengembalikan keputusannya di dalam objek `hookSpecificOutput`. Ini memberikannya kontrol yang lebih kaya: empat hasil (izinkan, tolak, tanya, atau tunda) ditambah kemampuan untuk memodifikasi input tool sebelum eksekusi.
1594 1609
1595| Bidang | Deskripsi |1610| Bidang | Deskripsi |
1596| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1611| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1597| `permissionDecision` | `"allow"` melewati prompt izin. `"deny"` mencegah pemanggilan tool. `"ask"` meminta pengguna untuk mengkonfirmasi. `"defer"` keluar dengan baik sehingga tool dapat dilanjutkan nanti. [Deny and ask rules](/id/permissions#manage-permissions) masih berlaku terlepas dari apa yang dikembalikan hook |1612| `permissionDecision` | `"allow"` melewati prompt izin, kecuali untuk [tools yang memerlukan interaksi pengguna](#pretooluse-decision-control). `"deny"` mencegah pemanggilan tool. `"ask"` meminta pengguna untuk mengkonfirmasi. `"defer"` keluar dengan baik sehingga tool dapat dilanjutkan nanti. [Deny and ask rules](/id/permissions#manage-permissions) masih dievaluasi terlepas dari apa yang dikembalikan hook |
1598| `permissionDecisionReason` | Untuk `"allow"` dan `"ask"`, ditampilkan ke pengguna tetapi bukan Claude. Untuk `"deny"`, ditampilkan ke Claude. Untuk `"defer"`, diabaikan |1613| `permissionDecisionReason` | Untuk `"allow"` dan `"ask"`, ditampilkan ke pengguna tetapi bukan Claude. Untuk `"deny"`, ditampilkan ke Claude. Untuk `"defer"`, diabaikan |
1599| `updatedInput` | Memodifikasi parameter input tool sebelum eksekusi. Menggantikan seluruh objek input, jadi sertakan bidang yang tidak berubah bersama yang dimodifikasi. Gabungkan dengan `"allow"` untuk persetujuan otomatis, atau `"ask"` untuk menampilkan input yang dimodifikasi ke pengguna. Untuk `"defer"`, diabaikan |1614| `updatedInput` | Memodifikasi parameter input tool sebelum eksekusi. Menggantikan seluruh objek input, jadi sertakan bidang yang tidak berubah bersama yang dimodifikasi. Gabungkan dengan `"allow"` untuk persetujuan otomatis, atau `"ask"` untuk menampilkan input yang dimodifikasi ke pengguna. Untuk `"defer"`, diabaikan |
1600| `additionalContext` | String ditambahkan ke konteks Claude bersama hasil tool. Diabaikan ketika `permissionDecision` adalah `"defer"`. Lihat [Tambahkan konteks untuk Claude](#add-context-for-claude) |1615| `additionalContext` | String ditambahkan ke konteks Claude bersama hasil tool. Diabaikan ketika `permissionDecision` adalah `"defer"`. Lihat [Tambahkan konteks untuk Claude](#add-context-for-claude) |
1619 1634
1620`AskUserQuestion` dan `ExitPlanMode` memerlukan interaksi pengguna dan biasanya memblokir dalam [mode non-interaktif](/id/headless) dengan flag `-p`. Mengembalikan `permissionDecision: "allow"` bersama dengan `updatedInput` memenuhi persyaratan itu: hook membaca input tool dari stdin, mengumpulkan jawaban melalui UI Anda sendiri, dan mengembalikannya dalam `updatedInput` sehingga tool dijalankan tanpa meminta. Mengembalikan `"allow"` saja tidak cukup untuk tools ini. Untuk `AskUserQuestion`, kembalikan array `questions` asli dan tambahkan objek [`answers`](#askuserquestion) yang memetakan teks setiap pertanyaan ke jawaban yang dipilih.1635`AskUserQuestion` dan `ExitPlanMode` memerlukan interaksi pengguna dan biasanya memblokir dalam [mode non-interaktif](/id/headless) dengan flag `-p`. Mengembalikan `permissionDecision: "allow"` bersama dengan `updatedInput` memenuhi persyaratan itu: hook membaca input tool dari stdin, mengumpulkan jawaban melalui UI Anda sendiri, dan mengembalikannya dalam `updatedInput` sehingga tool dijalankan tanpa meminta. Mengembalikan `"allow"` saja tidak cukup untuk tools ini. Untuk `AskUserQuestion`, kembalikan array `questions` asli dan tambahkan objek [`answers`](#askuserquestion) yang memetakan teks setiap pertanyaan ke jawaban yang dipilih.
1621 1636
1637Mulai dari v2.1.199, tool MCP yang server-nya menandainya dengan [`_meta["anthropic/requiresUserInteraction"]`](/id/mcp#require-approval-for-a-specific-tool) lebih ketat: hook tidak dapat melewati prompt persetujuannya dengan `"allow"`, dengan atau tanpa `updatedInput`, karena Claude Code tidak dapat mengkonfirmasi hook mengumpulkan interaksi yang dibutuhkan tool.
1638
1622<Note>1639<Note>
1623 PreToolUse sebelumnya menggunakan bidang `decision` dan `reason` tingkat atas, tetapi ini sudah usang untuk event ini. Gunakan `hookSpecificOutput.permissionDecision` dan `hookSpecificOutput.permissionDecisionReason` sebagai gantinya. Nilai usang `"approve"` dan `"block"` memetakan ke `"allow"` dan `"deny"` masing-masing. Events lain seperti PostToolUse dan Stop terus menggunakan `decision` dan `reason` tingkat atas sebagai format saat ini mereka.1640 PreToolUse sebelumnya menggunakan bidang `decision` dan `reason` tingkat atas, tetapi ini sudah usang untuk event ini. Gunakan `hookSpecificOutput.permissionDecision` dan `hookSpecificOutput.permissionDecisionReason` sebagai gantinya. Nilai usang `"approve"` dan `"block"` memetakan ke `"allow"` dan `"deny"` masing-masing. Events lain seperti PostToolUse dan Stop terus menggunakan `decision` dan `reason` tingkat atas sebagai format saat ini mereka.
1624</Note>1641</Note>
2016 Notification2033 Notification
2017</h3>2034</h3>
2018 2035
2019Dijalankan ketika Claude Code mengirimkan notifikasi. Cocok pada tipe notifikasi: `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_complete`, `elicitation_response`. Hilangkan matcher untuk menjalankan hooks untuk semua tipe notifikasi.2036Dijalankan ketika Claude Code mengirimkan notifikasi. Cocok pada tipe notifikasi. Hilangkan matcher untuk menjalankan hooks untuk semua tipe notifikasi.
2037
2038| Matcher | Kapan dijalankan |
2039| :--------------------- | :-------------------------------------------------------------------------------------------------------------------- |
2040| `permission_prompt` | Claude memerlukan persetujuan tool use |
2041| `idle_prompt` | Claude selesai dan menunggu prompt berikutnya Anda |
2042| `auth_success` | Autentikasi selesai |
2043| `elicitation_dialog` | Server MCP membuka formulir elicitation |
2044| `elicitation_complete` | Formulir elicitation MCP dikirimkan atau ditutup |
2045| `elicitation_response` | Respons elicitation MCP dikirim kembali ke server |
2046| `agent_needs_input` | Sesi latar belakang mulai menunggu input Anda. Dijalankan hanya saat [agent view](/id/agent-view) terbuka di terminal |
2047| `agent_completed` | Sesi latar belakang selesai atau gagal. Dijalankan hanya saat [agent view](/id/agent-view) terbuka di terminal |
2048
2049Tipe `agent_needs_input` dan `agent_completed` memerlukan Claude Code v2.1.198 atau lebih baru.
2020 2050
2021Gunakan matchers terpisah untuk menjalankan handler berbeda tergantung pada tipe notifikasi. Konfigurasi ini memicu skrip alert khusus izin ketika Claude memerlukan persetujuan izin dan notifikasi berbeda ketika Claude telah idle:2051Gunakan matchers terpisah untuk menjalankan handler berbeda tergantung pada tipe notifikasi. Konfigurasi ini memicu skrip alert khusus izin ketika Claude memerlukan persetujuan izin dan notifikasi berbeda ketika Claude telah idle:
2022 2052
2079 SubagentStart input2109 SubagentStart input
2080</h4>2110</h4>
2081 2111
2082Selain [bidang input umum](#common-input-fields), SubagentStart hooks menerima `agent_id` dengan pengenal unik untuk subagent dan `agent_type` dengan nama agent (agent bawaan seperti `"general-purpose"`, `"Explore"`, `"Plan"`, atau nama agent kustom).2112Selain [bidang input umum](#common-input-fields), SubagentStart hooks menerima `agent_id` dengan pengenal unik untuk subagent dan `agent_type` dengan nama agent yang matcher filter.
2083 2113
2084```json theme={null}2114```json theme={null}
2085{2115{
2561Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, CwdChanged hooks dapat mengembalikan `watchPaths` untuk secara dinamis menetapkan path file mana yang [FileChanged](#filechanged) pantau:2591Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, CwdChanged hooks dapat mengembalikan `watchPaths` untuk secara dinamis menetapkan path file mana yang [FileChanged](#filechanged) pantau:
2562 2592
2563| Bidang | Deskripsi |2593| Bidang | Deskripsi |
2564| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2594| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2565| `watchPaths` | Array path absolut. Menggantikan daftar watch dinamis saat ini (path dari konfigurasi `matcher` Anda selalu dipantau). Mengembalikan array kosong menghapus daftar dinamis, yang khas saat memasuki direktori baru |2595| `watchPaths` | Array path absolut. Menggantikan daftar watch dinamis saat ini. Path dari konfigurasi `matcher` Anda selalu dipantau. Mengembalikan array kosong menghapus daftar dinamis, yang khas saat memasuki direktori baru |
2566 2596
2567CwdChanged hooks tidak memiliki kontrol keputusan. Mereka tidak dapat memblokir perubahan direktori.2597CwdChanged hooks tidak memiliki kontrol keputusan. Mereka tidak dapat memblokir perubahan direktori.
2568 2598
2586Selain [bidang input umum](#common-input-fields), FileChanged hooks menerima `file_path` dan `event`.2616Selain [bidang input umum](#common-input-fields), FileChanged hooks menerima `file_path` dan `event`.
2587 2617
2588| Bidang | Deskripsi |2618| Bidang | Deskripsi |
2589| :---------- | :------------------------------------------------------------------------------------------------------ |2619| :---------- | :--------------------------------------------------------------------------------------------------------------------------------- |
2590| `file_path` | Path absolut ke file yang berubah |2620| `file_path` | Path absolut ke file yang berubah |
2591| `event` | Apa yang terjadi: `"change"` (file dimodifikasi), `"add"` (file dibuat), atau `"unlink"` (file dihapus) |2621| `event` | Apa yang terjadi: `"change"` untuk file yang dimodifikasi, `"add"` untuk file yang dibuat, atau `"unlink"` untuk file yang dihapus |
2592 2622
2593```json theme={null}2623```json theme={null}
2594{2624{
2608Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, FileChanged hooks dapat mengembalikan `watchPaths` untuk secara dinamis memperbarui path file mana yang dipantau:2638Selain [bidang output JSON](#json-output) yang tersedia untuk semua hooks, FileChanged hooks dapat mengembalikan `watchPaths` untuk secara dinamis memperbarui path file mana yang dipantau:
2609 2639
2610| Bidang | Deskripsi |2640| Bidang | Deskripsi |
2611| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2641| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2612| `watchPaths` | Array path absolut. Menggantikan daftar watch dinamis saat ini (path dari konfigurasi `matcher` Anda selalu dipantau). Gunakan ini ketika skrip hook Anda menemukan file tambahan untuk dipantau berdasarkan file yang berubah |2642| `watchPaths` | Array path absolut. Menggantikan daftar watch dinamis saat ini. Path dari konfigurasi `matcher` Anda selalu dipantau. Gunakan ini ketika skrip hook Anda menemukan file tambahan untuk dipantau berdasarkan file yang berubah |
2613 2643
2614FileChanged hooks tidak memiliki kontrol keputusan. Mereka tidak dapat memblokir perubahan file dari terjadi.2644FileChanged hooks tidak memiliki kontrol keputusan. Mereka tidak dapat memblokir perubahan file dari terjadi.
2615 2645
2617 WorktreeCreate2647 WorktreeCreate
2618</h3>2648</h3>
2619 2649
2620Ketika Anda menjalankan `claude --worktree` atau [subagent menggunakan `isolation: "worktree"`](/id/sub-agents#choose-the-subagent-scope), Claude Code membuat salinan kerja terisolasi menggunakan `git worktree`. Jika Anda mengonfigurasi hook WorktreeCreate, itu menggantikan perilaku git default, memungkinkan Anda menggunakan sistem kontrol versi berbeda seperti SVN, Perforce, atau Mercurial.2650Dijalankan ketika worktree sedang dibuat, baik dari `claude --worktree` atau dari [subagent menggunakan `isolation: "worktree"`](/id/sub-agents#choose-the-subagent-scope). Secara default Claude Code membuat salinan kerja terisolasi dengan `git worktree`. Mengonfigurasi hook WorktreeCreate menggantikan perilaku git default itu, memungkinkan Anda menggunakan sistem kontrol versi berbeda seperti SVN, Perforce, atau Mercurial.
2621 2651
2622Karena hook menggantikan perilaku default sepenuhnya, [`.worktreeinclude`](/id/worktrees#copy-gitignored-files-into-worktrees) tidak diproses. Jika Anda perlu menyalin file konfigurasi lokal seperti `.env` ke worktree baru, lakukan di dalam skrip hook Anda.2652Karena hook menggantikan perilaku default sepenuhnya, [`.worktreeinclude`](/id/worktrees#copy-gitignored-files-into-worktrees) tidak diproses. Jika Anda perlu menyalin file konfigurasi lokal seperti `.env` ke worktree baru, lakukan di dalam skrip hook Anda.
2623 2653
2648 WorktreeCreate input2678 WorktreeCreate input
2649</h4>2679</h4>
2650 2680
2651Selain [bidang input umum](#common-input-fields), WorktreeCreate hooks menerima bidang `name`. Ini adalah pengenal slug untuk worktree baru, baik ditentukan oleh pengguna atau auto-generated (misalnya, `bold-oak-a3f2`).2681Selain [bidang input umum](#common-input-fields), WorktreeCreate hooks menerima bidang `name`. Ini adalah pengenal slug untuk worktree baru, baik ditentukan oleh pengguna atau auto-generated, misalnya `bold-oak-a3f2`.
2652 2682
2653```json theme={null}2683```json theme={null}
2654{2684{
2675 WorktreeRemove2705 WorktreeRemove
2676</h3>2706</h3>
2677 2707
2678Pasangan cleanup untuk [WorktreeCreate](#worktreecreate). Hook ini dijalankan ketika worktree sedang dihapus, baik ketika Anda keluar dari sesi `--worktree` dan memilih untuk menghapusnya, atau ketika subagent dengan `isolation: "worktree"` selesai. Untuk worktrees berbasis git, Claude menangani cleanup secara otomatis dengan `git worktree remove`. Jika Anda mengonfigurasi hook WorktreeCreate untuk sistem kontrol versi non-git, pasangkan dengan hook WorktreeRemove untuk menangani cleanup. Tanpanya, direktori worktree ditinggalkan di disk.2708Dijalankan ketika worktree sedang dihapus, baik ketika Anda keluar dari sesi `--worktree` dan memilih untuk menghapusnya, atau ketika subagent dengan `isolation: "worktree"` selesai. Ini adalah pasangan cleanup untuk [WorktreeCreate](#worktreecreate).
2709
2710Untuk git-based worktrees, Claude Code menangani cleanup secara otomatis dengan `git worktree remove`. Jika Anda mengonfigurasi hook WorktreeCreate untuk sistem kontrol versi non-git, pasangkan dengan hook WorktreeRemove untuk menangani cleanup. Tanpanya, direktori worktree ditinggalkan di disk.
2679 2711
2680Claude Code meneruskan path yang dikembalikan oleh WorktreeCreate sebagai `worktree_path` dalam input hook. Contoh ini membaca path itu dan menghapus direktori:2712Claude Code meneruskan path yang dikembalikan oleh WorktreeCreate sebagai `worktree_path` dalam input hook. Contoh ini membaca path itu dan menghapus direktori:
2681 2713
2835 2867
2836Selain [bidang input umum](#common-input-fields), Elicitation hooks menerima `mcp_server_name`, `message`, dan bidang opsional `mode`, `url`, `elicitation_id`, dan `requested_schema`.2868Selain [bidang input umum](#common-input-fields), Elicitation hooks menerima `mcp_server_name`, `message`, dan bidang opsional `mode`, `url`, `elicitation_id`, dan `requested_schema`.
2837 2869
2838Untuk form-mode elicitation (kasus paling umum):2870Untuk form-mode elicitation, kasus paling umum:
2839 2871
2840```json theme={null}2872```json theme={null}
2841{2873{
2856}2888}
2857```2889```
2858 2890
2859Untuk URL-mode elicitation (autentikasi berbasis browser):2891Untuk URL-mode elicitation, digunakan untuk autentikasi berbasis browser:
2860 2892
2861```json theme={null}2893```json theme={null}
2862{2894{
3064 3096
3065Jika Anda memerlukan kontrol yang lebih halus pada event apa pun, gunakan [command hook](#command-hook-fields) dengan bidang per-event yang dijelaskan dalam [Decision control](#decision-control).3097Jika Anda memerlukan kontrol yang lebih halus pada event apa pun, gunakan [command hook](#command-hook-fields) dengan bidang per-event yang dijelaskan dalam [Decision control](#decision-control).
3066 3098
3067<h3 id="example-multi-criteria-stop-hook">3099<h3 id="check-multiple-conditions-before-stopping">
3068 Contoh: Multi-criteria Stop hook3100 Periksa beberapa kondisi sebelum berhenti
3069</h3>3101</h3>
3070 3102
3071Hook `Stop` ini menggunakan prompt detail untuk memeriksa tiga kondisi sebelum mengizinkan Claude berhenti. Jika `"ok"` adalah `false`, Claude terus bekerja dengan alasan yang disediakan sebagai instruksi berikutnya. Hooks `SubagentStop` menggunakan format yang sama untuk mengevaluasi apakah [subagent](/id/sub-agents) harus berhenti:3103Hook `Stop` ini menggunakan prompt detail untuk memeriksa tiga kondisi sebelum mengizinkan Claude berhenti. Hooks `SubagentStop` menggunakan format yang sama untuk mengevaluasi apakah [subagent](/id/sub-agents) harus berhenti. Jika `"ok"` adalah `false`, Claude terus bekerja dengan alasan yang disediakan sebagai instruksi berikutnya:
3072 3104
3073```json theme={null}3105```json theme={null}
3074{3106{
3192 3224
3193Notifikasi penyelesaian async hook ditekan secara default. Untuk melihatnya, aktifkan mode verbose dengan `Ctrl+O` atau mulai Claude Code dengan `--verbose`.3225Notifikasi penyelesaian async hook ditekan secara default. Untuk melihatnya, aktifkan mode verbose dengan `Ctrl+O` atau mulai Claude Code dengan `--verbose`.
3194 3226
3195<h3 id="example-run-tests-after-file-changes">3227<h3 id="run-tests-after-file-changes">
3196 Contoh: jalankan tests setelah perubahan file3228 Jalankan tests setelah perubahan file
3197</h3>3229</h3>
3198 3230
3199Hook ini memulai test suite di latar belakang setiap kali Claude menulis file, kemudian melaporkan hasil kembali ke Claude ketika tests selesai. Simpan skrip ini ke `.claude/hooks/run-tests-async.sh` dalam proyek Anda dan buat dapat dijalankan dengan `chmod +x`:3231Hook ini memulai test suite di latar belakang setiap kali Claude menulis file, kemudian melaporkan hasil kembali ke Claude ketika tests selesai. Simpan skrip ini ke `.claude/hooks/run-tests-async.sh` dalam proyek Anda dan buat dapat dijalankan dengan `chmod +x`:
3287 Windows PowerShell tool3319 Windows PowerShell tool
3288</h2>3320</h2>
3289 3321
3290Di Windows, Anda dapat menjalankan hook individual dalam PowerShell dengan menetapkan `"shell": "powershell"` pada command hook. Hooks spawn PowerShell secara langsung, jadi ini bekerja terlepas dari apakah `CLAUDE_CODE_USE_POWERSHELL_TOOL` diatur. Claude Code auto-detects `pwsh.exe` (PowerShell 7+) dengan fallback ke `powershell.exe` (5.1).3322Di Windows, Anda dapat menjalankan hook individual dalam PowerShell dengan menetapkan `"shell": "powershell"` pada command hook. Hooks spawn PowerShell secara langsung, jadi ini bekerja terlepas dari apakah `CLAUDE_CODE_USE_POWERSHELL_TOOL` diatur. Claude Code auto-detects `pwsh.exe`, executable PowerShell 7 dan yang lebih baru, dan fallback ke `powershell.exe` untuk Windows PowerShell 5.1.
3291 3323
3292```json theme={null}3324```json theme={null}
3293{3325{
3308}3340}
3309```3341```
3310 3342
3311Untuk mereferensikan root proyek dari perintah bentuk shell PowerShell, bacalah sebagai variabel lingkungan dengan `$env:CLAUDE_PROJECT_DIR`. PowerShell memperlakukan bentuk `${CLAUDE_PROJECT_DIR}` bare sebagai variabel lokal, bukan pencarian lingkungan, dan Claude Code mengganti placeholder itu dalam bentuk shell hanya untuk [plugin hooks](#reference-scripts-by-path). Untuk hook yang didefinisikan dalam `settings.json`, gunakan bentuk `$env:` atau beralih ke [exec form](#exec-form-and-shell-form), di mana `${CLAUDE_PROJECT_DIR}` diganti di setiap elemen `args` terlepas dari di mana hook didefinisikan.3343Untuk mereferensikan root proyek dari perintah bentuk shell PowerShell, tulis `${CLAUDE_PROJECT_DIR}` atau `$env:CLAUDE_PROJECT_DIR`. Mulai dari v2.1.198, Claude Code menulis ulang placeholder `${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`, dan `${CLAUDE_PLUGIN_DATA}` dalam perintah bentuk shell PowerShell ke bentuk `${env:NAME}` PowerShell, baik hook didefinisikan dalam `settings.json`, plugin, atau skill. PowerShell kemudian menyelesaikan nilai dari lingkungan yang diekspor setelah parsing, jadi placeholder bekerja di dalam string dengan tanda kutip ganda tetapi tidak di dalam string dengan tanda kutip tunggal, di mana PowerShell tidak pernah memperluas variabel.
3344
3345Sebelum v2.1.198, penulisan ulang ini hanya berlaku untuk plugin hooks. Pada versi yang lebih awal, hook `settings.json` memerlukan bentuk `$env:` atau [exec form](#exec-form-and-shell-form), di mana `${CLAUDE_PROJECT_DIR}` diganti di setiap elemen `args` terlepas dari di mana hook didefinisikan.
3346
3347Jangan tulis ejaan bare `$CLAUDE_PROJECT_DIR` dalam hook PowerShell. PowerShell menguraikannya sebagai variabel lokal yang tidak terdefinisi dan menyelesaikannya ke `$null`, yang meninggalkan jalur skrip tanpa awalan root proyeknya. Claude Code tidak menulis ulang bentuk itu; sebaliknya, ia mencatat peringatan dalam [debug log](#debug-hooks).
3312 3348
3313Contoh di bawah menunjukkan hook `settings.json` yang menjalankan skrip proyek dengan bentuk `$env:`:3349Contoh di bawah menunjukkan hook `settings.json` yang menjalankan skrip proyek dengan bentuk `$env:`, yang bekerja di setiap versi:
3314 3350
3315```json theme={null}3351```json theme={null}
3316{3352{