SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-29

Claude Code Hooks: Acara, Lokasi dan Kod Keluar 2

Ketahui lokasi hook Claude Code, acara yang mencetuskannya, kesan status keluar 2 terhadap panggilan alat dan risiko keselamatan apabila kod berjalan tanpa persetujuan model.

Cara hook Claude Code berfungsi

Hook Claude Code ialah perintah shell yang dijalankan sendiri oleh Claude Code pada titik tertentu dalam kitar hayatnya. Itulah perbezaan utama antara hook dengan fail peraturan. Arahan dalam CLAUDE.md ialah nasihat, dan model menilainya berbanding semua kandungan lain dalam konteksnya. Hook ialah kod, dan kod itu dijalankan sama ada model bersetuju atau tidak. Jika agen anda terus melangkau formatter yang telah anda nyatakan dua kali, anda tidak memerlukan arahan yang lebih tegas. Anda memerlukan hook.

Mekanismenya ringkas. Anda mendaftarkan perintah dalam fail tetapan di bawah nama acara. Apabila acara itu dicetuskan, Claude Code menjalankan perintah anda dan menulis data acara ke input standard (stdin) sebagai JSON (notasi objek JavaScript). Perintah anda membaca data itu, melaksanakan tugasnya dan mengembalikan status keluar. Status keluar 2 daripada hook PreToolUse membatalkan panggilan alat sebelum alat itu dijalankan. Apa-apa sahaja yang ditulis oleh skrip anda ke ralat standard (stderr) akan dikembalikan kepada model sebagai sebab.

Nama acara dan nama medan di sini berasal daripada rujukan hooks Claude Code, yang disemak pada Ogos 2026 terhadap keluaran 2.1.232. Antara muka ini berubah dengan cepat. Semak rujukan untuk versi anda sendiri sebelum menyalin JSON daripada mana-mana catatan blog, termasuk catatan ini. Paparkan versi anda dengan claude --version.

Lokasi konfigurasi hook

Hook ialah blok JSON dalam fail tetapan. Enam lokasi boleh mengandungi hook, dan skop fail menentukan skop hook tersebut.

  • ~/.claude/settings.json: setiap projek pada mesin anda sahaja.
  • .claude/settings.json: satu projek, disimpan dalam repository, supaya semua orang yang mengklonkannya mendapat hook tersebut.
  • .claude/settings.local.json: satu projek, pada mesin anda sahaja.
  • Tetapan dasar terurus: meliputi seluruh organisasi dan ditetapkan oleh pentadbir.
  • hooks/hooks.json dalam plugin, aktif selagi plugin itu diaktifkan.
  • Frontmatter skill atau subagent, aktif selagi komponen tersebut aktif.

Entri hook daripada fail-fail ini digabungkan dan bukannya saling mengatasi. Fail tetapan projek menambahkan hooknya kepada hook dalam tetapan pengguna anda, bukannya menggantikannya. Oleh itu, satu peristiwa boleh mengandungi beberapa hook daripada beberapa fail. Menetapkan "disableAllHooks": true akan mematikannya, dengan satu pengecualian: hook daripada tetapan dasar terurus terus berjalan melainkan tetapan itu turut digunakan dalam tetapan terurus.

Jalankan /hooks dalam sesi untuk menyenaraikan setiap hook yang sedang didaftarkan, dikumpulkan mengikut peristiwa, bersama fail sumber dan matcher bagi setiap hook. Menu ini hanya untuk dibaca. Untuk mengubah hook, edit fail tetapan tersebut. File watcher biasanya mengesan perubahan itu tanpa perlu memulakan semula.

Peristiwa hook Claude Code yang tersedia

