SSD Nodes Learn 🎉 VPS החל מ־$4.99/חודש
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-07

הגדרת statusLine ב-Claude Code על שרת VPS

למדו כיצד להגדיר statusLine ב-Claude Code כדי להציג את ה-hostname, נתיב התיקייה וענף ה-git. מנעו טעויות קריטיות בעבודה על שרתים מרובים באמצעות סקריפט פשוט ב-settings.json.

מה מציגה שורת הסטטוס של Claude Code

שורת הסטטוס של Claude Code היא שורה המופיעה מתחת לשורת הפקודה ומציגה את הפלט של סקריפט שכתבת. עליך להוסיף בלוק statusLine לתוך settings.json ולהפנות אותו לפקודה מסוימת. Claude Code מריץ את הפקודה הזו, שולח אליה את מצב הסשן כ־JSON ב־standard input, ומדפיס ל־standard output את כל מה שהפקודה כותבת.

זהו כל החוזה. הסקריפט שלך קורא JSON מ־stdin ומדפיס טקסט ל־stdout. הוא רץ על המכונה שלך, ושום דבר ממה שהוא מדפיס לא נשלח למודל, לכן הוא אינו צורך tokens.

במחשב נייד עם פרויקט אחד, מדובר בקישוט בלבד. בשלושה שרתים, מדובר באמצעי בטיחות. כל סשן של Claude Code נראה זהה בכל טרמינל, ולכן ארבעה חלונות SSH ללא תיוג הם הדרך שבה הגירה עלולה להסתיים בשרת הלא נכון. שורת סטטוס שמתחילה בשם המארח (hostname) מונעת את סוג הטעויות הזה.

היכן מוגדרת ההגדרה statusLine בקובץ settings.json

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

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

הערך type הוא תמיד "command". הערך command מורץ דרך shell, לכן הוא יכול להיות נתיב לסקריפט או פקודה פשוטה. ודאו שהחיבור תקין לפני כתיבת סקריפט כלשהו:

{
  "statusLine": {
    "type": "command",
    "command": "hostname -s"
  }
}

הפעילו את Claude Code ושלחו הודעה אחת. השורה מתחת ל-prompt תציג כעת את שם המארח (hostname) הקצר של השרת. אם היא נשארת ריקה, הבעיה היא בהגדרה או בתיבת הדו-שיח של האמון (trust dialog), ולא בסקריפט שלכם. קראו את "מדוע שורת הסטטוס נשארת ריקה" בהמשך.

נכון לאוגוסט 2026 קיימים שלושה מפתחות אופציונליים. padding מוסיף מרווח אופקי בתווים וערך ברירת המחדל שלו הוא 0. refreshInterval מריץ מחדש את הפקודה בכל N שניות בנוסף לטריגרים הרגילים, עם מינימום של 1; השתמשו בכך רק כאשר השורה מציגה שעון או נתון שמשתנה בזמן שהסשן אינו פעיל. hideVimModeIndicator מדכא את הטקסט המובנה -- INSERT -- כאשר הסקריפט שלכם כבר מרנדר את מצב ה-vim.

איזה נתונים מקבל הסקריפט של שורת הסטטוס?

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

cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.sh

הפנו את statusLine.command לקובץ הזה, התחילו סשן, ושלחו הודעה אחת. ה-bar קורא את captured. כעת בדקו מה הגיע:

jq . /tmp/statusline-input.json

כעת יש לכם את המבנה המדויק עבור ה-build שלכם, ותוכלו לחזור על הפעולה בכל פעם שעדכון משנה משהו.

החלקים היציבים, כפי שתועדו באוגוסט 2026, הם אובייקטים מקוננים ולא מפתחות שטוחים. model מכיל את id ואת display_name. workspace מכיל את current_dir ואת project_dir: current_dir הוא המקום שבו הסשן נמצא כעת, project_dir הוא המקום שבו הוא הופעל, והשניים נבדלים ברגע שספריית העבודה משתנה במהלך הסשן. ה-cwd ברמה העליונה נושא את אותו ערך כמו workspace.current_dir. context_window מכיל ספירות אסימונים (tokens) בתוספת used_percentage מחושב מראש. cost מכיל את total_cost_usd ומוני משך זמן. session_id יציב לאורך חיי הסשן וייחודי בין סשנים, מה שחשוב עבור caching מאוחר יותר.

