Claude Code Stop Hook: איך לגרום לסוכן לעצור, לקצר, ולשאול לפני שהוא מניח

בשורה התחתונה

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

איור פתיחה למדריך: Claude Code Stop Hook

הבעיה: הסוכן הפסיק לשאול

אם בזמן האחרון קלוד מרגיש לכם פחות מדויק, זה לא אתם וזה לא באג. השתנתה לו ההתנהגות: כשהוא לא בטוח מה בדיוק ביקשתם, הוא כבר לא עוצר לשאול. הוא מנחש בביטחון וממשיך.

הסיבה מבנית. מודלים מדורגים לפי מבחנים אוטומטיים, ובמבחנים כאלה תשובה בטוחה ושגויה מקבלת יותר נקודות משאלת הבהרה. זה כמו מועמד בריאיון עבודה שאף פעם לא אומר “אני לא יודע”. הוא נשמע חד, אבל חלק מהתשובות שלו הן ניחוש.

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

למה הוראה בקובץ CLAUDE.md לא פותרת את זה

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

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

Hook הוא מנגנון. זה קוד שרץ בצד שלכם, לא בתוך הפרומפט. הוא לא מושפע מאורך השיחה, הוא לא נשכח, והוא רץ בכל פעם מחדש.

מה זה Stop Hook

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

ה-Stop hook נורה בדיוק ברגע שבו הסוכן סיים לענות ולפני שהתור נסגר. זו נקודת החניה האחרונה, ולכן זה המקום היחיד שממנו אפשר להסתכל על התשובה המוגמרת ולהחליט אם לאשר אותה או להחזיר אותה לכתיבה מחדש.

מה ה-hook מקבל

Claude Code מריץ את הפקודה שלכם ושולח לה JSON ב-stdin. השדות שרלוונטיים לנו:

שדהמה יש בו
last_assistant_messageהטקסט המלא של התשובה שהסוכן הרגע סיים לכתוב. זה מה שאנחנו סופרים.
prompt_idמזהה ייחודי של התור הנוכחי. משמש אותנו כדי לא להיתקע בלולאה.
session_idמזהה השיחה. גיבוי למקרה שאין prompt_id.
cwdהתיקייה שממנה רצה השיחה. שימושי אם רוצים כללים שונים לפרויקטים שונים.
stop_reasonלמה הסוכן עצר, למשל end_turn.

איך ה-hook עונה

שתי דרכים. הפשוטה: לצאת עם קוד יציאה 2 ולכתוב את הסיבה ל-stderr. המדויקת יותר, וזו שנשתמש בה: לצאת עם 0 ולהדפיס JSON ל-stdout.

קוד יציאהמה קורה
0הצלחה. אם הודפס JSON ל-stdout, Claude Code קורא ממנו את ההחלטה. בלי JSON, התשובה מאושרת והתור נסגר.
2חסימה. התור לא נסגר, הסוכן ממשיך לעבוד, ומה שכתבתם ל-stderr הופך לסיבת החסימה.
אחרשגיאה לא חוסמת. התור נסגר כרגיל ומוצגת הודעת שגיאה קטנה.

ה-JSON שמחזיר חסימה נראה כך, וה-reason הוא ההוראה שהסוכן מקבל כדי לתקן את עצמו:

{
  "hookSpecificOutput": {
    "hookEventName": "Stop",
    "decision": "block",
    "reason": "התשובה ארוכה מדי. קצר אותה, או שאל שאלת הבהרה."
  }
}

שלב 1: יוצרים את קובץ ה-hook

צרו תיקייה בשם hooks בתוך תיקיית ההגדרות של Claude Code בבית שלכם, ובתוכה קובץ בשם word-limit.js:

Windows:    C:\Users\YOUR_NAME\.claude\hooks\word-limit.js
Mac/Linux:  ~/.claude/hooks/word-limit.js

הקוד כתוב ב-Node.js בלי ספריות חיצוניות, כי Node כבר מותקן אצל כל מי שמריץ Claude Code. אין מה להתקין.

זה הקוד המלא. העתיקו אותו כמו שהוא:

#!/usr/bin/env node
/**
 * Stop hook - word limit
 * חוסם כל תשובה של הסוכן שעוברת את מגבלת המילים,
 * ומחזיר לו הוראה לקצר או לשאול שאלה במקום לנחש.
 */