Release 2.1.232 menyenaraikan tiga puluh satu peristiwa, daripada SessionStart hingga SessionEnd, yang meliputi pemadatan, subagen, worktree dan fail konfigurasi. Kerja pentadbiran pelayan biasanya menggunakan beberapa daripadanya.

  • PreToolUse: sebelum panggilan alat dilaksanakan. Peristiwa ini boleh menyekat panggilan.
  • PostToolUse: selepas panggilan alat berjaya. PostToolUseFailure dicetuskan apabila panggilan gagal. Oleh itu, hook yang perlu melihat setiap hasil mesti menggunakan kedua-duanya.
  • PermissionRequest: apabila panggilan alat memerlukan keputusan kebenaran, iaitu ketika gesaan kelulusan akan dipaparkan.
  • UserPromptSubmit: apabila anda menghantar gesaan, sebelum Claude memprosesnya. Apa-apa yang dicetak oleh hook ini ke stdout akan ditambahkan pada konteks model.
  • SessionStart dan SessionEnd: pada setiap penghujung sesi. SessionStart juga dicetuskan selepas pemadatan, dengan nilai pemadan compact.
  • Stop: apabila Claude selesai memberikan respons. Peristiwa ini berlaku sekali bagi setiap giliran, bukan sekali bagi setiap tugas yang selesai.

Setiap kumpulan mengandungi matcher yang menentukan kejadian yang akan menjalankan hook. Pada peristiwa alat, medan ini menapis berdasarkan nama alat. Oleh itu, "Edit|Write" dicetuskan untuk pengeditan fail sahaja dan tidak untuk kejadian lain. Pemadan peka huruf besar dan kecil. Pemadan kosong dicetuskan pada setiap kejadian. Alat daripada pelayan MCP (model context protocol) dinamakan mcp__<server>__<tool>. Oleh itu, pemadan "mcp__github__.*" hanya menangkap alat daripada satu pelayan dan mengabaikan alat daripada pelayan lain.

Hook Stop mempunyai perangkap yang perlu diketahui sebelum anda menulisnya. Hook Stop yang menyekat akan mengarahkan model untuk bekerja semula, dan Claude Code akan mengatasi hook tersebut selepas lapan sekatan berturut-turut. Baca medan stop_hook_active daripada input hook dan keluar dengan kod 0 apabila nilainya true. Jika tidak, hook anda akan berulang sehingga mencapai had tersebut.

Input yang diterima oleh hook melalui stdin

Apabila Claude akan menjalankan npm test, hook PreToolUse pada Bash membaca data ini melalui stdin:

{
  "session_id": "abc123",
  "cwd": "/home/deploy/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

Setiap peristiwa mengandungi session_id, cwd, permission_mode, transcript_path dan hook_event_name. Peristiwa alat turut menambah tool_name, tool_input dan tool_use_id. Peristiwa lain mengandungi medan masing-masing: UserPromptSubmit mendapat teks prompt, manakala SessionStart mendapat source bagi startup, resume, clear, compact atau fork.

jq ialah cara biasa untuk membaca data ini dalam skrip shell, dan imej pelayan minimum tidak menyediakannya. Pasang dahulu dengan sudo apt install -y jq pada Ubuntu dan Debian.

Kesan status keluar terhadap panggilan alat yang sedang berjalan

Terdapat tiga hasil.

  • Exit 0 bermaksud hook anda tidak membantah. Pada PreToolUse, ini tidak sama dengan kelulusan, dan aliran kebenaran biasa masih berjalan. Pada UserPromptSubmit dan SessionStart, stdout ditambahkan pada konteks model.
  • Exit 2 menyekat tindakan bagi peristiwa yang boleh disekat, termasuk PreToolUse, dan stderr menjadi sebab yang dipaparkan kepada model. Bagi peristiwa yang tidak boleh disekat, seperti PostToolUse, sekatan itu diabaikan, tetapi stderr masih dihantar kepada model sebagai maklum balas.
  • Mana-mana kod keluar lain ialah ralat yang tidak menyekat. Tindakan diteruskan. Transkrip memaparkan notis ralat hook yang mengandungi baris pertama stderr selepas teks Failed with non-blocking status code:.

Untuk tindakan selain menyekat atau berdiam diri, gunakan exit 0 dan cetak objek JSON ke stdout. Hook PreToolUse membuat keputusan dengan permissionDecision:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Database drops go through a migration, not through the agent."
  }
}