שלושה כללים שומרים על סקריפט פעיל לאורך שינויי סכימה.

חלק מהמפתחות חסרים, לא null. vim, agent, pr, worktree ו-effort מופיעים רק כאשר התכונה התואמת פעילה. קריאת .vim.mode עם jq -r בזמן שמצב vim כבוי מדפיסה את המחרוזת המילולית null, וה-bar שלכם מציג null לקורא. הוסיפו את // empty לכל selector, כך שמפתח חסר לא ידפיס דבר.

חלק מהערכים הם null בשלבים מוקדמים. context_window.used_percentage ו-context_window.current_usage הם null לפני תגובת ה-API הראשונה, ו-current_usage חוזר ל-null אחרי /compact עד שהקריאה הבאה מאכלסת אותו מחדש. אחוז הקשר (context) ב-bar דורש לכן את // 0, אחרת הוא יציג null במהלך השניות הראשונות של כל סשן. לפני שאתם מציבים את המספר הזה ב-bar, כדאי לדעת כיצד חלון ההקשר מתמלא בפועל.

ענף ה-git אינו נמצא ב-JSON. אף שדה לא מדווח עליו. כל ענף ב-bar שלכם מגיע מהסקריפט שלכם שמריץ את git בעצמו.

סקריפט לשורת סטטוס שמתדרדר בחן במקום לקרוס

זוהי גרסת ה-copy-paste. הסקריפט מדפיס את שם המארח (hostname), ספריית העבודה, ענף ה-git ושם הדגם. לכל שדה יש מנגנון גיבוי, כך שאפילו אובייקט JSON ריק יפיק שורה שמישה.

#!/bin/bash
# ~/.claude/statusline.sh
input=$(cat)

# Read one field. Prints nothing when the key is missing or null.
field() { printf '%s' "$input" | jq -r "$1 // empty" 2>/dev/null; }

HOST=$(hostname -s 2>/dev/null)
[ -z "$HOST" ] && HOST="host"

DIR=$(field '.workspace.current_dir')
[ -z "$DIR" ] && DIR=$(field '.cwd')
[ -z "$DIR" ] && DIR="$PWD"

MODEL=$(field '.model.display_name')
[ -z "$MODEL" ] && MODEL="claude"

