תיעוד 51
אוטומציה של פעולות עם hooks
הרץ פקודות מעטפת באופן אוטומטי כש-Claude Code עורך קבצים, מסיים משימות, או זקוק לקלט. עצב קוד, שלח התראות, אמת פקודות, ואכוף כללי פרויקט.
Hooks הם פקודות מעטפת שהמשתמש מגדיר. Claude Code מריץ אותן בנקודות מסוימות במחזור החיים שלו, וזה נותן לך שליטה דטרמיניסטית: פעולות מסוימות תמיד מתרחשות, בלי להסתמך על כך שה-LLM יבחר להריץ אותן. השתמש ב-hooks כדי לאכוף כללי פרויקט, לבצע אוטומציה של משימות חוזרות, ולחבר את Claude Code לכלים הקיימים שלך.
להחלטות שדורשות שיקול דעת ולא כללים דטרמיניסטיים, אפשר גם להשתמש ב-hooks מבוססי prompt או ב-hooks מבוססי agent שמשתמשים במודל Claude כדי להעריך תנאים.
לדרכים נוספות להרחיב את Claude Code, ראה skills למתן הוראות נוספות ופקודות להרצה לקלוד, subagents להרצת משימות בהקשרים מבודדים, ו-plugins לאריזת הרחבות לשיתוף בין פרויקטים.
[!TIP]
המדריך הזה מכסה שימושים נפוצים ואיך להתחיל. לסכמות מלאות של אירועים, פורמטים של קלט ופלט ב-JSON, ותכונות מתקדמות כמו hooks אסינכרוניים ו-hooks לכלי MCP, ראה את הפניה ל-Hooks.
#הגדרת ה-hook הראשון
כדי ליצור hook, הוסף בלוק hooks לקובץ הגדרות. ההדרכה הזו יוצרת hook להתראת שולחן עבודה, כדי שתקבל התראה בכל פעם ש-Claude ממתין לקלט שלך, במקום לצפות בטרמינל.
1. הוספת ה-hook להגדרות
פתח את ~/.claude/settings.json והוסף hook מסוג Notification. אם הקובץ לא קיים, צור אותו. הדוגמה למטה משתמשת ב-osascript ל-macOS. ראה קבלת התראה כש-Claude זקוק לקלט לפקודות ל-Linux ול-Windows.
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}אם בקובץ ההגדרות כבר יש מפתח hooks, הוסף את Notification כאח למפתחות האירועים הקיימים, בלי להחליף את כל האובייקט. כל שם אירוע הוא מפתח בתוך אובייקט hooks היחיד:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
}
],
"Notification": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }]
}
]
}
}אפשר גם לבקש מ-Claude לכתוב את ה-hook עבורך, על ידי תיאור של מה שאתה רוצה ב-CLI.
2. אימות התצורה
הקלד /hooks בשורת הפקודה של Claude Code כדי לפתוח את דפדפן ה-hooks. ה-hook החדש מופיע ברשימה תחת Notification.
3. בדיקת ה-hook
לחץ Esc כדי לחזור ל-CLI. לחץ Shift+Tab עד ששורת המצב מציגה ⏸ manual mode on, בקש מ-Claude לעשות משהו שדורש הרשאה, ואז עבור למקום אחר מחוץ לטרמינל. אמורה להגיע התראת שולחן עבודה.
#מה אפשר לבצע באוטומציה
Hooks מאפשרים להריץ קוד בנקודות מפתח במחזור החיים של Claude Code: לעצב קבצים אחרי עריכות, לחסום פקודות לפני שהן רצות, לשלוח התראות כש-Claude זקוק לקלט, להזריק הקשר בתחילת סשן, ועוד. לרשימה המלאה של אירועי hook, ראה את הפניה ל-Hooks.
כל דוגמה כוללת בלוק תצורה מוכן לשימוש, שמוסיפים לקובץ הגדרות.
לדוגמה בפרודקשן של hooks שמריצים סקירת מודל נפרדת ומחזירים ממצאים לסשן, ראה איך התוסף security-guidance משתלב עם Claude Code.
#קבלת התראה כש-Claude זקוק לקלט
קבל התראת שולחן עבודה בכל פעם ש-Claude מסיים לעבוד וזקוק לקלט שלך, כדי שאפשר לעבור למשימות אחרות בלי לבדוק את הטרמינל.
ה-hook הזה משתמש באירוע Notification, ש-Claude Code מפעיל כש-Claude ממתין לקלט או להרשאה. ראה מתי כל סוג התראה מופעל לתזמון המדויק.
כל לשונית למטה משתמשת בפקודת ההתראה המקורית של הפלטפורמה. הוסף את זה ל-~/.claude/settings.json:
macOS
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}אם לא מופיעה התראה
osascript מנתב התראות דרך אפליקציית Script Editor המובנית. אם ל-Script Editor אין הרשאת התראות, הפקודה נכשלת בשקט, ו-macOS לא יבקש ממך לאשר אותה.
הרץ את זה ב-Terminal פעם אחת כדי ש-Script Editor יופיע בהגדרות ההתראות:
osascript -e 'display notification "test"'עדיין לא יופיע כלום. פתח את System Settings > Notifications, מצא את Script Editor ברשימה, והפעל את Allow Notifications. הרץ את הפקודה שוב כדי לוודא שהתראת הבדיקה מופיעה.
Linux
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}אם לא מופיעה התראה
notify-send צריך daemon להתראות שולחן עבודה, שאין בשרתים בלי ממשק גרפי, בסשני SSH, וברוב הקונטיינרים. בדוק את הפקודה ישירות קודם:
notify-send 'Claude Code' 'test'אם הפקודה לא נמצאה, התקן את החבילה libnotify-bin ב-Debian וב-Ubuntu, או את המקבילה בהפצה שלך.
Windows (PowerShell)
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
}
]
}
]
}
}אם לא מופיעה תיבת דו-שיח
הפקודה הזו פותחת תיבת דו-שיח ולא התראה בפינת המסך, כך שהתיבה יכולה להיפתח מאחורי חלון הטרמינל. בדוק את הפקודה ישירות ב-PowerShell קודם.
אם אתה מריץ את Claude Code בתוך WSL, powershell.exe חייב להיות זמין ב-PATH דרך Windows interop.
ה-matcher הריק מופעל על כל סוגי ההתראות. כדי להפעיל רק על אירועים מסוימים, הגדר אותו לאחד מהערכים האלה:
| Matcher | מתי מופעל |
|---|---|
permission_prompt | Claude צריך שתאשר שימוש בכלי או בקשת רשת של פקודה בארגז חול, וההנחיה המתינה כשש שניות |
idle_prompt | Claude סיים להגיב לפני כ-60 שניות, ומאז לא הקלדת |
auth_success | האימות הושלם |
elicitation_dialog | שרת MCP פותח טופס elicitation, ולא הקלדת במשך כשש שניות |
elicitation_url_dialog | שרת MCP מבקש ממך לפתוח כתובת בדפדפן, ולא הקלדת במשך כשש שניות |
elicitation_complete | שרת MCP מדווח ש-elicitation במצב URL הושלם |
elicitation_response | תשובת elicitation של MCP נשלחת בחזרה לשרת |
agent_needs_input | סשן ברקע מתחיל להמתין לקלט שלך בזמן ש-תצוגת agent פתוחה. מופעל גם כשסשן טרמינל מציג לך שאלת הגדרת טרמינל של חבר צוות ב-agent team או הודעה של מצב אוטומטי על חיובים של בקשת מסווג, ולא הקלדת במשך כשש שניות |
agent_completed | סשן ברקע מסתיים או נכשל. מופעל רק בזמן ש-תצוגת agent פתוחה |
quota_auto_resume_fired | Claude Code ממשיך את המשימה שלך אחרי שמגבלת שימוש ב-claude.ai עצרה אותה: באיפוס, או מוקדם יותר כשמשהו שאתה עושה ב-Claude Code במהלך ההמתנה, כמו הוספת קרדיטים לשימוש, שדרוג התוכנית, או החלפת מודלים, הופך את השימוש לזמין שוב, עם החריג של הגדרת המודל |
quota_auto_resume_stale | איפוס של מגבלת שימוש ב-claude.ai התרחש בזמן שהמחשב ישן יותר מכ-30 דקות. Claude Code ממתין שתלחץ Enter במקום להמשיך. אחרי שינה קצרה יותר הוא ממשיך ומפעיל את quota_auto_resume_fired |
quota_auto_resume_disabled | Claude Code מסיים את ההמתנה למגבלת שימוש ב-claude.ai בלי להמשיך את המשימה: autoContinueAtUsageLimit כבוי, או שהאיפוס זז ליותר מ-24 שעות קדימה במהלך המתנה ש-Claude Code התחיל בעצמו, המשימה שהמשיכה המשיכה לפגוע במגבלה, או שההמשך נחסם לפני שהגיע למודל. לא מופעל כשלוחצים Esc או Ctrl+C, או כשבוחרים Don't continue automatically |
plugin_notification | mod מעלה התראה עם $.ui.notify. ה-title של ה-hook הוא שם ה-mod, אלא אם ה-mod הגדיר אחד |
Claude Code מתזמן את permission_prompt אחרת בטרמינל וב-Claude Desktop, בהרחבת VS Code, ובמארחים אחרים שעונים לבקשות הרשאה דרך Agent SDK. ראה מתי כל סוג התראה מופעל לשני התזמונים.
ה-matchers quota_auto_resume_fired, quota_auto_resume_stale ו-quota_auto_resume_disabled דורשים Claude Code גרסה v2.1.234 או חדשה יותר.
בסשני טרמינל, permission_prompt לבקשת רשת של פקודה בארגז חול דורש Claude Code גרסה v2.1.246 או חדשה יותר.
agent_needs_input לשאלת הגדרת טרמינל של חבר צוות דורש Claude Code גרסה v2.1.248 או חדשה יותר.
הקלד /hooks בשורת הפקודה של Claude Code וודא שה-hook מופיע תחת Notification.
#עיצוב קוד אוטומטי אחרי עריכות
הרץ אוטומטית את Prettier על כל קובץ ש-Claude עורך, כדי שהעיצוב יישאר עקבי בלי התערבות ידנית.
ה-hook הזה משתמש באירוע PostToolUse עם matcher של Edit|Write, כך שהוא רץ רק אחרי כלי עריכת קבצים. הפקודה מחלצת את נתיב הקובץ שנערך עם jq ומעבירה אותו ל-Prettier. הוסף את זה ל-.claude/settings.json בשורש הפרויקט:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}כדי לבדוק את ה-hook, בקש מ-Claude להוסיף שורה עם מחרוזות במירכאות בודדות לקובץ JavaScript, ואז פתח את הקובץ: עם הגדרות ברירת המחדל של Prettier, ה-hook משכתב אותן למירכאות כפולות.
כשה-hook מצליח, Claude Code לא מציג כלום בשיחה. כדי לוודא שה-hook רץ, בדוק שהקובץ שנערך עוצב מחדש, או ראה בדיקה מה hook עשה.
כדי לעצב מחדש קובץ מסוים בכל שינוי שלו, כולל כשפקודת Bash משכתבת אותו, השתמש ב-hook מסוג FileChanged במקום.
[!NOTE]
דוגמאות ה-Bash בדף הזה משתמשות ב-
jqלניתוח JSON. התקן אותו עםbrew install jqב-macOS,apt-get install jqב-Debian וב-Ubuntu, או ראה הורדותjq.
#חסימת עריכות לקבצים מוגנים
מנע מ-Claude לשנות קבצים רגישים כמו .env, package-lock.json, או כל דבר ב-.git/. Claude מקבל משוב שמסביר למה העריכה נחסמה, כדי שיוכל להתאים את הגישה שלו.
הדוגמה הזו משתמשת בקובץ סקריפט נפרד שה-hook קורא לו. הסקריפט בודק את נתיב קובץ היעד מול רשימת תבניות מוגנות ויוצא עם קוד 2 כדי לחסום את העריכה.
1. יצירת סקריפט ה-hook
שמור את זה ב-.claude/hooks/protect-files.sh:
#!/bin/bash
# protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# Normalize Windows backslash separators so the patterns below match
FILE_PATH="${FILE_PATH//\\//}"
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 02. הפיכת הסקריפט לקובץ בר הרצה ב-macOS וב-Linux
סקריפטי hook חייבים להיות ברי הרצה כדי ש-Claude Code יריץ אותם:
chmod +x .claude/hooks/protect-files.sh3. רישום ה-hook
הוסף hook מסוג PreToolUse ל-.claude/settings.json שמריץ את הסקריפט לפני כל קריאה לכלי Edit או Write:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}4. בדיקת ה-hook
בקש מ-Claude להוסיף הערה לקובץ .env שלך. Claude Code חוסם את העריכה לפני שהיא רצה, ומעביר את הודעת Blocked: של הסקריפט ל-Claude כמשוב.
#הזרקה מחדש של הקשר אחרי compaction
כשחלון ההקשר של Claude מתמלא, compaction מסכם את השיחה כדי לפנות מקום. זה עלול לאבד פרטים חשובים. השתמש ב-hook מסוג SessionStart עם matcher של compact כדי להזריק מחדש הקשר קריטי אחרי כל compaction.
Claude Code מוסיף להקשר של Claude את הטקסט הרגיל שהפקודה שלך כותבת ל-stdout. הדוגמה הזו מזכירה ל-Claude מוסכמות פרויקט ועבודה אחרונה. הוסף את זה ל-.claude/settings.json בשורש הפרויקט:
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
}
]
}
]
}
}אפשר להחליף את echo בכל פקודה שמייצרת פלט דינמי, כמו git log --oneline -5 כדי להציג קומיטים אחרונים. להזרקת הקשר בכל תחילת סשן, שקול להשתמש ב-CLAUDE.md במקום. למשתני סביבה, ראה CLAUDE_ENV_FILE בחומר העיון.
#ביקורת על שינויי תצורה
עקוב אחרי שינויים בקובצי הגדרות או skills במהלך סשן. האירוע ConfigChange מופעל כשתהליך חיצוני או עורך משנה קובץ תצורה, כדי שאפשר לתעד שינויים לצורכי תאימות או לחסום שינויים לא מורשים.
הדוגמה הזו מוסיפה כל שינוי ליומן ביקורת. הוסף את זה ל-~/.claude/settings.json:
{
"hooks": {
"ConfigChange": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
}
]
}
]
}
}ה-matcher מסנן לפי סוג תצורה: user_settings, project_settings, local_settings, policy_settings, או skills. כדי לחסום שינוי מלהיכנס לתוקף, צא עם קוד 2 או החזר {"decision": "block"}. ראה את הפניה ל-ConfigChange לסכמת הקלט המלאה.
כדי לוודא שה-hook מתעד שינויים, ערוך קובץ הגדרות בעורך אחר בזמן שסשן רץ, ואז פתח את ~/claude-config-audit.log: ה-hook מוסיף שורת JSON אחת לכל שינוי, עם חותמת הזמן, המקור, ונתיב הקובץ.
#טעינה מחדש של הסביבה כשתיקייה או קבצים משתנים
חלק מהפרויקטים מגדירים משתני סביבה שונים לפי התיקייה שבה נמצאים. כלים כמו direnv עושים זאת אוטומטית במעטפת, אבל כלי Bash של Claude לא קולט את השינויים האלה בעצמו.
שילוב של hook מסוג SessionStart עם hook מסוג CwdChanged פותר את זה. SessionStart טוען את המשתנים של התיקייה שממנה מפעילים, ו-CwdChanged טוען אותם מחדש בכל פעם ש-Claude משנה תיקייה. שניהם כותבים אל CLAUDE_ENV_FILE, ש-Claude Code מריץ כתחילית סקריפט לפני כל פקודת Bash. הוסיפו את זה אל ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
],
"CwdChanged": [
{
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
]
}
}הריצו direnv allow פעם אחת בכל תיקייה שיש בה .envrc כדי ש-direnv יורשה לטעון אותו. אם משתמשים ב-devbox או ב-nix במקום direnv, אותו דפוס עובד עם devbox shellenv או devbox global shellenv במקום direnv export bash.
כדי להגיב לקבצים מסוימים במקום לכל שינוי תיקייה, השתמשו ב-FileChanged עם matcher שמפרט את שמות הקבצים למעקב, מופרדים ב-|. כשבונים את רשימת המעקב, Claude Code מפצל את הערך הזה לשמות קבצים מילוליים ולא מעריך אותו כביטוי רגולרי. ראו FileChanged כדי לראות איך אותו ערך גם מסנן אילו קבוצות hook רצות כשקובץ משתנה. הדוגמה הזו עוקבת אחרי .envrc ו-.env בתיקיית העבודה:
{
"hooks": {
"FileChanged": [
{
"matcher": ".envrc|.env",
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
]
}
}ראו את ערכי העזר של CwdChanged ושל FileChanged לסכמות קלט, לפלט watchPaths, ולפרטים על CLAUDE_ENV_FILE.
#אישור אוטומטי של בקשות הרשאה מסוימות
דלגו על תיבת האישור לקריאות כלים שתמיד מאשרים. הדוגמה הזו מאשרת אוטומטית את ExitPlanMode, הכלי ש-Claude קורא לו כשהוא מסיים להציג תוכנית ומבקש להמשיך, כך שלא מתבקשים אישור בכל פעם שתוכנית מוכנה.
בניגוד לדוגמאות קוד היציאה שלמעלה, אישור אוטומטי דורש שה-hook יכתוב החלטת JSON אל stdout. Claude Code מריץ hooks מסוג PermissionRequest כשהוא עומד לבקש הרשאה, ואם ה-hook מחזיר "behavior": "allow", Claude Code עונה לבקשה בשמכם.
ה-matcher מגביל את ה-hook ל-ExitPlanMode בלבד, כך ששום בקשה אחרת לא מושפעת. הוסיפו את זה אל ~/.claude/settings.json:
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
}
]
}
]
}
}כשה-hook מאשר, Claude Code יוצא ממצב plan ומשחזר את מצב ההרשאות שהיה פעיל לפני שנכנסתם למצב plan. התמליל מציג "Allowed by PermissionRequest hook" במקום שבו תיבת הדו-שיח הייתה מופיעה. נתיב ה-hook תמיד שומר את השיחה הנוכחית: הוא לא יכול לנקות את ההקשר ולהתחיל סשן מימוש חדש כמו שתיבת הדו-שיח יכולה.
כדי להגדיר מצב הרשאות מסוים במקום זאת, הפלט של ה-hook יכול לכלול מערך updatedPermissions עם רשומת setMode. ערך mode הוא כל מצב הרשאות כמו default, acceptEdits, או bypassPermissions, ו-destination: "session" מחיל אותו על הסשן הנוכחי בלבד.
[!NOTE]
bypassPermissionsחל רק אם התחלתם את הסשן כשמצב העקיפה כבר זמין:--dangerously-skip-permissions,--permission-mode bypassPermissions,--allow-dangerously-skip-permissions, אוpermissions.defaultMode: "bypassPermissions"בהגדרות משתמש,--settings, או הגדרות מנוהלות. הוא לא חל אם מצב העקיפה מושבת על ידיpermissions.disableBypassPermissionsMode, או אם התחלתם את הסשן במצב מוגבל.Claude Code אף פעם לא שומר אותו כ-
defaultMode.
כדי להעביר את הסשן ל-acceptEdits, ה-hook כותב את ה-JSON הזה אל stdout:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow",
"updatedPermissions": [
{ "type": "setMode", "mode": "acceptEdits", "destination": "session" }
]
}
}
}השאירו את ה-matcher צר ככל האפשר. התאמה על .* או השארת ה-matcher ריק תאשר אוטומטית כל בקשת הרשאה לכלי, כולל כתיבת קבצים ופקודות מעטפת. ראו את העזר של PermissionRequest לקבוצה המלאה של שדות ההחלטה.
#איך hooks עובדים
Claude Code מפעיל אירועי hook בנקודות מסוימות במחזור החיים שלו. כשאירוע מופעל, Claude Code מריץ את ה-hooks התואמים במקביל. ראו שדות מטפל hook לאופן הטיפול במטפלים כפולים. הטבלה למטה מציגה כל אירוע ומתי הוא מופעל:
| אירוע | מתי הוא מופעל |
|---|---|
SessionStart | כשסשן מתחיל או מתחדש |
Setup | כשמתחילים את Claude Code עם --init-only, או עם --init או --maintenance במצב -p. להכנה חד-פעמית ב-CI או בסקריפטים |
UserPromptSubmit | כשפרומפט נשלח, לפני ש-Claude מעבד אותו. מופעל גם בתורות ש-Claude Code מתחיל בעצמו |
UserPromptExpansion | כשפקודה שהמשתמש הקליד מתרחבת לפרומפט, לפני שהיא מגיעה ל-Claude. יכול לחסום את ההרחבה |
PreToolUse | לפני שקריאת כלי מתבצעת. יכול לחסום אותה |
PermissionRequest | כשקריאת כלי צריכה החלטת הרשאה |
PermissionDenied | כשמצב auto דוחה קריאת כלי, כולל דחיות בלי הכרעת מסווג. השתמשו ב-JSON hookSpecificOutput.retry: true כדי לומר למודל שהוא רשאי לנסות שוב את קריאת הכלי שנדחתה. Claude Code מתעלם מ-retry כשהמסווג לא הפיק הכרעה |
PostToolUse | אחרי שקריאת כלי מצליחה |
PostToolUseFailure | אחרי שקריאת כלי נכשלת |
PostToolBatch | אחרי שקבוצה מלאה של קריאות כלים מקבילות מסתיימת, לפני הקריאה הבאה למודל |
Notification | כש-Claude Code שולח התראה |
MessageDisplay | בזמן שטקסט הודעת העוזר מוצג |
SubagentStart | כש-subagent נוצר |
SubagentStop | כש-subagent מסיים |
TaskCreated | כשמשימה נוצרת דרך TaskCreate |
TaskCompleted | כשמשימה מסומנת כהושלמה |
Stop | כש-Claude מסיים להגיב |
StopFailure | כשהתור נגמר בגלל שגיאת API |
TeammateIdle | כשחבר בצוות סוכנים עומד לעבור למצב idle |
InstructionsLoaded | כשקובץ CLAUDE.md או .claude/rules/*.md נטען להקשר. מופעל בתחילת סשן וכשקבצים נטענים בטעינה עצלה במהלך סשן |
ConfigChange | כשקובץ הגדרות משתנה במהלך סשן |
CwdChanged | כשתיקיית העבודה משתנה, למשל כש-Claude מריץ פקודת cd. שימושי לניהול סביבה תגובתי עם כלים כמו direnv |
DirectoryAdded | כשתיקיית עבודה מתווספת באמצע סשן דרך /add-dir או בקשת הבקרה register_repo_root של ה-SDK |
FileChanged | כשקובץ במעקב משתנה בדיסק. השדה matcher מציין אילו שמות קבצים לעקוב אחריהם |
WorktreeCreate | כש-worktree נוצר דרך --worktree, isolation: "worktree", או לסשן ברקע. מחליף את התנהגות ברירת המחדל של git |
WorktreeRemove | כש-worktree ש-hook מסוג WorktreeCreate יצר מוסר |
PreCompact | לפני דחיסת הקשר |
PostCompact | אחרי שדחיסת ההקשר מסתיימת |
PreModelSwitch | לפני ש-Claude Code מחיל החלפת מודל שאתם או לקוח ביקשתם. יכול לחסום את ההחלפה |
PostModelSwitch | אחרי שמודל הסשן משתנה, כולל שינויים ש-Claude Code עושה בעצמו, כמו שחזור המודל כשמחדשים סשן |
Elicitation | כששרת MCP מבקש קלט משתמש במהלך קריאת כלי |
ElicitationResult | אחרי שמשתמש מגיב ל-elicitation של MCP, לפני שהתשובה נשלחת חזרה לשרת |
SessionEnd | כשסשן מסתיים |
לכל hook יש type שקובע איך הוא רץ. רוב ה-hooks משתמשים ב-"type": "command", שמריץ פקודת מעטפת. ארבעה סוגים נוספים זמינים:
"type": "http": שליחת נתוני האירוע ב-POST אל כתובת URL. ראו hooks מסוג HTTP."type": "mcp_tool": קריאה לכלי בשרת MCP מוגדר. ראו hooks של כלי MCP."type": "prompt": הערכה של LLM בתור יחיד. ראו hooks מבוססי prompt."type": "agent": אימות מרובה תורות עם גישה לכלים. hooks מסוג agent הם ניסיוניים ועשויים להשתנות. ראו hooks מבוססי agent.
#שילוב תוצאות מכמה hooks
כשכמה hooks תואמים לאותו אירוע, הפקודה של כל hook רצה עד הסוף לפני ש-Claude Code ממזג את התוצאות. hook אחד שמחזיר deny לא עוצר hooks אחים מלהתבצע. אל תסתמכו על deny של hook אחד כדי לדכא תופעות לוואי ב-hook אחר.
אחרי שכל ה-hooks התואמים מסתיימים, Claude Code משלב את הפלטים שלהם. להחלטות הרשאה של PreToolUse, התשובה המגבילה ביותר חלה, בסדר deny, defer, ask, allow. טקסט מ-additionalContext נשמר מכל hook ומועבר ל-Claude יחד.
הדוגמה למטה רושמת שני hooks מסוג PreToolUse על Bash. הראשון מוסיף כל פקודה לקובץ יומן ויוצא עם 0. השני מריץ סקריפט שיוצא עם 2 כדי לדחות כשהפקודה מכילה rm -rf:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r .tool_input.command >> ~/.claude/bash.log"
},
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm-rf.sh"
}
]
}
]
}
}כש-Claude מנסה להריץ rm -rf /tmp/build, שני ה-hooks מתבצעים במקביל. ה-hook של הרישום כותב את הפקודה אל ~/.claude/bash.log ויוצא עם 0, שמדווח שאין החלטה. ה-hook של גדר הבטיחות יוצא עם 2, שדוחה את קריאת הכלי. ה-deny גובר, כך ש-Claude Code חוסם את הפקודה ומראה ל-Claude את ה-stderr של גדר הבטיחות. רשומת היומן עדיין נכתבת כי ה-hook של הרישום כבר רץ.
#קריאת קלט והחזרת פלט
הוקים מתקשרים עם Claude Code דרך stdin, stdout, stderr וקודי יציאה. כשאירוע מופעל, Claude Code מעביר נתונים ספציפיים לאירוע כ-JSON אל stdin של הסקריפט. הסקריפט קורא את הנתונים, מבצע את העבודה, ומספר ל-Claude Code מה לעשות בהמשך באמצעות קוד היציאה.
#קלט של הוק
כל אירוע כולל שדות משותפים כמו session_id, מזהה ייחודי לסשן, ו-cwd, ספריית העבודה בזמן שהאירוע הופעל, אבל כל סוג אירוע מוסיף נתונים שונים. כש-Claude מריץ פקודת Bash, הוק PreToolUse מקבל את השדות האלה ב-stdin:
hook_event_name: האירוע שהפעיל את ההוקtool_name: הכלי ש-Claude עומד להשתמש בוtool_input: הארגומנטים ש-Claude העביר לכלי. עבור Bash, השדהcommandמחזיק את פקודת המעטפת.
לדוגמה, קלט ההוק לפקודה npm test נראה כך:
{
"session_id": "abc123",
"cwd": "/Users/sarah/myproject",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
}
}הסקריפט יכול לפרסר את ה-JSON ולפעול לפי כל אחד מהשדות האלה. הוקים מסוג UserPromptSubmit מקבלים במקום זאת את טקסט prompt, הוקים מסוג SessionStart מקבלים source של startup, resume, clear, compact או fork, וכן הלאה. ראו Common input fields במדריך העזר לשדות המשותפים, ואת הסעיף של כל אירוע לסכמות הספציפיות לאירוע.
#פלט של הוק
הסקריפט מספר ל-Claude Code מה לעשות בהמשך על ידי כתיבה ל-stdout או ל-stderr ויציאה עם קוד מסוים. הוק PreToolUse הבא חוסם פקודה:
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q "drop table"; then
echo "Blocked: dropping tables is not allowed" >&2 # stderr becomes Claude's feedback
exit 2 # exit 2 = block the action
fi
exit 0 # exit 0 = no decision; the normal permission flow appliesעם קוד יציאה שאינו 0 ואינו 2 ובלי פלט JSON תקין, הפעולה ממשיכה ברוב האירועים, אלא אם ההוק הוא אחד שכשל שלו חוסם את הפעולה. הוק עם onFailure שמוגדר ל-"block" הוא דוגמה אחת. צאו עם 0 כדי לדווח שאין התנגדות, או צאו עם 2 כדי לחסום את הפעולה:
- יציאה 0: אם יוצאים עם 0 מהוק
PreToolUse, קריאת הכלי עדיין עוברת את זרימת ההרשאות הרגילה, כי יציאה 0 לא מאשרת אותה. עבור הוקים מסוגUserPromptSubmit,UserPromptExpansion,SessionStartו-PostModelSwitch, Claude Code מוסיף את stdout שהוא מתייחס אליו כטקסט רגיל להקשר של Claude. - יציאה 2: כתבו סיבה ל-stderr. בהתאם לאירוע, Claude מקבל אותה כמשוב כדי שיוכל להתאים, המשתמש רואה אותה, או שלא מופיעה הודעה, כמו ב-
ConfigChangeוב-Elicitation. חלק מהאירועים אי אפשר לחסום: עבורSessionStartואחרים, יציאה 2 מציגה את stderr למשתמש והביצוע ממשיך. ראו exit code 2 behavior per event לרשימה המלאה. - כל קוד יציאה אחר: לחריגים לפי אירוע, כמו
WorktreeCreateשנכשל בכל יציאה שאינה אפס, ראו Exit code output. באירועים אחרים, אלא אם ההוק הוא אחד שכשל שלו חוסם את הפעולה, מצאו את המקרה לפי מה שההוק הדפיס ל-stdout:- אובייקט שפורסר ועובר אימות סכמה: Claude Code מתעלם מקוד היציאה, ה-JSON לבדו קובע את התוצאה, וההוק לא מדווח כשגיאה.
- אובייקט שפורסר ונכשל באימות סכמה, או stdout ש-Claude Code מנסה לפרסר כ-JSON אבל אינו JSON תקין: הפעולה ממשיכה כשגיאה לא חוסמת. בדקו את ההודעה
<hook name> hook errorלהודעת האימות או הפרסור. - stdout ש-Claude Code מתייחס אליו כטקסט רגיל, או stdout ריק: הפעולה ממשיכה כשגיאה לא חוסמת. התמליל מציג הודעת
<hook name> hook error, ואז את השורה הראשונה של stderr עם הקידומתFailed with non-blocking status code:. כדי ללכוד את stderr המלא, הפעילו debug logging עםclaude --debugאו על ידי הרצת/debugבאמצע הסשן.
#פלט JSON מובנה
קודי יציאה מאפשרים רק לחסום או להישאר בשקט. לשליטה רבה יותר, צאו עם 0 והדפיסו אובייקט JSON ל-stdout במקום זאת.
[!NOTE]
השתמשו ביציאה 2 כדי לחסום עם הודעת stderr, או ביציאה 0 עם JSON לשליטה מובנית. בחרו גישה אחת לכל הוק. למה שקורה כשמערבבים ביניהן, ראו Exit code output.
לדוגמה, הוק PreToolUse יכול לדחות קריאת כלי ולומר ל-Claude למה, או להעביר אותה למשתמש לאישור:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Use rg instead of grep for better performance"
}
}עם "deny", Claude Code מבטל את קריאת הכלי ומזין את permissionDecisionReason בחזרה ל-Claude.
ב-PreToolUse אפשר גם להחזיר "ask" כדי להציג למשתמש את בקשת ההרשאה הרגילה, או "allow" כדי לדלג על בקשת ההרשאה האינטראקטיבית. עם "allow", כללי deny ו-ask, כולל רשימות deny שמנוהלות ברמת הארגון, עדיין חלים, וכך גם בקשות עבור:
- קריאות מנתיבי רשת
- כלי MCP שמסומנים
requiresUserInteraction - קריאות לכלים שאפליקציית Agent SDK מסמנת
always_ask, אלא אם מצב ההרשאה מאשר את הקריאה - כלי connector שהארגון הגדיר ל-
askבסשנים שבהם ההגדרה הזו מגיעה ל-Claude Code
למה ש-"allow" עושה במצב plan, ראו Hook approvals in plan mode.
ערך רביעי, "defer", זמין במצב לא אינטראקטיבי עם הדגל -p. החזרתו מסיימת את התור כשקריאת הכלי נשמרת, כדי שעטיפת Agent SDK תוכל לאסוף קלט ולחדש. ראו Defer a tool call for later במדריך העזר.
הוק PreModelSwitch מחזיר את אותו שדה permissionDecision: "allow" מאפשר להחלפת מודל להמשיך, ו-"deny" מבטל אותה. "ask" מבקש לאשר את ההחלפה כשמריצים /model בסשן אינטראקטיבי. בכל מקום אחר, Claude Code מתייחס ל-"ask" כסירוב. ראו PreModelSwitch decision control.
אירועים אחרים משתמשים בדפוסי החלטה שונים. לדוגמה, הוקים מסוג PostToolUse ו-Stop משתמשים בשדה ברמה העליונה decision: "block", בעוד PermissionRequest משתמש ב-hookSpecificOutput.decision.behavior. ראו את טבלת הסיכום במדריך העזר לפירוט מלא לפי אירוע.
עבור הוקים מסוג UserPromptSubmit, השתמשו ב-hookSpecificOutput.additionalContext במקום זאת כדי להזריק טקסט להקשר של Claude. קננו את additionalContext בתוך hookSpecificOutput. אם ממקמים אותו ברמה העליונה של ה-JSON, Claude Code מתעלם ממנו בשקט. לדוגמה, הפלט הזה מוסיף את מצב הענף הנוכחי לכל פרומפט:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Current branch: release-42. Deploy freeze until Friday."
}
}ראו UserPromptSubmit decision control לצורת הפלט המלאה, כולל חסימת פרומפטים והגדרת כותרת הסשן.
הוקים עם type: "prompt" מטפלים בפלט בצורה שונה: ראו Prompt-based hooks.
#סינון הוקים עם matchers
בלי matcher, הוק מופעל בכל מופע של האירוע שלו. Matchers מאפשרים לצמצם את זה. לדוגמה, אם רוצים להריץ formatter רק אחרי עריכות קבצים, לא אחרי כל קריאת כלי, הוסיפו matcher להוק PostToolUse:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "prettier --write ..." }
]
}
]
}
}ה-matcher "Edit|Write" מופעל רק כש-Claude משתמש בכלי Edit או Write, לא כשהוא משתמש ב-Bash, Read או כל כלי אחר. פסיק מפריד חלופות באותו אופן, כך ש-"Edit, Write" שקול. ראו Matcher patterns לאופן שבו שמות פשוטים וביטויים רגולריים מוערכים.
[!NOTE]
Claude יכול גם ליצור או לשנות קבצים על ידי הרצת פקודות מעטפת. אם ההוק חייב לראות כל שינוי קובץ, למשל לסריקת תאימות או לרישום ביקורת, הוסיפו הוק
Stopשסורק את עץ העבודה פעם אחת בכל תור. לכיסוי לפי קריאה במקום זאת, התאימו גםBash|PowerShellותנו לסקריפט לרשום קבצים ששונו וקבצים שלא במעקב עםgit status --porcelain. סעיף קלט הוק PowerShell מסביר למה התאמה ל-Bashלבדו לא מספיקה. כדי להריץ הוק כשקובץ מסוים משתנה בדיסק, בלי קשר למי שכתב אותו, השתמשו בהוק FileChanged.
כל סוג אירוע מתאים על שדה מסוים:
| אירוע | מה ה-matcher מסנן | ערכי matcher לדוגמה |
|---|---|---|
PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied | שם הכלי | Bash, Edit|Write, mcp__.* |
SessionStart | איך הסשן התחיל | startup, resume, clear, compact, fork |
Setup | איזה דגל CLI הפעיל את ה-setup | init, maintenance |
SessionEnd | למה הסשן הסתיים | clear, resume, logout, prompt_input_exit, other |
Notification | סוג ההתראה | permission_prompt, idle_prompt, auth_success, elicitation_dialog, elicitation_url_dialog, elicitation_complete, elicitation_response, agent_needs_input, agent_completed, quota_auto_resume_fired, quota_auto_resume_stale, quota_auto_resume_disabled, plugin_notification |
SubagentStart | סוג הסוכן | general-purpose, Explore, Plan, או שמות סוכנים מותאמים |
PreCompact, PostCompact | מה הפעיל את הדחיסה | manual, auto |
PreModelSwitch, PostModelSwitch | השם הקנוני של המודל שהסשן עובר אליו, כפי שמתואר תחת PreModelSwitch | claude-opus-5, claude-opus-4-6|claude-opus-5, .*opus.* |
SubagentStop | סוג הסוכן | אותם ערכים כמו SubagentStart |
ConfigChange | מקור התצורה | user_settings, project_settings, local_settings, policy_settings, skills |
DirectoryAdded | איך הספרייה נוספה | slash_command, register_repo_root |
StopFailure | סוג השגיאה | rate_limit, overloaded, authentication_failed, oauth_org_not_allowed, account_on_hold, billing_error, invalid_request, model_not_found, server_error, max_output_tokens, cloud_credential_error, unknown |
InstructionsLoaded | סיבת הטעינה | session_start, nested_traversal, path_glob_match, include, compact |
Elicitation | שם שרת MCP | שמות שרתי ה-MCP שהגדרתם |
ElicitationResult | שם שרת MCP | אותם ערכים כמו Elicitation |
FileChanged | שמות קבצים מילוליים למעקב (ראו FileChanged) | .envrc|.env |
UserPromptExpansion | שם הפקודה | שמות ה-skill או הפקודה שלכם |
UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, CwdChanged, MessageDisplay | אין תמיכה ב-matcher | תמיד מופעל בכל מופע |
הלשוניות למטה מציגות עוד כמה matchers על סוגי אירועים שונים.
#רישום כל פקודת Bash
התאימו רק קריאות לכלי Bash ורשמו כל פקודה לקובץ. אירוע PostToolUse מופעל אחרי שהפקודה מסתיימת, כך ש-tool_input.command מכיל את מה שרץ. ההוק מקבל את נתוני האירוע כ-JSON ב-stdin, ו-jq -r '.tool_input.command' מחלץ רק את מחרוזת הפקודה, ש->> מוסיף לקובץ היומן:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}
]
}
]
}
}#התאמה לכלי MCP
כלי MCP משתמשים במוסכמת שמות שונה מכלים מובנים: mcp__<server>__<tool>, כאשר <server> הוא שם שרת ה-MCP ו-<tool> הוא הכלי שהוא מספק. לדוגמה, mcp__github__search_repositories או mcp__filesystem__read_file. כלים משרת שמצורף לתוסף משתמשים במקום זאת במקטע שרת עם scope, כמו mcp__plugin_my-plugin_db__query. השתמשו ב-matcher של ביטוי רגולרי כדי לכוון לכל הכלים משרת מסוים, או התאימו בין שרתים עם תבנית כמו mcp__.*__write.*. ראו Match MCP tools במדריך העזר לרשימת הדוגמאות המלאה.
הפקודה למטה מחלצת את שם הכלי מקלט ה-JSON של ההוק עם jq וכותבת אותו ל-stderr. כתיבה ל-stderr שומרת על stdout נקי לפלט JSON ושולחת את ההודעה ליומן הדיבוג:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__github__.*",
"hooks": [
{
"type": "command",
"command": "echo \"GitHub tool called: $(jq -r '.tool_name')\" >&2"
}
]
}
]
}
}#ניקוי בסיום הסשן
אירוע SessionEnd תומך ב-matchers על הסיבה שהסשן הסתיים. ההוק הזה מופעל רק על הסיבה clear, שנקבעת כשמריצים /clear, לא ביציאות רגילות:
{
"hooks": {
"SessionEnd": [
{
"matcher": "clear",
"hooks": [
{
"type": "command",
"command": "rm -f /tmp/claude-scratch-*.txt"
}
]
}
]
}
}#סינון לפי שם כלי וארגומנטים עם השדה if
השדה if משתמש בתחביר כללי הרשאה כדי לסנן הוקים לפי שם כלי וארגומנטים יחד, כך שתהליך ההוק נוצר רק כשקריאת הכלי תואמת. זה חורג מ-matcher, שמסנן ברמת הקבוצה לפי שם כלי בלבד.
לדוגמה, התצורה הזו מריצה הוק רק כש-Claude משתמש בפקודות git ולא בכל פקודות Bash:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(git *)",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"
}
]
}
]
}
}האם פקודת ההוק רצה תלוי בצורת תבנית ה-if ובפקודת Bash ש-Claude מפעיל:
תבנית if | פקודת Bash | ההוק רץ? | למה |
|---|---|---|---|
Bash(git *) | git push | כן | שם הפקודה תואם |
Bash(git *) | npm test && git push | כן | כל תת-פקודה נבדקת, git push תואם |
Bash(git *) | echo $(git log) | כן | פקודות בתוך $() ובתוך backticks נבדקות, git log תואם |
Bash(git *) | echo $(date) | לא | אין תת-פקודה שתואמת git * |
Bash(git push *) | echo $(date) | כן | תבניות שמציינות יותר משם הפקודה מריצות את ההוק בכל מקרה על $(), backticks או $VAR |
כש-Claude Code לא יכול לקבוע אילו פקודות קלט Bash מריץ, הוא מריץ את ההוק בלי תלות בתבנית. טבלת ההתאמה של Bash מכסה את צורות הפקודה ש-Claude Code יכול לצמצם לפי תת-פקודה ואת אלה שהוא לא יכול. מכיוון שהסינון הוא best-effort, השתמשו במערכת ההרשאות ולא בהוק כדי לאכוף allow או deny קשיח.
השדה if מקבל את אותן תבניות כמו כללי הרשאה: "Bash(git *)", "Edit(*.ts)" וכן הלאה. כדי להתאים כמה שמות כלים, השתמשו ב-handlers נפרדים שלכל אחד ערך if משלו, או התאימו ברמת matcher שבה נתמכת חלופה עם pipe.
if עובד רק על אירועי כלים: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest ו-PermissionDenied. הוספתו לכל אירוע אחר מונעת מההוק לרוץ.
#הגדרת מיקום ה-hook
המקום שבו מוסיפים hook קובע את ההיקף שלו:
| מיקום | היקף | ניתן לשיתוף |
|---|---|---|
~/.claude/settings.json | כל הפרויקטים שלך | לא, מקומי למחשב שלך |
.claude/settings.json | פרויקט יחיד | כן, אפשר לבצע commit למאגר |
.claude/settings.local.json | פרויקט יחיד | לא, נכנס ל-gitignore כש-Claude Code שומר אליו הגדרה |
| הגדרות מדיניות מנוהלות | ברמת הארגון | כן, בשליטת מנהל |
תוסף hooks/hooks.json | כשהתוסף מופעל | כן, ארוז עם התוסף |
| frontmatter של Skill | שאר הסשן מרגע שה-skill הופעל. ראו Hooks in skills and agents | כן, מוגדר בקובץ ה-skill |
| frontmatter של Subagent | בזמן שה-subagent הזה רץ | כן, מוגדר בקובץ ה-subagent |
הריצו /hooks ב-Claude Code כדי לעיין בכל ה-hooks המוגדרים, מקובצים לפי אירוע.
כדי להשבית hooks, הגדירו "disableAllHooks": true בקובץ ההגדרות. Claude Code קורא את הערך שנותר אחרי שחל סדר העדיפות של ההגדרות, כך שקובץ ההגדרות של פרויקט יכול לדרוס את שלכם. Hooks שמוגדרים בהגדרות מנוהלות עדיין רצים אלא אם disableAllHooks מוגדר גם שם. לטווח המלא של כל רמה, ראו disableAllHooks.
אם עורכים קבצי הגדרות ישירות בזמן ש-Claude Code רץ, צופה הקבצים בדרך כלל קולט שינויים ב-hooks באופן אוטומטי.
#Hooks מבוססי prompt
להחלטות שדורשות שיקול דעת ולא כללים דטרמיניסטיים, השתמשו ב-hooks מסוג type: "prompt". במקום להריץ פקודת shell, Claude Code שולח את ה-prompt שלכם ואת נתוני הקלט של ה-hook למודל Claude כדי לקבל את ההחלטה. אפשר לציין מודל אחר באמצעות השדה model אם צריך יותר יכולת.
התפקיד היחיד של המודל הוא להחזיר את ההחלטה שלו כ-JSON:
"ok": true: הפעולה ממשיכה"ok": false: מה שקורה תלוי באירוע:Stopו-SubagentStop: ה-reasonמוחזר ל-Claude כדי שהוא ימשיך לעבוד, אלא אם התשובה גם מגדירה"impossible": trueכדי לסמן שהתנאי הוא כזה שלעולם לא ניתן לספק, ובמקרה הזה Claude Code מאפשר את העצירה והתור מסתייםPreToolUse: קריאת הכלי נדחית. כברירת מחדל התור מסתיים וה-reasonשל הדחייה מופיע בצ'אט כשורת אזהרה. הגדירוcontinueOnBlock: trueעל ה-hook כדי במקום זאת להחזיר את ה-reasonל-Claude כשגיאת הכלי, כך שהוא יוכל להתאים ולהמשיךPostToolUse: כברירת מחדל התור מסתיים וה-reasonמופיע בצ'אט כשורת אזהרה. הגדירוcontinueOnBlock: trueכדי להחזיר את ה-reasonל-Claude ולהמשיך את התור במקום זאתPostToolBatch,UserPromptSubmitו-UserPromptExpansion: התור מסתיים וה-reasonמופיע בצ'אט כשורת אזהרה
הדוגמה הזו משתמשת ב-hook מסוג Stop כדי לשאול את המודל אם כל המשימות שביקשו הושלמו. אם המודל מחזיר "ok": false כי התנאי עדיין לא התקיים, Claude ממשיך לעבוד ומשתמש ב-reason כהוראה הבאה שלו:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
}
]
}
]
}
}לאפשרויות ההגדרה המלאות, ראו Hooks מבוססי prompt במדריך העיון.
#Hooks מבוססי agent
[!WARNING]
Agent hooks הם ניסיוניים. ההתנהגות וההגדרה עשויות להשתנות במהדורות עתידיות. לתהליכי עבודה בייצור, העדיפו command hooks.
כשהאימות דורש לבדוק קבצים או להריץ פקודות, השתמשו ב-hooks מסוג type: "agent". בניגוד ל-prompt hooks, שמבצעים קריאת LLM אחת, agent hooks מפעילים subagent שיכול לקרוא קבצים, לחפש בקוד ולהשתמש בכלים אחרים כדי לאמת תנאים לפני החזרת החלטה.
Agent hooks משתמשים בפורמט התשובה "ok" / "reason" עם timeout ברירת מחדל ארוך יותר של 60 שניות ועד 50 תורות של שימוש בכלים. הם לא תומכים בשדה impossible של prompt hook. כש-ok: false, Claude Code מטפל ב-agent hook כמו שהוא מטפל ב-prompt hook עם continueOnBlock: true על אותו אירוע, כך שב-PreToolUse וב-PostToolUse התור ממשיך. ל-agent hooks אין שדה continueOnBlock. ראו הגדרת agent hook לשדות, כולל ה-placeholder $ARGUMENTS ש-Claude Code מחליף בקלט ה-JSON של ה-hook.
הדוגמה הזו מוודאת שהבדיקות עוברות לפני שמאפשרים ל-Claude לעצור:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "agent",
"prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
"timeout": 120
}
]
}
]
}
}השתמשו ב-prompt hooks כשנתוני הקלט של ה-hook לבדם מספיקים כדי לקבל החלטה. השתמשו ב-agent hooks כשצריך לאמת משהו מול המצב בפועל של בסיס הקוד.
לאפשרויות ההגדרה המלאות, ראו Hooks מבוססי agent במדריך העיון.
#HTTP hooks
השתמשו ב-hooks מסוג type: "http" כדי לבצע POST של נתוני אירוע לנקודת קצה של HTTP במקום להריץ פקודת shell. נקודת הקצה מקבלת את אותו JSON ש-command hook היה מקבל ב-stdin, ומחזירה תוצאות דרך גוף תשובת ה-HTTP באותו פורמט JSON.
HTTP hooks שימושיים כשרוצים ששרת web, cloud function או שירות חיצוני יטפלו בלוגיקת ה-hook: לדוגמה, שירות ביקורת משותף שרושם אירועי שימוש בכלים ברחבי צוות.
הדוגמה הזו שולחת כל שימוש בכלי לשירות לוגים מקומי:
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/hooks/tool-use",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
]
}
]
}
}נקודת הקצה שלכם מגיבה בגוף JSON באותו פורמט פלט כמו command hooks, ו-Claude Code גם בודק את סטטוס התשובה:
- סטטוס 2xx: כדי לחסום קריאת כלי, החזירו בגוף את שדות
hookSpecificOutputהמתאימים. - כל סטטוס אחר, או שהבקשה נכשלת: Claude Code מדווח על שגיאה שאינה חוסמת ומאפשר לפעולה להמשיך. כדי שנקודת קצה שנכשלה תחסום את הפעולה, הגדירו
onFailure: "block"על ה-hook.
ערכי header תומכים בהחלפת משתני סביבה באמצעות התחביר $VAR_NAME או ${VAR_NAME}. רק משתנים שמופיעים במערך allowedEnvVars נפתרים. כל שאר ההפניות ל-$VAR נשארות ריקות.
לאפשרויות ההגדרה המלאות ולטיפול בתשובה, ראו HTTP hooks במדריך העיון.
#מגבלות ופתרון בעיות
#מגבלות
שמרו על האילוצים האלה כשמתכננים hooks:
- Command hooks מתקשרים רק דרך stdout, stderr וקודי יציאה. הם לא יכולים להפעיל פקודות
/או קריאות כלים. טקסט שמוחזר דרךadditionalContextמוזרק כ-system reminder שקלוד קורא כטקסט רגיל. HTTP hooks מתקשרים דרך גוף התגובה. - זמני המתנה של hooks משתנים לפי הסוג. אפשר לדרוס לכל hook עם השדה
timeoutבשניות.command,http,mcp_tool: 10 דקות. Claude Code מוריד את ברירת המחדל הזאת ל-30 שניות עבור hooks מסוגUserPromptSubmit,PreModelSwitchו-PostModelSwitch, ול-10 שניות עבורMessageDisplay.prompt: 30 שניות.agent: 60 שניות.- hooks מסוג
SessionEndמכל סוג חולקים תקציב של 1.5 שניות. אם ההגדרות שלכם קובעותtimeoutארוך יותר לכל hook, Claude Code מעלה את התקציב כדי להתאים, עד 60 שניות.
- hooks מסוג
PostToolUseלא יכולים לבטל פעולות כי הכלי כבר רץ. - hooks מסוג
PermissionRequestמופעלים כש-Claude Code עומד לבקש מכם הרשאה, או כשהוא היה דוחה אוטומטית קריאה שאי אפשר לבקש עליה אישור. במצב לא אינטראקטיבי עם הדגל-p, הם עדיין רצים מחוץ למצבdontAsk, וקריאה שאף hook לא מחליט עליה ושום דבר אחר לא יכול לענות עליה נדחית. - hooks מסוג
Stopמופעלים בכל פעם שקלוד מסיים להגיב, לא רק בסיום משימה. הם לא מופעלים בהפרעות של המשתמש. שגיאות API מפעילות StopFailure במקום. - כשכמה hooks מסוג
PreToolUseמחזיריםupdatedInputכדי לשכתב את הקלט של כלי, Claude Code לא ממזג את השכתובים ולא מבטיח עם איזה שכתוב הכלי רץ. הימנעו מיותר מ-hook אחד שמשכתב את הקלט של אותו כלי.
#Hooks ומצבי הרשאה
עם hook בקובץ הגדרות או ב-hooks/hooks.json של תוסף אי אפשר להרפות ממגבלות מעבר למה שכללי ההרשאה מאפשרים, ו-"deny" של hook נשמר בכל מצב הרשאה:
מה עדיין גובר על
"allow": hook שמחזיר"allow"לא עוקף כללי deny מההגדרות, והוא לא יכול לדכא את הבקשה עבור:- קריאות מנתיבי רשת
- כלי MCP שמסומנים
requiresUserInteraction - קריאות לכלים שאפליקציית Agent SDK מסמנת
always_ask, אלא אם מצב ההרשאה מאשר את הקריאה - כלי connector שהארגון שלכם הגדיר ל-
askבסשנים שבהם ההגדרה הזאת מגיעה ל-Claude Code
במצב plan, אם ה-hook מסוג
PreToolUseשלכם מחזיר"allow"לעריכת קובץ, מקבלים את אותה בקשה, חסימה או אישור שהעריכה הייתה מקבלת בלי hook. כדי להסיר את המגבלה הזאת על אישורי hooks, אשרו את התוכנית או עברו למצב הרשאה אחר."deny"בכל מצב הרשאה: hook שמחזירpermissionDecision: "deny"חוסם את הכלי גם במצבbypassPermissionsאו עם--dangerously-skip-permissions. hooks מסוגPreToolUseמופעלים לפני כל בדיקת מצב הרשאה, בכל מצב הרשאה, כוללdontAsk. זה מאפשר לאכוף מדיניות שמשתמשים לא יכולים לעקוף על ידי שינוי מצב ההרשאה שלהם.
[!NOTE]
אם למחשב שלכם אין הגדרות מנוהלות והסשן שלכם לא משתמש באישורי
/loginלתוכנית Team או Enterprise, mod יכול לאשר קריאה שה-hook מסוגPreToolUseשלכם חסם. סשן שרץ על מפתח API או עלCLAUDE_CODE_OAUTH_TOKENארוך טווח לא משתמש בהתחברות הזאת, גם כשההתחברות הזאת שמורה.במצב plan, mod יכול לאשר קריאה חסומה כזאת רק כשהיא לקריאה בלבד, ולכן לא עריכת קובץ. למקרים שבהם אישור של mod לא עובר את הכללים וה-hooks שלכם, ראו Extend permissions with hooks.
#Hook לא מופעל
ה-hook מוגדר אבל אף פעם לא רץ.
- הריצו
/hooksואשרו שה-hook מופיע תחת האירוע הנכון - עבור hook ב-frontmatter של skill, הפעילו את ה-skill או בקשו מקלוד לעשות זאת, ואז הריצו שוב
/hooks./hooksלא מציג hooks מ-skill שלא הופעל בסשן. אם/hooksעדיין לא מציג את ה-hook, בדקו סיבות אחרות, כמו frontmatter שלא נותח או אחת מהמגבלות על skill hooks - בדקו שתבנית ה-matcher תואמת לשם הכלי בדיוק. Matchers רגישים לאותיות גדולות וקטנות
- ודאו שאתם מפעילים את סוג האירוע הנכון:
PreToolUseמופעל לפני הרצת הכלי,PostToolUseמופעל אחרי. hook מסוגPermissionRequestמופעל כש-Claude Code עומד לבקש מכם הרשאה. ראו את המגבלות למקרים הלא אינטראקטיביים
#שגיאת hook בפלט
רואים הודעה כמו "PreToolUse hook error: ..." בתמליל.
הסקריפט שלכם יצא עם קוד שונה מאפס באופן לא צפוי. בדקו אותו ידנית על ידי העברת JSON לדוגמה בצינור:
echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh echo $? # Check the exit codeאם רואים "command not found", השתמשו בנתיבים מוחלטים או ב-
${CLAUDE_PROJECT_DIR}כדי להפנות לסקריפטים. כדי להימנע לגמרי מציטוט ב-shell, הוסיפו"args": []כדי לעבור לצורת exec, שמפעילה את הסקריפט ישירות בלי shellאם רואים "jq: command not found", התקינו את
jqאו השתמשו ב-Python/Node.js לניתוח JSONאם ההודעה כוללת
blocking because Git Bash wasn't found, אתם ב-Windows, Claude Code לא מצא את Git Bash, וה-hook שנכשל או שפג הזמן שלו חסם את קריאת הכלי. ראו Failed hooks on Windows without Git Bash לתיקוניםאם ההודעה מציגה הודעת אימות JSON, ה-stdout של ה-hook שלכם נותח כ-JSON אבל נכשל באימות הסכמה. אם היא מציגה הודעת ניתוח JSON, ה-stdout נראה כמו אובייקט JSON אבל לא היה JSON תקין. שני המקרים קורים גם ביציאה 0.
כדי לתקן כשל ניתוח, בנו את המטען עם מקודד JSON כמו
jqבמקום שרשור מחרוזות, כך שמרכאות ולוכסנים הפוכים בתוך ערכים יוברחו. הסעיף Exit code output במדריך מכסה את השילובים של קוד יציאה ו-JSONאם הסקריפט לא רץ בכלל, הפכו אותו לבר הרצה:
chmod +x ./my-hook.sh
#/hooks לא מציג hooks מוגדרים
ערכתם קובץ הגדרות אבל ה-hooks לא מופיעים בתפריט.
- עריכות קבצים נקלטות בדרך כלל אוטומטית. אם הן לא הופיעו אחרי כמה שניות, ייתכן שצופה הקבצים פספס את השינוי: הפעילו מחדש את הסשן כדי לכפות טעינה מחדש.
- ודאו שה-JSON שלכם תקין: פסיקים בסוף והערות לא מותרים
- אשרו שקובץ ההגדרות נמצא במיקום הנכון:
.claude/settings.jsonעבור hooks של פרויקט,~/.claude/settings.jsonעבור hooks גלובליים - אם התפריט מציג
Only hooks from managed settings run here, הארגון שלכם הגדירallowManagedHooksOnly. Hooks בקבצי ההגדרות של המשתמש, הפרויקט והמקומי לא רצים ולא מופיעים ברשימה
#Stop hook מגיע לתקרת החסימה
קלוד ממשיך לעבוד במקום לעצור, ואז מסיים את התור עם אזהרה שה-Stop hook חסם יותר מדי פעמים ברצף.
Claude Code דורס Stop hook אחרי שהוא חוסם שמונה פעמים ברצף בלי קריאת כלי מקלוד ביניהן. סקריפט ה-hook שלכם צריך לבדוק אם הוא כבר הפעיל המשך. נתחו את השדה stop_hook_active מקלט ה-JSON וצאו מוקדם אם הוא true:
#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
exit 0 # Allow Claude to stop
fi
# ... rest of your hook logicאם ה-hook שלכם באמת צריך יותר משמונה איטרציות כדי להתכנס, העלו את התקרה עם CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.
#ל-JSON של ה-hook אין השפעה
ה-hook שלכם מדפיס JSON תקין, אבל ההחלטה לא נכנסת לתוקף ולא מופיעה שגיאה בתמליל. בדקו איזו סיבה חלה:
- פלט נוסף לפני ה-JSON: משהו אחר כותב ל-stdout קודם, בדרך כלל
echoלא מותנה בפרופיל ה-shell שלכם, כך שהפלט כבר לא מתחיל ב-{. ראו פלט פרופיל shell לפני ה-JSON. - שדה ברמה הלא נכונה: השוו את המיקום של כל שדה מול פורמט JSON output. לדוגמה,
permissionDecisionשייך בתוךhookSpecificOutput, לא ברמה העליונה. ראו שדות ברמה הלא נכונה.
#פלט פרופיל shell לפני ה-JSON
Hooks רצים ב-shells לא אינטראקטיביים, אבל Git Bash וחלק מההגדרות, כמו BASH_ENV שמצביע על ~/.bashrc, עדיין טוענים את הפרופיל שלכם, וכל מה שהפרופיל מדפיס מגיע ל-stdout לפני ה-JSON של ה-hook:
Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}אלא אם ה-hook הוא async, Claude Code קורא פלט שלא מתחיל ב-{ כטקסט רגיל, כך שה-JSON שלכם מתעלמים ממנו. מכיוון שה-hook יצא ב-0, התמליל גם לא מציג שגיאה. כדי לבדוק את הסיבה הזאת, הפעילו את Claude Code עם claude --debug, הפעילו את ה-hook, וחפשו ביומן הדיבוג את Hook output does not start with {. כדי לתקן, עטפו את משפטי ה-echo בפרופיל כך שירוצו רק ב-shells אינטראקטיביים:
# In ~/.zshrc or ~/.bashrc
if [[ $- == *i* ]]; then
echo "Shell ready"
fiהמשתנה $- מכיל דגלי shell, ו-i פירושו אינטראקטיבי. Hooks רצים ב-shells לא אינטראקטיביים, כך שה-echo מדולג.
#שדות ברמה הלא נכונה
כשה-hook שלכם מחזיר permissionDecision או additionalContext ברמה העליונה במקום בתוך hookSpecificOutput, ה-JSON עדיין מנותח, ו-Claude Code מתעלם מהשדות במקום הלא נכון בלי לדווח על שגיאה. כדי לראות אילו שדות הוא התעלם מהם, הפעילו את Claude Code עם claude --debug וחפשו ביומן הדיבוג את Hook JSON output had unrecognized keys.
#בדיקה מה hook עשה
לחצו Ctrl+O כדי לפתוח את תצוגת התמליל וחפשו את התוצאה של ה-hook:
- הצלחה: לא רואים כלום, אלא אם ה-JSON של ה-hook מציג משהו, כמו
systemMessageאו משוב של Stop hook.- כדי לאשר שה-hook רץ, בדקו את ההשפעה שלו, כמו קובץ שעוצב מחדש
- שגיאה חוסמת: ברוב האירועים רואים את ההודעה שהגיעה עם החסימה, לדוגמה
Blocked: rm commands are not allowed. בכמה אירועים, כמוConfigChangeו-Elicitation, לא רואים הודעה. Exit code 2 מכסה מאיפה ההודעה מגיעה. - שגיאה לא חוסמת: רואים הודעת
<hook name> hook errorעם הסבר קצר, כמו השורה הראשונה של stderr אחריFailed with non-blocking status code:, או הודעת אימות או ניתוח JSON. הפעולה המשיכה.
כדי לחפש את התוצאה עבור קוד יציאה ו-stdout מסוימים, כולל החריגים לפי אירוע, ראו Exit code output במדריך.
לפרטי הרצה מלאים, כולל קודי יציאה של hooks, stdout ו-stderr, קראו את יומן הדיבוג. הפעילו את Claude Code עם claude --debug-file /tmp/claude.log כדי לכתוב לנתיב ידוע, ואז tail -f /tmp/claude.log בטרמינל אחר. אם הפעלתם בלי הדגל הזה, הריצו /debug באמצע הסשן כדי להפעיל תיעוד ולמצוא את נתיב היומן.
#מידע נוסף
- Hooks reference: סכמות אירועים מלאות, פורמט פלט JSON, async hooks ו-MCP tool hooks
- Security considerations: סקירה לפני פריסת hooks בסביבות משותפות או ייצור
- Bash command validator example: מימוש ייחוס מלא