"allow" melangkau gesaan interaktif, "deny" membatalkan panggilan dan menghantar sebabnya kepada model, manakala "ask" memaparkan gesaan seperti biasa. Pilih satu gaya bagi setiap hook. Jika exit 2 dicampurkan dengan keputusan JSON pada stdout, anda akan mendapat hasil yang perlu dirujuk secara berasingan.

Apabila beberapa hook sepadan dengan satu peristiwa, hook tersebut berjalan secara selari dan setiap satunya berjalan hingga selesai. deny daripada satu hook tidak menghentikan hook lain yang sepadan, jadi hook pengelogan masih menulis barisnya sementara hook guardrail menolak panggilan yang sama. Claude Code kemudiannya menggabungkan jawapan dan mengekalkan keputusan yang paling ketat mengikut urutan deny, defer, ask, allow.

Contoh 1: sekat perintah yang merosakkan sebelum dijalankan

Simpan ini sebagai .claude/hooks/block-destructive.sh dalam projek anda:

#!/bin/bash
# Deny a Bash tool call whose command matches a banned pattern.
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

for pattern in 'rm -rf /' 'mkfs' 'dd if=' 'DROP TABLE'; do
  if printf '%s' "$COMMAND" | grep -qiF -- "$pattern"; then
    echo "Blocked by policy: the command matches '$pattern'. A human runs this one." >&2
    exit 2
  fi
done

exit 0

Jadikan fail itu boleh dilaksanakan, kemudian daftarkannya pada PreToolUse dalam .claude/settings.json:

chmod +x .claude/hooks/block-destructive.sh
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-destructive.sh",
            "timeout": 10,
            "statusMessage": "Checking the command against policy"
          }
        ]
      }
    ]
  }
}

Uji skrip itu secara manual sebelum mempercayainya, kerana hook yang gagal apabila memproses inputnya sendiri akan membenarkan operasi secara lalai:

echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /var/lib/postgresql"}}' \
  | .claude/hooks/block-destructive.sh
echo $?

Anda sepatutnya melihat baris Blocked by policy: pada stderr dan kod keluar 2. Berikan perintah yang tidak berbahaya seperti ls -la dan anda sepatutnya tidak melihat sebarang output serta mendapat kod keluar 0. Dalam sesi, panggilan yang ditolak muncul dalam transkrip bersama mesej anda sebagai sebabnya, dan model membaca mesej itu lalu menyesuaikan tindakannya.

Satu ciri menjadikan langkah ini berbaloi: hook PreToolUse dicetuskan sebelum pemeriksaan mod kebenaran, dalam setiap mod kebenaran. Oleh itu, penolakan tetap berkuat kuasa walaupun di bawah bypassPermissions. Inilah yang menjadikan hook berguna bersama mod automatik Claude Code dan tetapan kebenarannya, apabila gesaan dikurangkan tetapi hook masih dicetuskan.

Jelaskan batasannya. Pemadanan corak pada rentetan perintah ialah perlindungan untuk menghalang ejen daripada bertindak cuai. Ia bukan sempadan terhadap ejen yang cuba mengelak kerana perintah yang sama boleh ditulis dalam bentuk yang tidak pernah dilihat oleh grep anda. Peraturan yang ketat perlu diletakkan dalam sistem kebenaran dan pada akaun yang digunakan oleh proses tersebut.

Contoh 2: format dan lint selepas setiap suntingan

PostToolUse dengan pemadan Edit|Write dijalankan selepas sebarang alat penyuntingan fail. Simpan ini sebagai .claude/hooks/after-edit.sh:

#!/bin/bash
# Format the edited file, then report lint failures back to the model.
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0

case "$FILE" in
  *.py)
    ruff format "$FILE" >/dev/null 2>&1
    if ! ruff check "$FILE" >&2; then
      exit 2
    fi
    ;;
  *.sh)
    if ! shellcheck "$FILE" >&2; then
      exit 2
    fi
    ;;