const fs = require("fs");
const os = require("os");
const path = require("path");

const LIMIT = 150;        // מגבלת המילים
const MAX_BLOCKS = 2;     // כמה פעמים מותר לחסום את אותו תור
const IGNORE_CODE = true; // לא לספור בלוקים של קוד

let raw = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => (raw += chunk));
process.stdin.on("end", () => {
  let input;
  try {
    input = JSON.parse(raw);
  } catch (e) {
    process.exit(0); // קלט לא תקין - לא חוסמים
  }

  let text = input.last_assistant_message || "";
  if (IGNORE_CODE) {
    text = text.replace(/```[\s\S]*?```/g, " ");
  }

  const words = text.trim().split(/\s+/).filter(Boolean).length;
  if (words <= LIMIT) process.exit(0);

  // מונע לולאה אינסופית: חוסמים לכל היותר MAX_BLOCKS פעמים בתור
  const turnId = String(input.prompt_id || input.session_id || "unknown");
  const stateFile = path.join(
    os.tmpdir(),
    "cc-word-limit-" + turnId.replace(/[^A-Za-z0-9_-]/g, "") + ".json"
  );

  let blocks = 0;
  try {
    blocks = JSON.parse(fs.readFileSync(stateFile, "utf8")).blocks || 0;
  } catch (e) {}

  if (blocks >= MAX_BLOCKS) process.exit(0);

  try {
    fs.writeFileSync(stateFile, JSON.stringify({ blocks: blocks + 1 }));
  } catch (e) {}

  const reason =
    "התשובה שלך היא " + words + " מילים, מעל המגבלה של " + LIMIT + ". " +
    "כתוב אותה מחדש בקצרה. אם היא ארוכה כי לא היית בטוח מה ביקשו ממך " +
    "וכיסית כמה אפשרויות - אל תנחש: שאל שאלת הבהרה אחת קצרה ועצור.";

  process.stdout.write(
    JSON.stringify({
      hookSpecificOutput: {
        hookEventName: "Stop",
        decision: "block",
        reason: reason,
      },
      systemMessage: "Stop hook: נחסם (" + words + "/" + LIMIT + " מילים)",
    })
  );
  process.exit(0);
});

על Mac או Linux, תנו לו הרשאת הרצה:

chmod +x ~/.claude/hooks/word-limit.js

שלב 2: מחברים את ה-hook להגדרות

עכשיו צריך להגיד ל-Claude Code להריץ את הקובץ בכל סיום תשובה. פותחים את קובץ ההגדרות ומוסיפים את הבלוק הבא. אם כבר יש בקובץ תוכן, מוסיפים רק את המפתח hooks ולא מוחקים את השאר.

Windows

הקובץ: C:\Users\YOUR_NAME\.claude\settings.json

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node",
            "args": ["C:\\Users\\YOUR_NAME\\.claude\\hooks\\word-limit.js"],
            "timeout": 10
          }
        ]
      }
    ]
  }
}

Mac / Linux

הקובץ: ~/.claude/settings.json

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node",
            "args": ["/Users/YOUR_NAME/.claude/hooks/word-limit.js"],
            "timeout": 10
          }
        ]
      }
    ]
  }
}

שלוש נקודות שמפילות את רוב האנשים:

  • החליפו את YOUR_NAME בשם המשתמש האמיתי שלכם.
  • כשמשתמשים ב-args, הנתיב חייב להיות מלא. הקיצור ~ לא מתורגם בצורה הזאת.
  • ב-Windows, כל בקסלאש בנתיב נכתב פעמיים בתוך JSON.

שלב 3: מוודאים שזה עובד

הפעילו מחדש את Claude Code, ואז הריצו בתוכו:

/hooks

ייפתח מסך שמראה את כל ה-hooks המוגדרים. אתם אמורים לראות שורה תחת Stop עם התווית User Settings. אם היא שם, החיבור תקין.

בדיקה אמיתית: בקשו מהסוכן משהו שגורר תשובה ארוכה, למשל “תסביר לי לעומק איך עובד מנגנון ההרשאות”. במקום מסה של טקסט, אתם אמורים לראות שהתשובה נחסמת והסוכן מחזיר גרסה קצרה, או שואל שאלת הבהרה.

