Hooks ב-Claude Code: איך להריץ אוטומציה בכל שלב בעבודה

מאת צוות מדיה דיל · 08.08.2026 · AI · 9 דק׳

מדריך מעשי ל-Hooks ב-Claude Code: איך מריצים אוטומציה - הרצת פורמט, בדיקות lint וחסימת פקודות מסוכנות - בכל שלב בעבודת הסוכן, בלי להסתמך על הזיכרון או שיקול הדעת של המודל עצמו.

מכירים את הרגע הזה: Claude Code סיים לערוך קובץ, הקוד עובד מצוין, אבל שכחתם להריץ Prettier, ה-linter צועק עליכם ב-CI, ואתם מגלים את זה רק כשה-pull request כבר פתוח ומישהו מהצוות מגיב "יש בעיות פורמט". או גרוע מזה - סוכן AI שמריץ פקודת rm -rf על תיקייה שלא התכוונתם למחוק, ואין שום מנגנון שעוצר אותו בזמן. בדיוק בשביל זה קיימים Hooks ב-Claude Code: דרך להריץ אוטומציה - סקריפט shell, קריאת HTTP, או אפילו פרומפט ל-LLM - בדיוק בנקודות המפתח של תהליך העבודה, בלי להסתמך על זה שהמודל "יזכור" לעשות את זה בעצמו.

מה זה בעצם Hooks ב-Claude Code

Hooks הם פקודות מוגדרות-משתמש שרצות אוטומטית בנקודות מסוימות במחזור החיים (lifecycle) של Claude Code. במקום להסביר ל-Claude בכל פעם מחדש "תריץ lint אחרי עריכה" או "אל תמחק קבצים בלי לבדוק קודם", אתם מגדירים Hook פעם אחת, וההתנהגות הזו הופכת לחלק קבוע ואמין מהתהליך - היא לא תלויה בזיכרון של המודל, בהקשר השיחה, או במצב הרוח שלו באותו טוקן.

מבחינה טכנית, Hook יכול להיות סוג אחד מכמה: פקודת command (סקריפט shell רגיל), קריאת http לשרת חיצוני, קריאה לכלי MCP (mcp_tool), פרומפט שנשלח למודל (prompt), או אפילו סוכן משנה שלם (agent). ה-Hook מקבל מידע על מה שקורה כרגע דרך JSON - ב-stdin עבור command hooks, או בגוף הבקשה עבור HTTP hooks - וב"עונה" בחזרה באמצעות exit code, פלט ל-stdout, ולעיתים גם אובייקט JSON מובנה שמכתיב מה יקרה הלאה.

למי שכבר עובד עם Claude Code על בסיס יומיומי, ה-Hooks הם בעצם השכבה שהופכת אותו מכלי שעוזר לכם לכתוב קוד, לסביבת עבודה עם gates אוטומטיים - בדיוק כמו pre-commit hooks ב-git, רק גמישים הרבה יותר ומכוונים לכל שלב בתהליך שבו הסוכן פועל.

אילו אירועים (Events) אפשר לתפוס

הלב של המערכת הוא רשימת ה-Events שבהם אפשר "לתלות" Hook. חלקם רלוונטיים כמעט לכל צוות פיתוח, אחרים יותר נישתיים. כדאי להכיר לפחות את הבסיסיים:

  • PreToolUse - נורה לפני שכלי (Tool) בפועל מתבצע, למשל לפני הרצת פקודת Bash או לפני עריכת קובץ. זהו האירוע שמאפשר לחסום פעולה לפני שהיא קורית בכלל - למשל לעצור פקודת מחיקה מסוכנת.
  • PostToolUse - נורה אחרי שכלי הצליח לרוץ. זה בדיוק המקום להריץ פורמטר או linter מיד אחרי עריכת קובץ, כשה-Claude עדיין "בתמונה" ויכול להגיב לתוצאה.
  • PostToolUseFailure - נורה כשכלי נכשל בהרצתו, שימושי לתפוס כשלים ולתעד אותם.
  • UserPromptSubmit - נורה לפני ש-Claude מעבד פרומפט שהמשתמש שלח, ומאפשר להוסיף הקשר או לחסום פרומפט לפני שהוא בכלל נכנס לעיבוד.
  • Stop - נורה כש-Claude מסיים לענות בתור. אפשר להשתמש בו כדי לוודא שתנאי מסוים מתקיים (למשל שכל הבדיקות עוברות) לפני שהתהליך באמת "נגמר".
  • SubagentStop - מקביל ל-Stop אבל עבור סוכן משנה (subagent) שמסיים את פעולתו, רלוונטי בעבודה עם ריבוי סוכנים.
  • SessionStart ו-SessionEnd - נוריות בתחילת וסיום הסשן, כולל מקרים של resume, clear או compact - שימושיים לטעינת הקשר ראשוני או לניקוי בסיום.
  • PreCompact ו-PostCompact - נוריות לפני ואחרי דחיסת ההקשר (context compaction), שימושי אם רוצים לשמר מידע לפני שהוא "נדחס" ואולי מאבד פרטים.
  • PermissionRequest ו-PermissionDenied - נוריות כשכלי מבקש החלטת הרשאה, או כשההרשאה נדחתה - נקודת שליטה נוספת מעבר ל-PreToolUse.
  • Notification - נורה כש-Claude Code שולח התראה למשתמש, למשל בקשת הרשאה או מצב idle.