esac

exit 0
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/after-edit.sh",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

Minta Claude menambah fungsi dengan inden yang tidak betul ke dalam fail Python, kemudian buka fail itu. Fail tersebut akan diformatkan secara automatik. Ini mengesahkan bahawa hook telah dijalankan kerana hook yang berjaya tidak memaparkan apa-apa dalam perbualan.

Exit 2 di sini tidak membatalkan apa-apa. PostToolUse dijalankan selepas alat tersebut selesai, jadi suntingan tetap disimpan pada cakera. Kelebihan exit 2 ialah output ruff check dihantar kepada model sebagai maklum balas. Dengan itu, model membetulkan ralat yang baru diperkenalkannya dan bukannya meneruskan tugas. Inilah perbezaan antara kegagalan lint yang hanya dikesan semasa commit dengan kegagalan yang dibaiki oleh ejen dalam turn yang sama.

Dua had pemadan penting di sini. Edit|Write tidak melihat fail yang diubah melalui perintah shell, dan Claude cukup kerap menulis fail melalui Bash sehingga jurang ini benar-benar wujud. Untuk liputan bagi setiap panggilan, padankan Bash juga dan minta skrip menyenaraikan fail yang berubah dengan git status --porcelain. Untuk liputan sekali bagi setiap turn, letakkan imbasan itu dalam hook Stop.

Contoh 3: rekodkan setiap panggilan alat untuk audit

Pemadan kosong pada PostToolUse dicetuskan bagi setiap alat. Menghantar rekod ke jurnal sistem, bukannya ke fail dalam direktori rumah, memastikan rekod itu tidak boleh dicapai oleh shell ejen sendiri:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{time: now|todate, session: .session_id, cwd: .cwd, tool: .tool_name, input: .tool_input}' | logger -t claude-code -p local0.info"
          }
        ]
      }
    ]
  }
}

Baca rekod tersebut semula dengan journalctl -t claude-code -o cat | tail -n 5. Anda sepatutnya melihat satu baris JSON bagi setiap panggilan alat, dengan rekod terkini berada di baris terakhir. Jika tiada rekod dipaparkan, ini bermakna hook tidak dijalankan. Bahagian penyelesaian masalah di bawah menerangkan perkara ini.

Tambahkan blok yang sama di bawah PostToolUseFailure untuk merekod panggilan yang gagal, kerana PostToolUse hanya dicetuskan apabila berjaya dan arahan yang gagal biasanya merupakan panggilan yang paling penting untuk diperiksa. Sebab menggunakan logger, bukannya menambahkan rekod pada fail dalam direktori rumah, ialah pemilikan: hook dijalankan sebagai pengguna yang sama dengan shell ejen. Oleh itu, apa-apa yang boleh ditambah oleh pengguna tersebut juga boleh dipadamkan kandungannya oleh pengguna yang sama. Jurnal ditulis oleh systemd-journald menggunakan akaunnya sendiri.

Tempoh hook boleh berjalan

ChartDefault hook timeout in seconds, by hook type and event
The data behind this chart
[
  {
    "label": "command, http or mcp_tool hook",
    "default_timeout_seconds": 600
  },
  {
    "label": "agent hook",
    "default_timeout_seconds": 60
  },
  {
    "label": "prompt hook",
    "default_timeout_seconds": 30
  },
  {
    "label": "command hook on UserPromptSubmit",
    "default_timeout_seconds": 30
  },
  {
    "label": "command hook on MessageDisplay",
    "default_timeout_seconds": 10
  },
  {
    "label": "any hook on SessionEnd",
    "default_timeout_seconds": 1.5
  }
]

Secara lalai, command hook mendapat masa 600 saat, iaitu sepuluh minit. Sesetengah event memendekkan tempoh itu dengan ketara. Semua hook SessionEnd berkongsi peruntukan 1.5 saat, jadi pembersihan pada akhir sesi perlu dilakukan dengan cepat. Namun, menetapkan timeout yang lebih panjang pada hook akan meningkatkan peruntukan bersama itu kepada nilai yang sama, sehingga 60 saat.

