SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-15

Hook Claude Code: Peristiwa, Exit 2 dan Keselamatan

Ketahui lokasi hook Claude Code, peristiwa yang mencetuskannya, sebab exit code 2 membatalkan panggilan tool dan kos keselamatan apabila hook menjalankan kod.

Apakah hook Claude Code

Hook Claude Code ialah perintah shell yang dijalankan sendiri oleh Claude Code pada titik tetap dalam kitar hayatnya. Itulah perbezaan utama antara hook dengan fail peraturan. Arahan dalam CLAUDE.md ialah panduan, dan model menilainya bersama semua perkara lain dalam konteksnya. Hook ialah kod, dan ia dijalankan sama ada model bersetuju atau tidak. Jika agent 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 peristiwa. Apabila peristiwa itu berlaku, Claude Code menjalankan perintah anda dan menulis data peristiwa ke input standardnya (stdin) dalam format JSON (JavaScript object notation). Perintah anda membaca data itu, melaksanakan tugasnya dan mengembalikan status keluar. Exit 2 daripada hook PreToolUse membatalkan panggilan tool sebelum tool itu dijalankan, manakala apa-apa yang ditulis oleh skrip anda ke ralat standard (stderr) dikembalikan kepada model sebagai sebabnya.

Nama peristiwa dan nama medan di sini diambil daripada rujukan hooks Claude Code, yang disemak pada August 2026 terhadap release 2.1.232. Antara muka ini berubah dengan cepat, jadi 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: semua projek pada mesin anda, dan bukan pada mesin orang lain.
  • .claude/settings.json: satu projek, disimpan dalam repository, supaya semua orang yang mengklonkannya mendapat hook tersebut.
  • .claude/settings.local.json: satu projek, hanya pada mesin anda.
  • Tetapan dasar terurus: meliputi seluruh organisasi dan ditetapkan oleh pentadbir.
  • hooks/hooks.json dalam plugin, aktif selagi plugin tersebut didayakan.
  • Frontmatter skill atau subagent, aktif selagi komponen tersebut aktif.

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

Jalankan /hooks dalam sesi untuk menyenaraikan semua hook yang sedang didaftarkan, dikumpulkan mengikut peristiwa, bersama fail sumber dan matcher bagi setiap hook. Menu ini baca sahaja. Untuk mengubah hook, edit fail tetapan tersebut. File watcher biasanya mengesan perubahan itu tanpa memerlukan restart.

Peristiwa hook Claude Code yang tersedia

Release 2.1.232 menyenaraikan thirty one peristiwa, daripada SessionStart hingga SessionEnd, yang meliputi compaction, subagents, worktrees dan fail konfigurasi. Kerja pentadbiran pelayan biasanya menggunakan beberapa daripadanya.

  • PreToolUse: sebelum panggilan tool dilaksanakan. Peristiwa ini boleh menyekat pelaksanaan.
  • PostToolUse: selepas panggilan tool berjaya. PostToolUseFailure dicetuskan apabila panggilan itu gagal. Oleh itu, hook yang perlu melihat setiap hasil mesti menggunakan kedua-duanya.
  • PermissionRequest: apabila panggilan tool memerlukan keputusan permission, iaitu ketika prompt kelulusan akan dipaparkan.
  • UserPromptSubmit: apabila anda menghantar prompt, sebelum Claude memprosesnya. Apa-apa sahaja yang dicetak oleh hook ini ke stdout akan ditambahkan pada context model.
  • SessionStart dan SessionEnd: pada setiap penghujung session. SessionStart juga dicetuskan selepas compaction, dengan nilai matcher compact.
  • Stop: apabila Claude selesai memberikan respons. Peristiwa ini berlaku sekali bagi setiap turn, bukan sekali bagi setiap task yang selesai.

Setiap kumpulan mempunyai matcher yang menentukan kejadian yang akan menjalankan hook. Bagi peristiwa tool, ia menapis mengikut nama tool. Oleh itu, "Edit|Write" dicetuskan untuk pengeditan fail sahaja dan tidak untuk kejadian lain. Matcher adalah peka huruf besar dan kecil. Matcher kosong dicetuskan bagi setiap kejadian. Tool daripada server MCP (model context protocol) dinamakan mcp__<server>__<tool>. Oleh itu, matcher "mcp__github__.*" akan menangkap tool daripada satu server sahaja dan membiarkan tool daripada server lain.

Hook Stop mempunyai perangkap yang perlu diketahui sebelum anda menulisnya. Hook Stop yang menyekat akan menyebabkan model kembali bekerja, dan Claude Code akan mengatasi hook itu 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.

Perkara yang diterima oleh hook pada stdin

Apabila Claude akan menjalankan npm test, hook PreToolUse pada Bash membaca data ini daripada 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 menambah tool_name, tool_input dan tool_use_id. Peristiwa lain mempunyai medan masing-masing: UserPromptSubmit menerima teks prompt, manakala SessionStart menerima source bagi startup, resume, clear, compact atau fork.