מעבר לאלה יש עוד אירועים ממוקדים יותר - סביב יצירת worktrees, שינויי קונפיגורציה, טעינת CLAUDE.md, ניהול tasks ועוד - אבל רוב הצוותים שמתחילים עם Hooks יעבדו בעיקר עם PreToolUse, PostToolUse, UserPromptSubmit ו-Stop. אלו האירועים שנותנים את ההחזר הכי גדול על ההשקעה.

איך מגדירים Hook בפועל - settings.json

ההגדרה של Hooks נעשית בקובץ JSON, שאפשר למקם בכמה רמות: ~/.claude/settings.json לכל הפרויקטים שלכם, .claude/settings.json בתוך פרויקט ספציפי (וגם לשתף עם הצוות ב-git), .claude/settings.local.json לקובץ אישי שלא עולה ל-git, ואפילו הגדרות ברמת ארגון או בתוך plugin. כל ההגדרות האלה מתמזגות זו עם זו, כך שאפשר לשלב Hooks גלובליים עם כאלה שספציפיים לפרויקט מסוים.

המבנה הבסיסי נראה כך:

  • מפתח עליון בשם hooks, ותחתיו מפתח לכל שם Event (למשל PostToolUse).
  • מערך של אובייקטים, שכל אחד מהם מכיל matcher - תבנית שמגדירה על אילו כלים או תת-אירועים ה-Hook יופעל.
  • בתוך כל matcher, מערך hooks בפועל - כל אחד מגדיר type (למשל command), את הפקודה עצמה, וזמן timeout אופציונלי.

ה-matcher יכול להיות פשוט מאוד - כוכבית או מחרוזת ריקה שתופסת הכל, שם כלי מדויק כמו Bash, רשימה מופרדת בקו אנכי כמו Edit|Write, או אפילו regex מלא כשמדובר בתווים מיוחדים. דוגמה מוחשית ל-Hook שמריץ בדיקת lint אחרי כל עריכה או כתיבה של קובץ:

  • Event: PostToolUse
  • matcher: "Edit|Write" - כלומר, יופעל רק אחרי שהכלי Edit או הכלי Write רץ בהצלחה
  • hook מסוג command שמריץ סקריפט מקומי, למשל ${CLAUDE_PROJECT_DIR}/.claude/hooks/lint-check.sh

שימו לב למשתנה ${CLAUDE_PROJECT_DIR} - זהו placeholder שמייצג את שורש הפרויקט, כדי שהסקריפט יעבוד בצורה עקבית בלי לתלות אותו בנתיב מוחלט. בדומה לו קיימים גם ${CLAUDE_PLUGIN_ROOT} ו-${CLAUDE_PLUGIN_DATA} לעבודה עם plugins.

הסקריפט עצמו מקבל את המידע הרלוונטי כ-JSON דרך stdin - שדות כמו session_id, cwd, hook_event_name, ובאירועי כלי גם tool_name ו-tool_input עם הפרמטרים המדויקים שהכלי קיבל. כלי כמו jq הופך את שליפת השדות האלה לפשוטה למדי בתוך סקריפט bash.

קודי יציאה (Exit Codes) - איך ה-Hook "מדבר" עם Claude

אחרי שהסקריפט רץ, האופן שבו הוא מסתיים קובע מה קורה הלאה, וזה אחד הדברים החשובים ביותר להבין נכון:

  • Exit code 0 - הצלחה. אם ה-Hook כותב JSON תקין ל-stdout, Claude Code מפרסר אותו ומשתמש בשדות שבו כדי להשפיע על ההמשך. פלט ל-stderr במקרה הזה הולך רק ל-debug log, לא חוזר ל-Claude.
  • Exit code 2 - שגיאה חוסמת. תוכן ה-stderr מוזרם בחזרה ל-Claude כהודעת שגיאה, וכל JSON שנכתב מתעלמים ממנו. ההשפעה המדויקת תלויה באירוע הספציפי: ב-PreToolUse זה חוסם את קריאת הכלי; ב-UserPromptSubmit זה חוסם ומוחק את הפרומפט; ב-Stop זה מונע מ-Claude לעצור וגורם לו להמשיך.
  • כל קוד יציאה אחר - שגיאה לא-חוסמת. הפעולה ממשיכה כרגיל, אך ב-transcript תופיע הודעת שגיאה עם השורה הראשונה מה-stderr, ושאר הפרטים נשארים ב-debug log.