Hook yang mencapai had masa akan dibatalkan dan tidak menghasilkan keputusan. Bagi PreToolUse guardrail, ini bermakna hook tersebut tidak menyekat operasi: tool call diteruskan ke aliran kebenaran biasa. Oleh itu, pastikan skrip guardrail ringkas. Untuk kerja yang mengambil masa dan tidak perlu ditunggu, seperti menghantar log ke lokasi lain, tetapkan "async": true supaya hook berjalan di latar belakang tanpa melambatkan tool call.

Cangkuk, fail peraturan, kemahiran dan pelayan MCP

Empat perkara ini sering dikelirukan kerana semuanya mengubah tindakan ejen. Hanya satu daripadanya tidak lagi sekadar cadangan.

Fail peraturan (CLAUDE.md atau fail di bawah .claude/rules/) ialah teks yang dimuatkan ke dalam konteks model. Fail ini membentuk tingkah laku, tetapi tidak menguatkuasakan apa-apa. Dalam perbualan yang panjang, diff yang besar dan permintaan pengguna yang baharu, satu baris daripadanya boleh terlepas daripada perhatian. Inilah mekanisme biasa yang menyebabkan ejen mengabaikan arahan yang anda tulis.

Kemahiran ialah folder yang mengandungi arahan dan skrip. Model memuatkannya apabila menganggap kemahiran itu berkaitan. Pertimbangan tersebut ialah tujuan kemahiran, dan juga hadnya: model masih membuat keputusan. Anda boleh melihat kedua-dua aspek ini dalam kemahiran seperti Ponytail, yang mengarahkan ejen supaya membuat perubahan paling kecil yang berfungsi, kerana kemahiran itu membentuk pendekatan terhadap keseluruhan tugasan dengan cara yang tidak dapat dilakukan oleh cangkuk, dan hanya apabila model memilih untuk memuatkannya.

Pelayan MCP (protokol konteks model) memberikan model alat baharu untuk dipanggil. Pelayan ini memperluas perkara yang boleh dicapai oleh ejen. Namun, pelayan ini tidak menyebabkan ejen menggunakan mana-mana alat, dan ia merupakan proses berasingan yang perlu anda kendalikan. Pengendalian itu sendiri ialah tugas khusus: lihat menjalankan pelayan MCP pada VPS.

Cangkuk ialah satu-satunya daripada empat perkara ini yang berjalan tanpa dipilih oleh model. Gunakan fail peraturan untuk menetapkan keutamaan, dan gunakan kemahiran untuk prosedur yang perlu diikuti oleh model apabila berkaitan. Gunakan cangkuk untuk langkah yang mesti berlaku setiap kali, atau untuk perkara yang tidak boleh berlaku sama sekali. Perbandingan yang lebih terperinci, termasuk keadaan kemahiran lebih sesuai daripada fail peraturan, terdapat dalam perbandingan kemahiran, MCP dan fail peraturan.

Plugin ialah kaedah pembungkusan, bukan mekanisme kelima. Plugin menggabungkan cangkuk dengan kemahiran menjadi satu unit yang boleh dipasang. Dengan cara ini, pasukan boleh menggunakan kawalan yang sama pada setiap mesin: lihat cara plugin Claude Code berfungsi.

Keputusan keselamatan pada VPS yang dikongsi

Hook ialah kod yang dicetuskan oleh ejen dan dijalankan sebagai pengguna yang memulakan Claude Code. Hook mewarisi persekitaran serta keizinan fail pengguna tersebut. Pada komputer riba, ini ialah persoalan aliran kerja. Pada VPS yang menjalankan ejen tanpa pengawasan, ini ialah persoalan keselamatan dengan empat aspek praktikal.