jq ialah cara biasa untuk membaca data ini dalam skrip shell, tetapi 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 disampaikan 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 apa-apa tindakan selain menyekat atau tidak berbuat apa-apa, 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. Mencampurkan exit 2 dengan keputusan JSON pada stdout menghasilkan keputusan yang perlu anda cari secara berasingan.

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

Contoh 1: sekat arahan yang merosakkan sebelum arahan itu dijalankan

Simpan fail 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 anda mempercayainya kerana hook yang gagal memproses inputnya sendiri akan membenarkan operasi diteruskan:

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 arahan yang tidak berbahaya seperti ls -la dan anda sepatutnya tidak melihat sebarang output serta menerima kod keluar 0. Dalam satu sesi, panggilan yang disekat muncul dalam transkrip bersama mesej anda sebagai sebabnya, lalu model membaca mesej itu dan menyesuaikan tindakannya.

Satu ciri menjadikan langkah ini berbaloi: hook PreToolUse dicetuskan sebelum semakan permission mode, dalam setiap permission mode, maka deny tetap berkuat kuasa walaupun di bawah bypassPermissions. Inilah yang menjadikan hook berguna bersama Claude Code auto mode dan tetapan permissionnya, apabila prompt dikurangkan tetapi hook masih dicetuskan.

Jelaskan batasannya. Padanan corak pada rentetan arahan ialah perlindungan asas terhadap kecuaian agent, bukan sempadan terhadap agent yang mencari jalan lain, kerana arahan yang sama boleh ditulis dalam bentuk yang tidak pernah dilihat oleh grep anda. Peraturan yang tegas hendaklah diletakkan dalam sistem permission dan pada akaun yang digunakan untuk menjalankan proses.

Contoh 2: format dan lint selepas setiap penyuntingan

PostToolUse dengan padanan Edit|Write dijalankan selepas mana-mana alat penyuntingan fail. Simpan konfigurasi 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 menambahkan fungsi yang mempunyai inden yang salah pada 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.

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

Dua had matcher penting dalam keadaan ini. Edit|Write tidak melihat fail yang diubah oleh arahan 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 menggunakan git status --porcelain. Untuk liputan sekali bagi setiap giliran, letakkan imbasan itu dalam hook Stop.

Contoh 3: log setiap panggilan alat untuk audit

Matcher kosong pada PostToolUse dicetuskan untuk setiap alat. Menghantar rekod ke system journal dan bukannya ke fail dalam home directory memastikan rekod itu tidak boleh dicapai melalui 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 itu semula dengan journalctl -t claude-code -o cat | tail -n 5. Anda sepatutnya melihat satu baris JSON bagi setiap panggilan alat, dengan rekod terbaharu di bahagian akhir. Jika tiada apa-apa dipaparkan, hook itu 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 operasi berjaya, sedangkan perintah yang gagal biasanya lebih penting untuk diperiksa. Sebab penggunaan logger dan bukannya menambahkan rekod ke fail dalam home directory ialah pemilikan: hook dijalankan sebagai pengguna yang sama dengan shell ejen, jadi apa-apa yang boleh ditambah oleh pengguna itu juga boleh dipadamkan kandungannya oleh pengguna yang sama. Journal ditulis oleh systemd-journald menggunakan akaunnya sendiri.

Berapa lama 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 peristiwa memendekkan tempoh ini dengan ketara. Semua hook SessionEnd berkongsi bajet 1.5 saat, jadi pembersihan pada penghujung sesi mesti dilakukan dengan cepat. Walau bagaimanapun, menetapkan timeout yang lebih lama pada hook akan meningkatkan bajet dikongsi itu kepada tempoh 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 tugas yang mengambil masa dan tidak perlu ditunggu, seperti menghantar log ke lokasi lain, tetapkan "async": true supaya hook berjalan di latar belakang tanpa menangguhkan tool call.

Fail, rules, skill dan pelayan MCP

Empat perkara ini sering dikelirukan kerana semuanya mengubah tindakan agent. Hanya satu daripadanya berhenti menjadi cadangan.

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

Skill ialah folder yang mengandungi arahan dan skrip yang dimuatkan oleh model apabila model menilai bahawa skill itu berkaitan. Penilaian tersebut ialah tujuan skill, dan juga hadnya: model masih membuat keputusan. Anda dapat melihat kedua-dua aspek ini dalam skill seperti Ponytail, yang mengarahkan agent kepada perubahan paling kecil yang berfungsi, kerana skill itu membentuk cara keseluruhan tugasan dilaksanakan, dengan cara yang tidak dapat dilakukan oleh hook, dan hanya ketika model memilih untuk memuatkannya.