קיצור דרך: לתת לסוכן להתקין את זה לבד

אם לא בא לכם לגעת בקבצים, אפשר פשוט לבקש. הדביקו לסוכן את המשפט הבא:

“תוסיף לי Stop hook ב-settings.json הגלובלי שלי: סקריפט Node שקורא את last_assistant_message מה-stdin, סופר מילים בלי בלוקים של קוד, ואם יש יותר מ-150 מילים מחזיר JSON עם decision: block וסיבה שמבקשת לקצר או לשאול שאלת הבהרה. תוסיף גם מגן מפני לולאה לפי prompt_id.”

אחרי שהוא מסיים, הריצו /hooks ותוודאו שהשורה מופיעה.

התאמות אישיות

מה לשנותאיך
אורך התשובהשנו את LIMIT בראש הקובץ. 150 זה נוקשה ומצוין לעבודה יומיומית, 300 נוח יותר להסברים.
לספור גם קודהפכו את IGNORE_CODE ל-false. כברירת מחדל בלוקים של קוד לא נספרים, כי אין סיבה להעניש על קוד ארוך.
כמה נסיונות תיקוןMAX_BLOCKS קובע כמה פעמים ה-hook יחסום את אותו תור לפני שהוא מוותר. 2 זה איזון טוב.
רק בפרויקט מסויםשימו את אותו בלוק בקובץ .claude/settings.json שבתוך הפרויקט, במקום בקובץ הגלובלי. הגדרות משני המקומות מתמזגות.
לכבות לרגעהוסיפו disableAllHooks: true לקובץ ההגדרות, או פשוט הוציאו את בלוק ה-Stop.

טיפים מהשטח

  • הכוח האמיתי הוא לא בקיצור אלא בניסוח ה-reason. זה הטקסט היחיד שהסוכן קורא, ולכן שם כדאי להגיד לו במפורש לשאול במקום לנחש.
  • אל תוותרו על מגן הלולאה. בלי MAX_BLOCKS, סוכן שמתעקש על תשובה ארוכה יכול להיתקע במעגל ולשרוף טוקנים.
  • התחילו ממגבלה גבוהה יחסית, למשל 250, ותרדו בהדרגה. קפיצה ישר ל-150 מרגישה חונקת ביום הראשון.
  • ה-hook רץ אצלכם על המחשב עם ההרשאות שלכם. אל תריצו hooks שלא קראתם, בדיוק כמו כל סקריפט אחר.
  • אותו רעיון עובד גם למטרות אחרות: להריץ לינטר בסיום כל תשובה, לחסום סיום כשיש בדיקות שנכשלות, או לשלוח התראה כשהסוכן סיים משימה ארוכה.
  • הקובץ הגלובלי חל על כל הפרויקטים. אם אתם עובדים גם על תיעוד ארוך, שקלו להגדיר אותו ברמת הפרויקט בלבד.

מגבלות שכדאי להכיר

  • ה-hook לא הופך את המודל לחכם יותר. הוא רק לא נותן לו לסיים תור בתשובה מנופחת, ודוחף אותו לשאול.
  • ספירת מילים היא קירוב. תשובה של 149 מילים מלאה בהנחות תעבור.
  • אם הפקודה חורגת מה-timeout שהגדרתם, היא מבוטלת והתור נסגר כרגיל, בלי חסימה.
  • hooks ברמת פרויקט דורשים אישור אמון לתיקייה בפעם הראשונה.
  • מבנה השדות של Hooks מתעדכן מדי פעם. אם משהו מפסיק לעבוד, הדוקומנטציה הרשמית היא מקור האמת.

לינקים

נכתב על ידי

מוביל AI ודאטה בקבוצה עסקית גדולה, מעביר סדנאות ובונה סוכני AI לארגונים.

עודכן לאחרונה:

רוצים שהצוות שלכם יעבוד ככה?

אני עובד עם צוותי פיתוח על Claude Code, סוכני קוד, MCP ותשתיות AI, מהתכנון ועד הייצור.

5,000+ חברים בקהילת Vibe Coding Israel

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

הצטרפות לקבוצה (נפתח בחלון חדש)

המספר מתעדכן ידנית. נכון ל-10/2026.