Hook dalam repositori ialah kod yang tidak anda tulis. .claude/settings.json disimpan dalam repositori, jadi tindakan mengklon repositori dan memulakan sesi di dalamnya boleh mendaftarkan hook yang disertakan bersama repositori. Claude Code meletakkan hook projek di belakang dialog kepercayaan ruang kerja untuk folder tersebut. Ini bermaksud menerima kepercayaan ialah saat anda memutuskan untuk menjalankan hook itu. Baca blok hooks terlebih dahulu.

Hook melihat keseluruhan input alat. Hook audit yang merekodkan tool_input menulis setiap argumen bagi setiap arahan ke dalam fail, termasuk sebarang token yang kebetulan terdapat pada baris arahan. Log itu kemudiannya memerlukan perlindungan yang sama seperti rahsia tersebut. Ini ialah sebahagian daripada masalah yang lebih luas, iaitu menjauhkan rahsia daripada capaian ejen AI.

Hook boleh menulis ke dalam konteks model. Apa sahaja yang dicetak oleh hook SessionStart atau UserPromptSubmit ke stdout akan ditambahkan pada perbualan. Hook yang menyalurkan teks daripada sumber luar, penjejak isu atau fail log memberikan teks tidak dipercayai kepada model seolah-olah anda sendiri yang menaipnya. Hook yang memajukan nota daripada sesi Claude Code lain pada VPS yang sama melakukan perkara yang sama. Output satu ejen tidak lebih layak dipercayai berbanding output penjejak isu. Anggap stdout itu sebagai input, bukan output.

Keistimewaan ialah kawalan sebenar. Jalankan ejen sebagai pengguna khusus tanpa keistimewaan, dengan hanya peraturan sudo yang diperlukan. Penafian PreToolUse wajar digunakan, dan sememangnya ia direka sebagai usaha terbaik: dokumentasi rujukan menyatakan perkara yang sama tentang penapis if serta mengarahkan anda menggunakan sistem keizinan apabila memerlukan penafian yang tegas. Peraturan keizinan dan akaun yang digunakan oleh proses ialah bahagian yang tetap berkesan apabila keadaan menjadi kritikal.

Satu ciri tetap berkesan dalam setiap konfigurasi. Hook PreToolUse dicetuskan sebelum semakan mod keizinan dalam setiap mod keizinan. Oleh itu, hook yang mengembalikan deny akan menyekat alat tersebut walaupun di bawah bypassPermissions. Hook boleh mengetatkan perkara yang dibenarkan oleh peraturan keizinan. Hook tidak boleh melonggarkannya.

Mengapa hook saya tidak berjalan?