Pelayan MCP (model context protocol) memberikan model alat baharu untuk dipanggil. Pelayan ini meluaskan perkara yang boleh dicapai oleh agent. Namun, pelayan ini tidak menyebabkan agent menggunakan mana-mana alat, dan merupakan proses berasingan yang perlu anda kendalikan. Itu sendiri ialah tugas tersendiri: lihat menjalankan pelayan MCP pada VPS.

Hook ialah satu-satunya daripada empat perkara ini yang berjalan tanpa dipilih oleh model. Gunakan fail rules untuk menetapkan keutamaan, dan skill untuk prosedur yang perlu diikuti oleh model apabila prosedur itu terpakai. Gunakan hook untuk langkah yang mesti berlaku setiap kali, atau perkara yang tidak boleh berlaku sama sekali. Perbandingan yang lebih mendalam, termasuk keadaan skill lebih sesuai berbanding fail rules, terdapat dalam perbandingan skill, MCP dan fail rules.

Plugin ialah kaedah pembungkusan, bukannya mekanisme kelima. Plugin menggabungkan hook dan skill menjadi satu unit yang boleh dipasang. Dengan cara ini, pasukan boleh menggunakan guardrail yang sama pada setiap mesin: lihat cara plugin Claude Code berfungsi.

Keputusan keselamatan pada VPS dikongsi

Hook ialah kod yang dicetuskan oleh ejen dan dijalankan sebagai pengguna yang memulakan Claude Code. Hook mewarisi persekitaran dan kebenaran 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 pengklonan repositori dan memulakan sesi di dalamnya boleh mendaftarkan hook yang disertakan bersama repositori. Claude Code melindungi hook projek melalui dialog kepercayaan ruang kerja untuk folder tersebut. Ini bermakna penerimaan kepercayaan ialah saat anda memutuskan untuk menjalankannya. Baca blok hooks terlebih dahulu.

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

Hook boleh menulis ke dalam konteks model. Apa-apa 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 menaipnya. Anggap stdout itu sebagai input, bukan output.

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

Satu sifat berlaku dalam setiap konfigurasi. Hook PreToolUse dicetuskan sebelum semakan permission-mode dalam setiap mod kebenaran. Oleh itu, hook yang memulangkan deny akan menyekat alat walaupun di bawah bypassPermissions. Hook boleh mengetatkan perkara yang dibenarkan oleh peraturan kebenaran. Hook tidak boleh melonggarkannya.

Mengapa hook saya tidak dicetuskan?

Ikuti langkah ini mengikut urutan. Setiap langkah menyatakan gejala yang akan anda lihat.

  • Jalankan /hooks dan semak sama ada hook muncul di bawah peristiwa yang dijangkakan. Hook yang tiada dalam menu biasanya bermaksud fail tetapan mempunyai ralat sintaks JSON, kerana koma di hujung dan komen tidak dibenarkan, atau fail itu tiada 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 ialah 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 path itu tidak dapat diselesaikan. Gunakan ${CLAUDE_PROJECT_DIR} atau path mutlak. Jika skrip langsung tidak berjalan, kemungkinan besar skrip itu tidak boleh dilaksanakan.
  • Hook mencetak JSON yang sah tetapi tiada apa-apa berlaku. Hook dalam bentuk shell dijalankan melalui sh -c. Jika profil shell anda mencetak banner, banner itu ditambah di hadapan JSON anda. Output stdout tidak lagi bermula dengan {, jadi Claude Code membaca keseluruhan output sebagai teks biasa dan mengabaikan keputusan tersebut. Apabila keluar dengan kod 0, tiada apa-apa dilaporkan di mana-mana kecuali dalam log nyahpepijat. Bungkus sebarang echo dalam profil anda supaya ia hanya dijalankan 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 kandungan yang ditulisnya 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 pada setiap kejadian peristiwa tersebut tanpa mengira keputusan model. Gunakan arahan untuk menetapkan 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 matcher 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 permission-mode, jadi penolakan itu tetap berkuat kuasa walaupun dalam mod bypassPermissions. Padanan corak pada rentetan perintah ialah kawalan pencegahan, bukannya sempadan keselamatan, kerana perintah yang sama boleh ditulis dalam bentuk yang tidak dipadankan oleh corak. Oleh itu, sokong kawalan ini dengan peraturan permission 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 banner setiap kali shell dimulakan. Banner itu muncul pada stdout sebelum JSON anda. Oleh sebab output tersebut tidak lagi bermula dengan {, Claude Code menganggap keseluruhannya sebagai teks biasa dan mengabaikan keputusan itu. Jika proses keluar dengan kod 0, tiada apa-apa juga dilaporkan dalam transkrip. Lindungi sebarang echo dalam profil anda dengan semakan untuk shell interaktif. Kemudian, sahkan pembaikan tersebut dengan membaca log nyahpepijat daripada claude --debug-file /tmp/claude.log.

Adakah selamat untuk menjalankan hook Claude Code pada pelayan dikongsi?

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