מעבר לקוד היציאה, Hook יכול להחזיר גם אובייקט JSON מובנה עם שדות כמו continue (עצירת כל התהליך), decision ו-reason (למשל "block" עם הסבר), ותת-אובייקט hookSpecificOutput שמכיל שדות ייחודיים לפי סוג האירוע - כמו permissionDecision באירועי PreToolUse שיכול לקבל את הערכים allow, deny, ask או defer, כולל אפשרות לשנות בפועל את הקלט לכלי דרך updatedInput לפני שהוא מתבצע.

שיקולי אבטחה - למה חשוב לשים לב

Hooks הם כלי עוצמתי, אבל בדיוק בגלל זה יש כמה נקודות שכדאי להכיר לפני שסומכים עליהם על עיוור:

  • פלט מוגבל בגודל - הפלט של Hook מוגבל ל-10,000 תווים; מעבר לזה נשמר לקובץ נפרד עם תצוגה חלקית בלבד.
  • הגנה מפני הזרקת פרומפט (prompt injection) - שדה additionalContext שהוחזר מ-Hook עובר דרך אותן הגנות שחלות על כל תוכן שמגיע מבחוץ, ולכן מומלץ לכתוב בו קביעות עובדתיות ולא פקודות ציווי - כדי לא ליצור וקטור תקיפה בטעות.
  • שליטה ברמת מדיניות ארגונית - הגדרה בשם allowManagedHooksOnly מאפשרת לארגון לחסום Hooks שהוגדרו ברמת משתמש, פרויקט או plugin, ולהשאיר רק Hooks שהוגדרו במדיניות המנוהלת.
  • Allowlists ל-HTTP hooks - הגדרות כמו allowedHttpHookUrls ו-httpHookAllowedEnvVars מגבילות לאילו כתובות URL מותר לפנות ואילו משתני סביבה מותר לחשוף להם, מה שחשוב כשה-Hook שולח מידע רגיש לשרת חיצוני.
  • בדיקת תקינות JSON - קובץ profile של shell שמדפיס פלט בעת עלייה (כמו הודעת ברוכים הבאים) יכול "לזהם" את הפלט של Hook ולשבור את הפרסור של ה-JSON, ולכן שווה לוודא שהסקריפטים רצים בסביבה נקייה.

המסקנה המעשית: כשמדובר ב-Hooks שחוסמים פעולות מסוכנות, כתבו אותם בזהירות, תבדקו אותם היטב, ותזכרו שהם רצים עם ההרשאות של המשתמש שמריץ את Claude Code - כלומר יש להם גישה אמיתית למערכת הקבצים ולסביבה.

דוגמה מהשטח: חסימת פקודות הרסניות

אחד השימושים הכי נפוצים ב-Hooks הוא רשת ביטחון מול פקודות Bash מסוכנות. הרעיון: Hook מסוג PreToolUse עם matcher על Bash, שבודק את תוכן הפקודה לפני שהיא רצה בפועל. אפשר אפילו לצמצם את התפעול שלו רק לתת-מקרים מסוימים באמצעות שדה if שמגדיר תנאי הרשאה, למשל "Bash(rm *)" - כך שה-Hook יופעל רק כשמדובר בפועל בפקודת rm.

הסקריפט עצמו קורא את השדה tool_input.command מתוך ה-JSON שהגיע ב-stdin (למשל בעזרת jq), ובודק אם מדובר בפקודה מסוכנת כמו rm -rf. אם כן - הוא מחזיר JSON עם hookSpecificOutput.permissionDecision ששווה ל-"deny" ועם permissionDecisionReason שמסביר למה. אם לא - הוא פשוט יוצא עם exit code 0 בלי להחזיר החלטה, ואז זרימת ההרשאות הרגילה של Claude Code ממשיכה כרגיל. זהו בדיוק סוג ה-Hook שמאפשר לצוותי פיתוח לתת ל-Claude Code הרשאות רחבות יחסית לעבודה עצמאית, בלי לוותר על שכבת ביטחון בסיסית מפני טעויות או פקודות שיצאו משליטה.

בדיוק באותו אופן אפשר לבנות Hook על PostToolUse שרץ אחרי כל Edit או Write ומריץ בו-זמנית Prettier, ESLint או Black על הקובץ שהשתנה, כך שהקוד שיוצא מתחת לידיים של Claude תמיד מפורמט ועומד בסטנדרטים של הפרויקט - בלי שאתם צריכים לזכור לעשות את זה, ובלי לחכות ל-CI כדי לגלות שזה לא קרה.

מתי Hooks ומתי CLAUDE.md