SHORT="$DIR"
if [ -n "$HOME" ]; then
  case "$DIR" in
    "$HOME") SHORT="~" ;;
    "$HOME"/*) SHORT="~/${DIR#"$HOME"/}" ;;
  esac
fi

BRANCH=""
if git -C "$DIR" rev-parse --git-dir >/dev/null 2>&1; then
  BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
  [ -z "$BRANCH" ] && BRANCH="detached"
fi

CYAN=$'\033[36m'
YELLOW=$'\033[33m'
DIM=$'\033[2m'
RESET=$'\033[0m'

LINE="${CYAN}${HOST}${RESET} ${SHORT}"
[ -n "$BRANCH" ] && LINE="${LINE} ${YELLOW}${BRANCH}${RESET}"
LINE="${LINE} ${DIM}${MODEL}${RESET}"

printf '%s\n' "$LINE"

כל קריאה עוברת דרך field, שמוסיף // empty, כך שמפתח ששונה שמו או הוסר מפיק מחרוזת ריקה והשורה הבאה מספקת ערך ברירת מחדל. הספרייה נסוגה מ-workspace.current_dir ל-cwd ולבסוף ל-$PWD. הענף נלקח מ-git -C "$DIR" במקום מ-git גולמי, כך שהענף תמיד תואם לספרייה שמוצגת בשורת המצב.

שמרו את הקובץ והפכו אותו לניתן להרצה:

chmod +x ~/.claude/statusline.sh

סיבית ההרצה (execute bit) אינה אופציונלית. Claude Code מריץ את הפקודה דרך shell, לכן סקריפט ללא +x ייכשל עם Permission denied, לא יפיק stdout, והשורה תישאר ריקה ללא שגיאה גלויה.

jq מנתח JSON בשורת הפקודה ואינו מותקן בשרת Ubuntu חדש:

sudo apt update && sudo apt install -y jq

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

בדקו את הסקריפט לפני שתסמכו עליו

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

echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.sh

תקבלו את שם המארח (hostname), לאחר מכן את /srv/api, ואז את Opus. שום ענף (branch) לא יופיע, כיוון ש-/srv/api במכונה שלכם כנראה אינו מאגר git.

שנית, בצעו את בדיקת ה-degradation, שהיא הבדיקה שאנשים נוטים לדלג עליה:

echo '{}' | ~/.claude/statusline.sh

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

מה עליך לראות

שורת הסטטוס מוצגת בשורה נפרדת מעל תגיות ה-footer המובנות ואינה מחליפה אותן. בהגדרה תקינה, השורה מורכבת מהרכיבים הבאים: שם המארח (hostname) המקוצר בצבע ציאן, נתיב ספריית העבודה הנוכחית כאשר ספריית הבית מקוצרת ל-~, שם הענף (branch) בצהוב כאשר הספרייה היא מאגר git, ולאחריו שם המודל בטקסט עמום. התוצאה צריכה להיראות בדומה ל-web-01 ~/api main Opus, עם ארבעת החלקים הללו צבועים.

השורה מריצה מחדש את הסקריפט שלך בכל תחילת סשן (כולל חידוש סשן קיים), עם הגעת הודעת עוזר חדשה, לאחר סיום /compact, בעת שינוי מצב הרשאות, בעת מעבר בין מצבי vim, ובתקתוק refreshInterval אם הגדרת כזה. עדכונים עוברים תהליך של debounce ב-300 ms, כך שרצף מהיר של שינויים מריץ את הסקריפט פעם אחת בלבד. השורה מוסתרת בזמן השלמה אוטומטית, תפריט העזרה והנחיות הרשאה, וחוזרת להופיע לאחר מכן.

מדוע שם המארח (hostname) חייב להופיע ראשון

כאשר מריצים סוכנים על יותר משרת אחד, הטרמינל הוא המקור היחיד שמעיד על המיקום שלכם, וטרמינלים עלולים להטעות. פתיחת חיבור ssh נוסף מתוך חלונית tmux גורמת לעיתים קרובות לכך שכותרת החלון נשארת עם השם הישן, כיוון שהכותרת נקבעת על ידי shell שלא "יודע" שהתבצע מעבר. אם תעזבו את Claude Code רץ בתוך session מנותק של tmux על גבי VPS ותתחברו אליו מחדש יום לאחר מכן, שום דבר על המסך לא יבדיל בין שרת ה-build לבין שרת ה-production.

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

העניקו לכל שרת צבע משלו כדי שתזהו אותו עוד לפני שתקראו את הטקסט. הוסיפו שתי שורות מעל ההשמה של LINE=:

CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")

לאחר מכן השתמשו ב-${HOST_COLOR} במקום ב-${CYAN}. הפקודה cksum מדפיסה checksum של שם המארח, כך ששם נתון תמיד ימופה לאותו צבע בטווח שבין 31 ל-36 (אדום עד ציאן). העתיקו את אותו סקריפט לכל שרת, וכל אחד מהם יתייג את עצמו.

התיקייה (directory) ראויה למקומה מאותה סיבה. /srv/api ו-/srv/api-staging נמצאים במרחק הקשה אחת זה מזה בפקודת ssh, אך ההבדל בתוצאה ביניהם הוא אירוע חמור. המודל וה-branch הם שני הפרמטרים הנוספים ששווים את המקום: המודל מציין באיזה session המשכתם לעבוד, וה-branch מציין אם הסוכן עומד לבצע commit ל-main.

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

שמירה על מהירות הסקריפט

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

כל קריאה ל-jq עולה כמה מילי-שניות. git הוא החלק שהופך לאיטי: git status במאגר (repository) גדול עם cache קר לוקח מאות מילי-שניות. הסקריפט שלעיל נמנע מ-git status במכוון וקורא ל-git branch --show-current, שקורא את .git/HEAD ומחזיר תשובה באופן מיידי.

אם אתם מוסיפים פעולה כבדה יותר, בצעו לה caching לקובץ ורעננו אותו בכל כמה שניות. השתמשו ב-session כמפתח לקובץ:

CACHE="/tmp/statusline-$(field '.session_id')"

השתמשו ב-session_id, לא ב-$$. $$ הוא מזהה התהליך (PID) של הסקריפט שלכם, והוא שונה בכל הרצה; לכן, cache שמבוסס עליו לעולם לא יבצע hit ואתם תשלמו את המחיר המלא בכל פעם. session_id הוא יציב לכל אורך ה-session ושונה בין sessions שונים, כך ששני sessions של Claude Code בשני מאגרים שונים לא יוכלו לקרוא את שם ה-branch השמור של האחר.

מגבלה נוספת שכדאי להכיר: tput cols לא עובד בתוך סקריפט של statusline. Claude Code לוכד את הפלט במקום לחבר את הסקריפט שלכם ל-terminal, ולכן לזיהוי הרוחב אין מה למדוד. החל מגרסה v2.1.153 ומעלה, Claude Code מגדיר את משתני הסביבה COLUMNS ו-LINES לפני הרצת הפקודה, לכן קראו את $COLUMNS כאשר עליכם להחליט כמה להדפיס.

מדוע שורת הסטטוס נשארת ריקה

לא מופיע דבר. בדקו את הרשאת ההרצה (execute bit) באמצעות ls -l ~/.claude/statusline.sh, ולאחר מכן הריצו את הסקריפט ידנית עם קלט הדמה שלעיל. אם הוא מדפיס שורה ב-shell אך לא ב-Claude Code, התחילו עם claude --debug, שמתעד את קוד היציאה ואת ה-stderr של הרצת שורת הסטטוס הראשונה בסשן.

יומן הניפוי (debug log) מציג Status line command skipped: workspace trust not accepted. שורת הסטטוס מריצה פקודת shell, ולכן היא כפופה לאותו מנגנון אמון סביבת עבודה (workspace trust) כמו hooks. עד שלא תאשרו את תיבת הדו-שיח של האמון עבור אותה ספרייה, הפקודה לא תרוץ. זה נפוץ ב-VPS, שבו כל clone חדש הוא ספרייה ש-Claude Code טרם הכיר. הפעילו מחדש את Claude Code באותה ספרייה ואשרו את הדו-שיח.

הכל ריק ו-disableAllHooks מוגדר. "disableAllHooks": true ב-settings.json משבית גם את שורת הסטטוס, כיוון שמדובר באותו מנגנון הרצת shell. הסירו הגדרה זו או שנו אותה ל-false.

השורה מדפיסה null. בורר (selector) של jq הגיע למפתח חסר או null, ו-jq -r מדפיס null כארבעת התווים null. הוסיפו // empty עבור טקסט ו-// 0 עבור מספרים.

השורה מתרוקנת מיד לאחר עריכת הסקריפט. פקודה שמסתיימת בקוד שאינו אפס, או שאינה מדפיסה דבר, מרוקנת את השורה. הסיבה הנפוצה היא שורה אחרונה כמו [ -n "$BRANCH" ] && LINE="...", שמחזירה 1 כאשר הענף ריק וגוררת איתה את קוד היציאה של כל הסקריפט. השאירו את printf אחרון, או הוסיפו exit 0.

קודי בריחה (escape codes) מוצגים כטקסט מילולי כגון \e]8;; על הבר. השתמשו ב-printf '%b' במקום ב-echo -e. קישורי OSC 8 לחיצים דורשים גם טרמינל שתומך בהם, ו-tmux או SSH עלולים להסיר את הרצפים הללו, לכן צבע פשוט הוא הבחירה הבטוחה יותר במכונה מרוחקת.

הצד הימני של השורה קטוע. התראות מערכת ומונה ה-tokens במצב verbose חולקים את אותה שורה מצד ימין, וטרמינל צר גורם לאובדן החפיפה. שמרו על פלט קצר. לחישוב מדויק של השימוש במקום מספר על הבר, ראו כיצד Claude Code סופר tokens.

FAQ

היכן מוגדרת הגדרת ה-statusline של Claude Code?

ב-settings.json, כבלוק statusLine שבו type מוגדר ל-"command" ו-command מוגדר לנתיב של סקריפט או לפקודת shell. הגדרות המשתמש נמצאות ב-~/.claude/settings.json וחלות על כל פרויקט באותה מכונה. הגדרות פרויקט נמצאות ב-.claude/settings.json בתוך ה-repository, והן גוברות על הגדרות המשתמש עבור אותה ספרייה. ההגדרות נטענות מחדש באופן אוטומטי, אך שינוי יבוא לידי ביטוי רק בטריגר העדכון הבא, כגון ההודעה הבאה שלכם.

מדוע ה-statusline של Claude Code ריק?

ארבע סיבות מכסות כמעט את כל המקרים. הסקריפט חסר את הרשאת ההרצה (execute bit), ולכן ה-shell מחזיר Permission denied ושום דבר לא מגיע ל-stdout. תיבת הדו-שיח של אמון בסביבת העבודה (workspace trust) לא אושרה, ו-claude --debug מתעד ב-Status line command skipped: workspace trust not accepted. ה-disableAllHooks מוגדר כ-true, מה שמשבית את ה-statusline תחת אותה הגבלה. לחלופין, הסקריפט מסיים את פעולתו עם קוד שגיאה (non-zero), מה שמרוקן את השורה. בדקו זאת ידנית תחילה: echo '{}' | ~/.claude/statusline.sh חייב להדפיס משהו.

האם ה-JSON של ה-statusline כולל את ה-git branch?

לא. ה-JSON נושא מצב session כגון המודל, ספריות ה-workspace, נתוני חלון ההקשר (context window) ועלות. שום דבר בו לא מדווח על git. ענף (branch) שמופיע בשורת המצב שלכם מגיע מסקריפט אישי שקורא ל-git branch --show-current. העבירו את הספרייה מה-JSON באמצעות git -C "$DIR", כך שהענף תמיד יתאים לספרייה שהשורה מציגה.

האם ה-statusline צורך tokens או מאט את ה-session?

הוא לא צורך tokens, כיוון שהסקריפט רץ מקומית והפלט שלו לעולם לא נשלח למודל. המהירות היא באחריותכם. הפקודה רצה בכל הודעה של ה-assistant עם debounce של 300 מילי-שניות, ו-Claude Code מבטל ריצה פעילה כאשר מגיע עדכון חדש, כך שסקריפט שלוקח שנייה שלמה יציג טקסט לא מעודכן. הימנעו מ-git status ב-repositories גדולים, ובצעו caching לכל פעולה איטית בקובץ שמזוהה לפי session_id.

כיצד אציג statusline שונה בכל שרת?

השתמשו בסקריפט אחד ותנו לו לקרוא את פרטי המכונה. הסקריפט לעיל מדפיס את $HOSTNAME עם hostname -s כברירת מחדל, כך שאותו קובץ שמועתק לכל שרת מתייג כל אחד מהם כראוי, וטריק הצבע לפי checksum מעניק לכל hostname צבע משלו. אם שרת מסוים דורש פריסה שונה, הציבו בלוק statusLine בהגדרות הפרויקט של ה-repository שבו אתם עובדים באותה מכונה, שכן הגדרות פרויקט גוברות על הגדרות משתמש עבור אותה ספרייה.