
Claude Code Hooks: Panduan Lengkap untuk Developer dengan Contoh Siap Produksi
Claude Code sangat andal dalam menulis kode, tetapi sistem ini tetaplah probabilistik. Anda bisa memintanya menjalankan Prettier setelah setiap pengeditan file. Anda bisa menaruh instruksi itu di CLAUDE.md Anda. Dan kadang-kadang, ia akan begitu saja... lupa. Claude Code hooks mengatasi masalah ini dengan memberi Anda kendali yang deterministik dan terjamin atas apa yang terjadi sebelum, selama, dan setelah setiap tindakan yang diambil Claude.
Selama beberapa bulan terakhir, saya telah mengonfigurasi hooks di puluhan proyek, dan hooks secara diam-diam telah menjadi bagian terpenting dari setup Claude Code saya. Panduan ini mencakup segalanya, mulai dari dasar-dasar hingga starter kit siap produksi yang bisa Anda langsung gunakan di proyek mana pun hari ini. Jika Anda pernah menggunakan Claude Code bersama tool seperti Cursor atau Copilot, Anda sudah tahu nilai dari kustomisasi, hooks membawanya selangkah lebih jauh.
Apa Itu Claude Code Hooks (dan Mengapa Anda Perlu Peduli)?
Claude Code hooks adalah perintah shell, endpoint HTTP, atau prompt LLM yang ditentukan pengguna, yang dieksekusi secara otomatis pada titik-titik tertentu dalam siklus hidup Claude Code. Menurut dokumentasi resmi Anthropic, berbeda dengan instruksi prompt yang mungkin diabaikan oleh Claude, hooks dipicu secara deterministik setiap saat, memberi Anda kendali yang terjamin atas pemformatan, keamanan, notifikasi, dan otomatisasi alur kerja.
Masalah Probabilistik
Begini soal instruksi CLAUDE.md: instruksi itu saran, bukan kontrak. Anda bisa menulis "selalu jalankan npx prettier --write setelah mengedit file TypeScript" di konteks proyek Anda, dan Claude akan mengikutinya sebagian besar waktu. Tapi "sebagian besar waktu" tidak cukup baik ketika Anda menegakkan pemformatan kode di seluruh tim, atau memblokir push ke production, atau mencatat setiap perintah shell untuk audit keamanan.
Inilah ketegangan inti dalam setiap tool coding AI. Claude adalah model bahasa, ia beroperasi berdasarkan probabilitas. Context engineering Anda bisa mendorong perilaku, tapi tidak bisa menjaminnya.
Bagaimana Hooks Memecahkan Masalah Ini
Hooks sama sekali melewati LLM. Hooks adalah skrip shell, panggilan HTTP, atau evaluasi AI yang dijalankan pada event siklus hidup tertentu—sebelum tool berjalan (PreToolUse), setelah selesai (PostToolUse), saat notifikasi muncul, saat sesi dimulai, atau saat Claude berhenti. Anggap saja seperti Git hooks, tapi untuk asisten coding AI Anda.
Ada empat jenis hook: command (skrip shell), HTTP (permintaan POST webhook), prompt (evaluasi ya/tidak Claude satu giliran), dan agent (melahirkan subagent dengan akses tool). Kita akan membahas masing-masing nanti—command hook menangani sekitar 90% kebutuhan Anda.
Cara Kerja Claude Code Hooks: Alur Siklus Hidup
Claude Code hooks dieksekusi dalam siklus hidup yang telah ditentukan: sebuah event dipicu (misalnya, PreToolUse), matcher memeriksa apakah hook tersebut berlaku, skrip hook dijalankan dan menerima JSON melalui stdin, lalu exit code menentukan apa yang terjadi selanjutnya. Exit code 0 berarti lanjutkan, exit code 2 berarti memblokir aksi tersebut. Alur ini sama, apa pun jenis hook yang Anda gunakan.
Event -> Matcher -> Hook -> Exit Code (Alur 4 Langkah)
Berikut cara kerja setiap eksekusi hook:
1. EVENT FIRES e.g., PreToolUse(Write)
|
2. MATCHER CHECKS Does "Write" match the hook's matcher pattern?
|
3. HOOK EXECUTES Shell script runs, receives JSON via stdin
|
4. EXIT CODE DECIDES 0 = proceed | 2 = block | other = errorJSON yang diterima melalui stdin berisi semua informasi tentang event tersebut: tool_name, tool_input (path file, konten, perintah), dan metadata sesi. Skrip Anda membaca JSON ini, menjalankan logika yang diperlukan, lalu keluar dengan kode yang sesuai.
Untuk hook PreToolUse, exit code 2 adalah yang paling berpengaruh—kode ini memblokir aksi sepenuhnya dan mengirimkan pesan stdout Anda kembali ke Claude sebagai umpan balik. Claude melihat pesan Anda dan dapat menyesuaikan pendekatannya.
Cakupan Konfigurasi: Pengguna, Proyek, dan Lokal
Hooks berada di settings.json pada tiga level:
| Cakupan | File | Di-commit ke Git? | Kasus Penggunaan |
|---|---|---|---|
| Pengguna | ~/.claude/settings.json | Tidak | Default pribadi (notifikasi, preferensi pemformatan) |
| Proyek | .claude/settings.json | Ya | Hooks yang dibagikan tim (perlindungan file, test runner, linting) |
| Lokal | .claude/settings.local.json | Tidak (di-gitignore) | Override pribadi untuk proyek ini |
Pengaturan proyek adalah yang paling berguna bagi tim. Letakkan hooks Anda ke .claude/settings.json, commit file tersebut, dan setiap developer di tim akan mendapatkan guardrail yang sama secara otomatis.
Field if: Penyaringan yang Lebih Spesifik
Sejak Claude Code v2.1.85, hooks mendukung field if yang memungkinkan Anda menyaring berdasarkan argumen tool, bukan hanya nama tool. Sebagaimana didokumentasikan dalam referensi hooks Anthropic, ini berarti Anda dapat menulis hook yang hanya terpicu pada perintah Bash yang cocok dengan git push, alih-alih berjalan pada setiap pemanggilan Bash.
{
"matcher": "Bash",
"if": "tool_input.command matches 'git push'",
"hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}Ini merupakan peningkatan besar. Sebelum adanya if, Anda harus mencocokkan terlalu luas (setiap perintah Bash) atau melakukan penyaringan di dalam skrip Anda (berantakan).
Semua Event Hook Claude Code: Tabel Referensi Cepat
Claude Code menyediakan lebih dari 20 event hook di seluruh siklus hidupnya, sebagaimana didokumentasikan dalam referensi hook resmi dan changelog Claude Code. Yang paling umum digunakan adalah PreToolUse, PostToolUse, Notification, dan Stop, tetapi event yang lebih baru seperti ConfigChange dan FileChanged membuka pola otomasi tingkat lanjut.
Berikut referensi lengkapnya:
| Event | Kapan Dipicu | Bisa Memblokir? | Kasus Penggunaan Umum |
|---|---|---|---|
| PreToolUse | Sebelum tool dieksekusi | Ya (exit 2) | Memblokir perintah berbahaya, melindungi file |
| PostToolUse | Setelah tool selesai | Tidak | Format otomatis, menjalankan tes, mencatat tindakan |
| Notification | Saat Claude mengirim notifikasi | Tidak | Peringatan desktop, pesan Slack |
| Stop | Saat Claude menyelesaikan respons | Tidak | Pembersihan, pembuatan ringkasan |
| SessionStart | Saat inisialisasi sesi | Tidak | Menyisipkan konteks, mengatur environment |
| UserPromptSubmit | Saat pengguna mengirim prompt | Ya (exit 2) | Validasi input, penyaringan konten |
| PreCompact | Sebelum pemadatan konteks | Tidak | Menyimpan status sebelum memori dipangkas |
| PostCompact | Setelah pemadatan konteks | Tidak | Menyisipkan kembali konteks penting |
| ConfigChange | Saat pengaturan berubah | Tidak | Hot-reload variabel environment |
| FileChanged | Saat file yang dipantau berubah | Tidak | Memicu rebuild, membatalkan cache |
| TaskCreated | Saat task baru dibuat | Tidak | Pelacakan task, alokasi sumber daya |
| PermissionDenied | Saat pemeriksaan izin gagal | Tidak | Pencatatan audit, peringatan untuk tindakan yang diblokir |
| WorktreeCreate | Saat Git worktree baru dibuat | Tidak | Menginisialisasi pengaturan khusus worktree |
| SubagentStart | Saat subagent dimulai | Tidak | Memantau aktivitas subagent |
| SubagentStop | Saat subagent selesai | Tidak | Memvalidasi output subagent |
Tips pro: Anda akan menggunakan PreToolUse dan PostToolUse untuk 80% hook Anda. SessionStart adalah yang paling berguna berikutnya, sangat cocok untuk menyisipkan konteks proyek yang dibutuhkan Claude di awal setiap sesi.
Penjelasan 4 Jenis Hook Claude Code
Claude Code mendukung empat jenis handler hook: command hook menjalankan skrip shell, HTTP hook melakukan POST ke URL, prompt hook menanyakan pertanyaan ya/tidak kepada Claude, dan agent hook memunculkan subagent dengan akses tool. Berdasarkan pengalaman kami, command hook menangani 90% kasus penggunaan. Gunakan HTTP untuk integrasi eksternal, serta prompt dan agent hook untuk keputusan bernuansa yang membutuhkan penilaian AI.
| Jenis | Kecepatan | Kompleksitas | Paling Cocok Untuk | Contoh |
|---|---|---|---|---|
| Command | Cepat | Rendah | Pemformatan, pemblokiran, pencatatan log | Menjalankan Prettier setelah mengedit file |
| HTTP | Sedang | Sedang | Layanan eksternal, webhook | Melakukan POST ke Slack saat selesai |
| Prompt | Lambat | Sedang | Keputusan subjektif | "Apakah kode ini aman untuk dijalankan?" |
| Agent | Paling lambat | Tinggi | Verifikasi kompleks yang menyadari file | Memeriksa apakah kode baru mengikuti pola proyek |
Hook Perintah (Andalan Utama)
Hook perintah menjalankan perintah shell dan menggunakan exit code untuk menentukan hasilnya. Hook ini menerima data JSON dari event melalui stdin.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
}]
}]
}
}Inilah yang akan Anda gunakan untuk pemformatan, perlindungan file, notifikasi, dan sebagian besar otomatisasi. Cepat, sederhana, dan dapat diprediksi.
HTTP Hooks (Integrasi Eksternal)
HTTP hooks mengirim permintaan POST ke sebuah URL dengan JSON event sebagai body-nya. Kode status respons menentukan hasilnya (200 = lanjut, 403 = blokir).
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "http",
"url": "https://your-api.com/claude-webhook"
}]
}]
}
}Cocok untuk mengirim event ke Slack, Discord, PagerDuty, atau dashboard kustom. Anda juga bisa menggunakannya untuk meng-query policy engine eksternal sebelum mengizinkan eksekusi sebuah tool.
Prompt Hook (Keputusan Berbasis AI)
Prompt hook meneruskan data event ke Claude itu sendiri untuk evaluasi ya/tidak dalam satu giliran. Claude mengembalikan respons JSON berisi \"decision\": \"allow\" atau \"decision\": \"block\" beserta alasannya.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "prompt",
"prompt": "Is this bash command safe to run in a production environment? Consider: does it modify system files, delete data, or access sensitive credentials?"
}]
}]
}
}Gunakan ini secukupnya. Hook ini menambah latensi (satu panggilan LLM penuh per eksekusi hook) dan biaya. Namun untuk pemeriksaan keamanan yang benar-benar subjektif, seperti "apakah migrasi database ini terlihat merusak?", sulit untuk ditandingi. Jika Anda penasaran tentang mengganti model Claude Code, model yang digunakan untuk prompt hook mengikuti model sesi Anda saat ini.
Hook Agen (Verifikasi Berbantuan Alat)
Hook agen meluncurkan subagen yang memiliki akses ke alat Read, Grep, dan Glob. Subagen dapat memeriksa file sebelum mengambil keputusan.
{
"hooks": {
"PreToolUse": [{
"matcher": "Write",
"hooks": [{
"type": "agent",
"prompt": "Check if the file being written follows the project's naming conventions and import patterns. Read .claude/CONVENTIONS.md for the rules."
}]
}]
}
}Ini adalah jenis hook yang paling kuat, tetapi juga paling lambat. Gunakan hanya untuk pemeriksaan berisiko tinggi yang membutuhkan konteks file agar dapat mengambil keputusan dengan tepat.
7 Contoh Hook Claude Code Siap Produksi (Tinggal Salin-Tempel)
Hook Claude Code yang paling berguna antara lain pemformatan otomatis dengan Prettier atau Black setelah pengeditan file, memblokir penulisan ke file yang dilindungi, mengirim notifikasi desktop saat tugas selesai, menyuntikkan konteks proyek di awal sesi, menjalankan pengujian setelah perubahan kode, menegakkan perlindungan branch, dan mengaudit semua penggunaan tool. Saya telah menjalankan berbagai variasinya di setiap proyek selama tiga bulan terakhir.
Setiap contoh di bawah ini adalah cuplikan settings.json lengkap yang bisa langsung Anda letakkan di .claude/settings.json milik Anda. Koleksi komunitas seperti awesome-claude-code memiliki lebih banyak pola lagi.
1. Format Otomatis saat Menyimpan
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}]
}
}Hook ini terpicu setelah setiap Write atau Edit, mengekstrak path file dari JSON stdin, dan menjalankan formatter yang sesuai. exit 0 di akhir memastikan hook tidak pernah memblokir—kegagalan formatting tidak boleh menghentikan Claude.
Pro tip: Tambahkan *.go dengan gofmt dan *.rs dengan rustfmt jika Anda bekerja lintas bahasa.
2. Blokir Penulisan ke File yang Dilindungi
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\.local|package-lock\\.json|yarn\\.lock|pnpm-lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: This file is protected. Edit it manually.\"}' && exit 2"
}]
}]
}
}Kode keluar 2 memblokir tindakan tersebut dan mengirim pesan JSON kembali ke Claude. Claude melihat umpan balik itu dan menyesuaikan diri, biasanya ia akan memberi tahu bahwa ia ingin mengubah file tersebut dan meminta Anda melakukannya secara manual. Field if mencegah hal ini terpicu pada setiap Write.
3. Notifikasi Desktop saat Selesai
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Claude Code task finished\"' /dev/stdin); if [ \"$(uname)\" = 'Darwin' ]; then osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\"; else notify-send 'Claude Code' \"$MSG\"; fi; exit 0"
}]
}]
}
}Berfungsi di macOS (osascript) dan Linux (notify-send). Matcher yang kosong berarti notifikasi ini akan dipicu untuk semua notifikasi. Ini benar-benar berguna saat Anda menjalankan tugas yang memakan waktu lama lalu beralih ke jendela lain.
4. Injeksi Konteks di Awal Sesi
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null || echo none)\"' | Last commit: '\"$(git log --oneline -1 2>/dev/null || echo none)\"'\"}'; exit 0"
}]
}]
}
}Ini menginjeksikan nama proyek saat ini, branch Git, dan commit terakhir ke dalam setiap sesi. Claude menerima konteks ini secara otomatis, tanpa perlu memberi tahu branch mana yang sedang Anda gunakan.
5. Menjalankan Tes Secara Otomatis Setelah Perubahan Kode
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '\\.(ts|tsx|js|jsx|py)$'",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path' /dev/stdin); TEST_FILE=$(echo \"$FILE\" | sed 's/\\.[^.]*$/.test&/'); if [ -f \"$TEST_FILE\" ]; then npx jest \"$TEST_FILE\" --no-coverage 2>&1 | tail -5; fi; exit 0",
"timeout": 30000
}]
}]
}
}Jika file tes yang sesuai ada, tes tersebut akan berjalan secara otomatis setelah Claude mengedit sumbernya. tail -5 menjaga agar output tetap ringkas, dan timeout mencegah rangkaian tes berjalan tak terkendali. Ini sangat cocok dipadukan dengan alur kerja tinjauan kode berbasis AI.
6. Penerapan Proteksi Branch (Lanjutan)
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"if": "tool_input.command matches 'git push.*(main|master|production)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: Direct push to protected branch. Use a feature branch and open a PR.\"}' && exit 2"
}]
}]
}
}Ini memblokir setiap git push yang menargetkan branch main, master, atau production. Claude akan menerima umpan balik tersebut dan akan menyarankan untuk membuat branch fitur sebagai gantinya.
7. Pencatatan Audit Keamanan (Lanjutan)
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "INPUT=$(cat /dev/stdin); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] BASH: $CMD\" >> .claude/audit.log; exit 0"
}]
}]
}
}Mencatat setiap perintah Bash yang dijalankan Claude ke dalam file audit dengan stempel waktu UTC. Sangat berguna untuk tinjauan keamanan dan memahami apa yang sebenarnya dilakukan Claude selama sesi berlangsung. Tambahkan .claude/audit.log ke dalam .gitignore Anda.
Hooks vs MCP vs Skills vs CLAUDE.md: Kapan Menggunakan yang Mana
Gunakan hooks untuk otomatisasi deterministik yang harus selalu berjalan (formatting, pemblokiran, notifikasi). Gunakan MCP untuk memberi Claude akses ke alat dan data eksternal. Gunakan Skills untuk paket prompt yang dapat digunakan kembali. Gunakan CLAUDE.md untuk panduan perilaku dan konteks proyek. Hooks bersifat terjamin; semuanya yang lain bersifat probabilistik. Inilah satu-satunya perbedaan paling penting, dan saya selalu kembali ke poin ini saat memberi saran kepada tim.
Matriks Keputusan
| Mekanisme | Deterministik? | Kapan Berjalan | Paling Cocok Untuk | Contoh |
|---|---|---|---|---|
| Hooks | Ya | Otomatis pada event lifecycle | Penegakan aturan, otomatisasi, notifikasi | Auto-format, memblokir penulisan file |
| MCP | Tidak (Claude yang memutuskan) | Saat Claude memanggil MCP tool | Kapabilitas baru, akses data eksternal | Query database, mencari di Notion |
| Skills | Tidak (pengguna yang memicu) | Saat pengguna menjalankan slash command | Set instruksi yang dapat digunakan ulang | /review untuk alur kerja code review |
| CLAUDE.md | Tidak (panduan) | Dibaca saat sesi dimulai | Konteks proyek, standar penulisan kode | "Gunakan Tailwind, tulis tes untuk semua kode baru" |
Untuk pembahasan mendalam tentang MCP, lihat panduan MCP kami. Jika Anda beralih dari Cursor, sistem rules Cursor kurang lebih setara dengan CLAUDE.md, tetapi Cursor tidak memiliki fitur seperti hooks.
Ketika Semuanya Tumpang Tindih (dan Cara Memilihnya)
Berikut diagram alir yang saya gunakan:
- "Apakah ini HARUS terjadi setiap saat, tanpa pengecualian?", Hook. Memformat kode, memblokir file yang dilindungi, mengirim notifikasi. Tanpa ambiguitas.
- "Apakah Claude membutuhkan KEMAMPUAN baru yang belum dimilikinya?", server MCP. Mengakses database, memanggil API, mencari dokumen eksternal.
- "Apakah saya ingin INSTRUKSI yang dapat digunakan kembali untuk alur kerja tertentu?", Skill (perintah slash). Template tinjauan kode, daftar periksa deployment.
- "Apakah saya ingin membentuk PERILAKU Claude dalam proyek ini?", CLAUDE.md. Standar pengkodean, keputusan arsitektur, library pilihan.
Contoh nyata yang memperjelas batasannya:
- "Selalu format dengan Prettier" = Hook (harus terjadi setiap saat)
- "Gunakan Prettier untuk pemformatan" di CLAUDE.md = Panduan (Claude mungkin lupa)
- "Cari dokumen perusahaan kami" = MCP (kemampuan baru)
- "Ikuti panduan gaya kami saat meninjau kode" = Skill atau CLAUDE.md
Seperti yang dijelaskan dalam pengumuman plugin Anthropic, hook adalah salah satu bagian dari ekosistem plugin yang lebih luas, yang juga mencakup MCP dan Skill. Semuanya dirancang untuk saling melengkapi, bukan bersaing.
Starter Kit: Konfigurasi Claude Code Hooks Siap Pakai untuk Proyek Apa Pun
Konfigurasi hooks awal untuk Claude Code sebaiknya mencakup auto-format saat file diedit, notifikasi saat tugas selesai, perlindungan untuk file-file sensitif, injeksi konteks sesi, dan stop hook untuk pembersihan. Inilah konfigurasi persis yang saya terapkan di setiap proyek baru, disesuaikan dengan stack yang digunakan, tetapi strukturnya tetap sama.
Konfigurasi
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null)\"' | Node: '\"$(node -v 2>/dev/null)\"'\"}'; exit 0"
}]
}],
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\..+|.*lock\\.json|.*lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Protected file. Edit manually.\"}' && exit 2"
}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; *.go) gofmt -w \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}],
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Done\"' /dev/stdin); osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\" 2>/dev/null || notify-send 'Claude Code' \"$MSG\" 2>/dev/null; exit 0"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '[STOP] '\"$(date +%H:%M:%S)\"'' >> .claude/session.log; exit 0"
}]
}]
}
}Cara Menyesuaikan untuk Stack Anda
| Stack | Perintah Format | Perintah Test | Ekstensi Watch |
|---|---|---|---|
| Node/TypeScript | npx prettier --write | npx jest --no-coverage | .ts, .tsx, .js, .jsx |
| Python | black | pytest -x | .py |
| Go | gofmt -w | go test ./... | .go |
| Rust | rustfmt | cargo test | .rs |
Ganti perintah format dan test pada konfigurasi di atas agar sesuai dengan stack Anda. Strukturnya tetap sama persis.
Memastikan Hook Anda Berfungsi
Tiga cara untuk memastikan hook aktif:
- Perintah
/hooks, Ketik/hooksdi Claude Code untuk melihat semua hook yang terdaftar, matcher-nya, dan statusnya. - Pemeriksaan transkrip, Setelah hook berjalan, periksa transkrip sesi. Eksekusi hook akan muncul beserta output dan kode keluarnya.
- Toggle cepat, Tambahkan
"disableAllHooks": trueke settings.json Anda untuk menonaktifkan semua hook sementara tanpa menghapus konfigurasinya. Hapus pengaturan tersebut (atau setel kefalse) untuk mengaktifkannya kembali.
Integrasi CI/CD: Hook Claude Code dalam Mode Headless
Hook Claude Code bekerja dalam mode headless (claude -p) dengan beberapa perbedaan: Hook notifikasi tetap berjalan, tetapi Anda sebaiknya mengalihkannya ke pencatatan log alih-alih peringatan desktop. Hook PreToolUse dengan kode keluar 2 dapat menjeda sesi headless untuk tinjauan manusia. GitHub Actions menggunakan anthropics/claude-code-action@v1 bersama dengan hook untuk alur kerja otomatis.
Perilaku Mode Headless
| Event Hook | Mode Interaktif | Mode Headless (-p) | Rekomendasi CI |
|---|---|---|---|
| PreToolUse (exit 2) | Memblokir, menampilkan pesan | Menjeda untuk --resume | Gunakan untuk persetujuan manusia yang wajib |
| PostToolUse | Berjalan normal | Berjalan normal | Pertahankan formatter dan logger |
| Notification | Peringatan desktop | Tetap berjalan (tanpa UI) | Alihkan ke file log atau webhook Slack |
| Stop | Menjalankan pembersihan | Menjalankan pembersihan | Cocok untuk pengumpulan artefak CI |
| SessionStart | Menyuntikkan konteks | Menyuntikkan konteks | Suntikkan variabel lingkungan CI |
Kejutan besar dalam mode headless: hook PreToolUse yang keluar dengan kode 2 tidak sekadar gagal secara diam-diam. Hook tersebut menjeda sesi dan memungkinkan Anda melanjutkannya dengan --resume, yang memberi Anda pola human-in-the-loop untuk pipeline CI.
Integrasi GitHub Actions
Berikut adalah alur kerja GitHub Actions minimal yang menggunakan Claude Code dengan hooks. Sebagaimana didokumentasikan dalam panduan resmi GitHub Actions:
- name: Run Claude Code
uses: anthropics/claude-code-action@v1
with:
prompt: "Review this PR and suggest improvements"
allowed_tools: "Read,Grep,Glob"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}Hooks di .claude/settings.json Anda ikut tersimpan bersama repo, sehingga akan berjalan di CI persis seperti saat dijalankan secara lokal. Pastikan saja setiap hooks yang bergantung pada alat khusus desktop (seperti osascript) memiliki fallback atau kondisional.
Manajemen Hook Tim
Sebuah pola yang bekerja dengan baik untuk tim:
.claude/settings.json(di-commit), Hook yang dibagikan untuk tim: perlindungan file, formatter, perlindungan branch. Semua orang mendapatkan ini..claude/settings.local.json(di-gitignore), Hook pribadi: preferensi notifikasi, logging kustom, hook eksperimental.~/.claude/settings.json(global pengguna), Default Anda di semua proyek: gaya notifikasi, preferensi pemformatan pribadi.
Ini mencerminkan cara kerja .editorconfig (di-commit) dan pengaturan IDE lokal (pribadi). Seperti yang dicatat oleh panduan CI/CD Angelo Lima, tim yang menstandardisasi hook bersama mengalami lebih sedikit masalah "works on my machine" dengan Claude Code.
Troubleshooting Hook Claude Code dan Kesalahan Umum
Masalah umum pada hook Claude Code meliputi hook yang tidak berjalan (periksa ejaan matcher dan lokasi settings.json), hook yang berjalan tetapi tidak memblokir (kode exit salah, gunakan 2 bukan 1), infinite loop (hook Stop memicu dirinya sendiri), dan startup yang lambat (terlalu banyak hook sinkron). Kesalahan paling umum yang saya temui adalah kebingungan kode exit—developer menggunakan exit 1 padahal yang dimaksud adalah exit 2.
Hook Tidak Terpicu
Gejala: Anda telah menambahkan hook, tetapi tidak ada yang terjadi saat event muncul.
Perbaikan:
- Salah ketik matcher, Matcher bersifat case-sensitive.
\"write\"tidak akan cocok dengan toolWrite. Periksa nama tool yang tepat dengan/hooks. - File pengaturan salah, Hook di
~/.claude/settings.jsontidak akan muncul di output/hooksuntuk scope proyek. Coba.claude/settings.jsondi root proyek. - Kesalahan sintaks JSON, Koma yang terselip atau kurung yang hilang akan menonaktifkan seluruh konfigurasi hook secara diam-diam. Jalankan settings.json Anda melalui
jq .untuk memvalidasinya. disableAllHooks: true, Periksa apakah seseorang (atau sesi debug sebelumnya) membiarkan flag ini tetap aktif.
Hook Berjalan tetapi Tidak Memblokir
Gejala: Hook PreToolUse Anda tereksekusi, tetapi tindakan tetap berjalan.
Perbaikan:
- Kode keluar salah, Kode keluar 1 berarti "error" (hook gagal), bukan "blokir." Gunakan
exit 2untuk memblokir sebuah tindakan. Hal ini menjebak hampir semua orang, sebagaimana dicatat dalam dokumentasi resmi. - JSON stdout tidak ada, Untuk hook pemblokiran, keluarkan pesan JSON agar Claude tahu mengapa tindakan tersebut diblokir:
echo '{"message": "Blocked: reason"}'
Perulangan Tak Berujung
Gejala: Claude terus mencoba ulang tindakan yang sama, atau mesin Anda menjadi panas secara mencurigakan.
Solusi:
- Hook Stop memicu tindakan, Jika hook Stop Anda menulis file atau menjalankan perintah yang menyebabkan Claude merespons, Anda telah menciptakan sebuah perulangan. Hook Stop seharusnya hanya melakukan hal-hal pasif: mencatat log, mengirim notifikasi, atau membersihkan.
- Hook PostToolUse menyebabkan pengeditan, Hook PostToolUse yang memodifikasi file akan memicu event PostToolUse lainnya. Cegah hal ini dengan matcher yang spesifik atau field
if.
Masalah Performa
Gejala: Claude terasa jauh lebih lambat saat memulai atau menjalankan tool.
Solusi:
- Terlalu banyak hook SessionStart, Masing-masing hook berjalan secara sinkron saat startup. Pastikan hook tetap ringan (masing-masing di bawah 1 detik).
- Skrip berat di jalur yang sering dieksekusi, Hook pada PreToolUse dan PostToolUse sering terpicu. Jika skrip Anda melakukan permintaan jaringan atau komputasi berat, tambahkan field
timeout(milidetik) dan pertimbangkan apakah sebaiknya menggunakan hook HTTP saja. - Tidak ada caching, Jika Anda memeriksa hal yang sama berulang kali (seperti "apakah ini branch yang dilindungi?"), simpan hasilnya di file sementara alih-alih menjalankan perintah Git pada setiap pemanggilan hook.
Pertanyaan yang Sering Diajukan
Apa itu hook Claude Code dan bagaimana cara kerjanya?
Hook Claude Code adalah skrip otomatisasi yang ditentukan pengguna dan dieksekusi pada event siklus hidup tertentu selama sesi Claude Code. Anda mengonfigurasinya di settings.json dengan pola matcher dan handler (perintah shell, endpoint HTTP, prompt, atau agen). Ketika event yang cocok terpicu, hook akan berjalan secara otomatis dan menggunakan kode keluar (exit code) untuk mengontrol hasilnya.
Bagaimana cara mengonfigurasi hooks di settings.json Claude Code?
Tambahkan objek "hooks" ke salah satu dari tiga lokasi konfigurasi: ~/.claude/settings.json (global-pengguna), .claude/settings.json (bersama-proyek), atau .claude/settings.local.json (pribadi-proyek). Setiap jenis event dipetakan ke sebuah array berisi definisi hook dengan matcher, field if opsional, dan array hooks yang berisi objek handler dengan type serta command atau url.
Apa perbedaan antara hook PreToolUse dan PostToolUse?
PreToolUse berjalan sebelum tool dieksekusi, sehingga Anda dapat memblokirnya dengan exit code 2. PostToolUse berjalan setelah eksekusi selesai, berguna untuk pemformatan, pengujian, atau pencatatan log. PreToolUse digunakan untuk pencegahan dan pengendalian. PostToolUse digunakan untuk validasi dan pembersihan. Keduanya menerima nama tool dan input sebagai JSON melalui stdin.
Bisakah hook Claude Code memblokir perintah berbahaya?
Ya. Hook PreToolUse dengan kode keluar 2 dapat memblokir eksekusi tool apa pun. Anda bisa melindungi file sensitif agar tidak ditulisi, memblokir perintah shell yang cocok dengan pola berbahaya seperti rm -rf atau git push main, dan mencegah akses ke database produksi. Pesan pemblokiran dikirim kembali ke Claude sebagai umpan balik, sehingga ia dapat menyesuaikan pendekatannya.
Apa saja event hook yang tersedia di Claude Code?
Claude Code menyediakan 15+ event: PreToolUse dan PostToolUse untuk eksekusi tool, Notification untuk peringatan, Stop untuk akhir sesi, SessionStart untuk inisialisasi, UserPromptSubmit untuk penyaringan input, PreCompact dan PostCompact untuk manajemen konteks, serta event yang lebih baru seperti ConfigChange, FileChanged, TaskCreated, dan PermissionDenied. Lihat tabel referensi lengkap di bagian event hook di atas.
Bagaimana hooks berbeda dari MCP tools dan Skills?
Hooks bersifat deterministik—hooks selalu berjalan pada event yang cocok, apa pun keputusan Claude. MCP tools memperluas kemampuan Claude (akses database, panggilan API), tetapi Claude yang memilih kapan menggunakannya. Skills adalah paket instruksi yang dapat digunakan kembali dan dipanggil melalui slash command. CLAUDE.md menyediakan panduan perilaku. Gunakan hooks ketika sesuatu harus terjadi setiap saat, dan gunakan MCP ketika Claude membutuhkan kemampuan baru.
Apakah hook Claude Code berfungsi dalam mode headless?
Ya, dengan beberapa catatan. Hook tetap berjalan normal dalam mode headless (claude -p), tetapi hook khusus desktop seperti notifikasi macOS memerlukan fallback. Yang penting, hook PreToolUse yang keluar dengan kode 2 dapat menjeda sesi headless untuk persetujuan manusia melalui --resume. Hal ini memungkinkan pipeline CI/CD human-in-the-loop di mana tindakan tertentu memerlukan persetujuan manual.
Berapa banyak hook yang terlalu banyak? Apakah hook memperlambat Claude Code?
Tidak ada batasan pasti, tetapi setiap hook sinkron menambah latensi. Hook SessionStart berjalan saat startup, jadi buatlah tetap cepat (di bawah 1 detik masing-masing). Hook PreToolUse dan PostToolUse dipicu pada setiap panggilan tool yang cocok, dan skrip yang berat di sini akan cepat menumpuk. Saya menyarankan untuk menjaga total hook di bawah 10-15, menggunakan field if untuk mempersempit cakupan, serta menambahkan nilai timeout untuk mencegah skrip yang berjalan tak terkendali.
Bisakah saya menggunakan hooks untuk memformat kode secara otomatis dengan Prettier atau Black?
Ya, ini adalah kasus penggunaan hook yang paling populer. Buat hook PostToolUse yang cocok dengan Write|Edit, ekstrak path file dari JSON stdin, lalu jalankan formatter yang sesuai berdasarkan ekstensi file. Lihat contoh nomor satu di bagian contoh produksi untuk konfigurasi lengkap yang siap disalin dan ditempel, yang menangani file TypeScript, JavaScript, dan Python.
Apakah hooks Claude Code aman? Apa saja risiko keamanannya?
Hooks berjalan dengan izin pengguna penuh Anda, tanpa sandbox. Hook yang berbahaya dapat membaca kunci SSH Anda, menghapus file, atau mencuri data. Gunakan hanya hooks dari sumber tepercaya, tinjau setiap .claude/settings.json yang dibagikan sebelum menerimanya ke dalam proyek Anda, dan gunakan .claude/settings.local.json untuk hooks pribadi yang tidak boleh dibagikan. Untuk pola keamanan AI yang lebih luas, lihat panduan guardrail LLM kami.