Ikuti langkah ini mengikut urutan. Setiap langkah menerangkan simptom yang akan anda lihat.

  • Jalankan /hooks dan semak sama ada hook muncul di bawah peristiwa yang anda jangkakan. Hook yang tiada dalam menu biasanya bermaksud fail tetapan mempunyai ralat sintaks JSON kerana koma di hujung dan komen tidak dibenarkan, atau fail itu tidak berada di salah satu daripada enam lokasi di atas.
  • Bandingkan matcher dengan nama alat secara tepat. Matcher peka huruf besar dan kecil, jadi "bash" tidak pernah sepadan dengan alat Bash.
  • Jalankan skrip secara manual dengan input sampel, seperti dalam contoh 1 di atas. Kod keluar yang tidak dijangka menunjukkan terdapat pepijat dalam skrip anda. Claude Code melaporkannya sebagai ralat hook, bukan sebagai keputusan.
  • Notis yang berbunyi jq: command not found bermaksud jq tiada pada mesin tersebut. command not found untuk skrip anda sendiri bermaksud laluan itu tidak dapat diselesaikan, jadi gunakan ${CLAUDE_PROJECT_DIR} atau laluan mutlak. Jika skrip langsung tidak berjalan, kemungkinan besar skrip itu tidak mempunyai kebenaran untuk dilaksanakan.
  • Hook mencetak JSON yang sah tetapi tiada apa-apa berlaku. Hook dalam bentuk shell dijalankan melalui sh -c. Jika profil shell anda mencetak sepanduk, sepanduk itu ditambahkan di hadapan JSON anda. Output standard tidak lagi bermula dengan {, jadi Claude Code membaca keseluruhan output sebagai teks biasa dan mengabaikan keputusan tersebut. Dengan exit 0, tiada apa-apa dilaporkan di mana-mana kecuali dalam log nyahpepijat. Balut sebarang echo dalam profil anda supaya ia hanya berjalan dalam shell interaktif.
  • Jika masalah masih belum selesai, mulakan sesi dengan claude --debug-file /tmp/claude.log dan jalankan tail -f /tmp/claude.log dalam terminal kedua. Log nyahpepijat merekodkan hook yang sepadan, kod keluar yang dikembalikan oleh setiap hook, serta semua yang ditulis ke stdout dan stderr.

FAQ

Apakah perbezaan antara hook Claude Code dengan arahan CLAUDE.md?

Arahan CLAUDE.md ialah teks dalam konteks model. Oleh itu, arahan ini bersaing untuk mendapatkan perhatian bersama perbualan dan permintaan semasa, lalu model boleh menilainya berbanding kedua-duanya. Hook ialah perintah shell yang dijalankan oleh Claude Code pada titik tetap dalam kitar hayatnya. Oleh itu, hook dilaksanakan setiap kali peristiwa tersebut berlaku, tanpa mengira keputusan model. Gunakan arahan untuk pilihan atau keutamaan. Gunakan hook untuk langkah yang mesti sentiasa berlaku atau tindakan yang tidak boleh berlaku sama sekali.

Bagaimanakah saya menghentikan Claude Code daripada menjalankan perintah shell tertentu?

Daftarkan hook PreToolUse dengan pemadan Bash yang membaca perintah daripada .tool_input.command, menulis sebab ke stderr dan keluar dengan kod 2. Claude Code membatalkan panggilan tersebut dan memaparkan sebab anda kepada model. Proses ini berlaku sebelum semakan mod kebenaran, jadi penolakan tersebut tetap berkuat kuasa walaupun dalam mod bypassPermissions. Padanan corak pada rentetan perintah ialah kawalan pencegahan, bukan sempadan keselamatan, kerana perintah yang sama boleh ditulis dalam bentuk yang tidak dipadankan oleh corak. Oleh itu, sertakannya bersama peraturan kebenaran dan akaun tanpa keistimewaan.

Hook saya mencetak JSON yang sah, tetapi tiada apa-apa berlaku. Mengapa?

Punca yang paling biasa ialah profil shell anda. Hook tanpa medan args dijalankan melalui sh -c, dan sesetengah profil mencetak sepanduk pada setiap shell. Sepanduk itu masuk ke stdout sebelum JSON anda. Oleh sebab output itu tidak lagi bermula dengan {, Claude Code menganggap keseluruhan output sebagai teks biasa dan mengabaikan keputusan tersebut. Jika proses keluar dengan kod 0, tiada apa-apa juga dilaporkan dalam transkrip. Lindungi mana-mana echo dalam profil anda dengan ujian shell interaktif, kemudian sahkan pembetulan itu dengan membaca log nyahpepijat daripada claude --debug-file /tmp/claude.log.

Adakah selamat menjalankan hook Claude Code pada pelayan yang dikongsi?

Hook dijalankan sebagai pengguna yang memulakan Claude Code dan menggunakan keizinan fail pengguna tersebut. Oleh itu, hook boleh melakukan apa sahaja yang boleh dilakukan oleh akaun itu. Dua amalan merangkumi sebahagian besar risiko: jalankan ejen menggunakan akaun khusus tanpa keistimewaan dengan dasar sudo yang terhad, dan baca blok hooks dalam mana-mana repositori sebelum menerima dialog kepercayaan ruang kerja, kerana hook projek dihantar dalam .claude/settings.json. Tetapkan "disableAllHooks": true dalam fail tetapan anda jika anda tidak mahu mana-mana hook tersebut dijalankan.