שאלה שעולה הרבה: אם אפשר פשוט לכתוב ב-CLAUDE.md "תמיד תריץ lint אחרי עריכה", למה בכלל צריך Hooks? התשובה היא שהוראות בקובץ הנחיות הן המלצה למודל - הוא בדרך כלל יעקוב אחריה, אבל לא בטוח ב-100% מהמקרים, במיוחד בשיחות ארוכות שבהן ההקשר מתמלא. Hook, לעומת זאת, הוא מנגנון דטרמיניסטי שרץ ברמת המערכת (harness) ולא תלוי בזיכרון או בשיקול הדעת של המודל. לכן, ככלל אצבע: הוראות התנהגות כלליות שייכות ל-CLAUDE.md או ל-skills ופקודות מותאמות אישית, ואילו כל דבר שחייב לקרות בוודאות - פורמט קוד, בדיקות אבטחה, חסימת פעולות מסוכנות, עדכון מערכות חיצוניות - שייך ל-Hooks.

שאלות נפוצות

מה ההבדל בין PreToolUse ל-PostToolUse?

PreToolUse נורה לפני שהכלי בפועל רץ, ולכן הוא היחיד שיכול לחסום את הפעולה מראש - למשל למנוע הרצת פקודה מסוכנת. PostToolUse נורה אחרי שהכלי כבר הצליח לרוץ, ולכן משמש בעיקר להרצת פעולות המשך כמו lint או פורמט, לא לחסימה - כי הפעולה המקורית כבר קרתה.

איפה בדיוק מגדירים Hooks בפרויקט?

ההגדרה נמצאת בקובץ JSON, ואפשר למקם אותה בכמה רמות: ~/.claude/settings.json עבור הגדרות שחלות על כל הפרויקטים שלכם, .claude/settings.json בתוך פרויקט ספציפי כדי לשתף עם כל הצוות דרך git, או .claude/settings.local.json להגדרות אישיות שלא נכנסות לבקרת גרסאות. אפשר גם להגדיר Hooks ברמת plugin או במדיניות ארגונית.

מה קורה אם ה-Hook שלי נכשל או נתקע?

לכל Hook יש timeout (ברירת המחדל היא 600 שניות עבור command hooks) שאחריו הוא מבוטל. אם ה-Hook יוצא עם קוד שאינו 0 ואינו 2, מדובר בשגיאה לא-חוסמת - הפעולה המקורית ממשיכה כרגיל, וב-transcript תוצג רק השורה הראשונה מה-stderr לצורך דיבוג, כשהפרטים המלאים נשמרים בקובץ ה-debug log.

האם Hook יכול לשנות את הפקודה שהמודל רצה להריץ, לא רק לחסום אותה?

כן. באירוע PreToolUse אפשר להחזיר בשדה hookSpecificOutput.updatedInput קלט מעודכן לכלי, כך שהפעולה בפועל תרוץ עם פרמטרים ששונו על ידי ה-Hook, ולא רק להחליט אם לאשר או לחסום אותה כמו שהיא.

האם Hooks יכולים לרוץ גם דרך HTTP ולא רק כסקריפט מקומי?

כן, בנוסף ל-Hook מסוג command שמריץ סקריפט מקומי, יש גם Hook מסוג http ששולח בקשה לכתובת URL חיצונית, Hook מסוג mcp_tool שקורא לכלי MCP קיים, ואפילו Hooks מסוג prompt או agent שמפעילים מודל שפה כדי לקבל החלטה.

האם צריך לכתוב Hooks בעצמנו מאפס בכל פרויקט?

לא בהכרח - אפשר לשתף הגדרות Hooks דרך .claude/settings.json שנכנס לבקרת גרסאות יחד עם שאר קוד הפרויקט, כך שכל מי שמצטרף לצוות מקבל אוטומטית את אותן רשתות ביטחון ואוטומציות, בלי צורך להגדיר הכל מחדש בכל מכונה.

הטמעה נכונה של Hooks יכולה לחסוך לצוות שעות של תיקוני פורמט, לתפוס באגים לפני שהם מגיעים ל-production, ולתת שקט נפשי אמיתי כשעובדים עם Claude Code על בסיס יומיומי - אבל היא דורשת הבנה מדויקת של האירועים, קודי היציאה ושיקולי האבטחה כדי לא ליצור תלות שברירית. בצוות מדיה דיל אנחנו מלווים ארגונים וצוותי פיתוח בהטמעת Claude Code בצורה בטוחה ויעילה, כולל בניית Hooks מותאמים לתהליכי העבודה הספציפיים שלכם. מוזמנים לדבר איתנו ב-וואטסאפ

תגיות: Claude Code · Hooks · PreToolUse · PostToolUse · אוטומציה בפיתוח · settings.json · AI Agents

← חזרה לבלוג · צור קשר