מדריך גרוק CLI בעברית

תיעוד 41

ניהול סשנים

גרוק שומר כל שיחה לדיסק באופן אוטומטי. בין אם עובדים ב-TUI, במצב headless, או דרך agent stdio, גרוק מתעד את החילוף כסשן. אפשר לחדש אותו, להריץ אותו אחורה, או לדחוס אותו. המסמך הזה מתאר איך לנהל סשנים.


#מה הם סשנים

סשן הוא שיחה מתמשכת עם היסטוריה מלאה. הוא כולל:

  • כל הפרומפטים של המשתמש ותשובות הסוכן
  • קריאות לכלים והתוצאות שלהן
  • מצב רשימת TODO/משימות
  • נקודות rewind לביטול תורות מאוחרים יותר
  • שימוש בטוקנים ומספרי תורות
  • סשנים של תת-סוכנים (כשזה מופעל)

סשנים מזוהים באמצעות מזהה סשן ייחודי (UUIDv7 כשגרוק מייצר אותו. לקוח יכול לספק מזהה משלו עם -s) ונשמרים בדיסק תחת ~/.grok/sessions/. הגדר את GROK_HOME כדי לדרוס את תיקיית הבסיס. כשהוא לא מוגדר, גרוק משתמש ב-~/.grok.


#פריסת האחסון

גרוק שומר כל סשן בתיקייה משלו, מקובץ לפי תיקיית העבודה. הוא מקודד את תיקיית העבודה ב-URL כדי לתת שם לקבוצה. כשהשם המקודד חורג מ-255 בתים, הוא משתמש במקום זאת ב-slug ובגיבוב ורושם את הנתיב המקורי בקובץ .cwd בתוך הקבוצה.

~/.grok/sessions/<encoded-cwd>/<session-id>/
  summary.json            # metadata: summary/title, timestamps, model ID, message counts
  updates.jsonl           # ACP session update stream (conversation + tool calls)
  chat_history.jsonl      # raw chat messages sent to the model
  system_prompt.txt       # the rendered system prompt, as sent to the model
  prompt_context.json     # the inputs the system prompt was rendered from
  tool_definitions.json   # function tools sent on the latest model call (no MCP server__tool entries)
  plan.json               # TODO/task list state
  rewind_points.jsonl     # rewind points for /rewind undo
  signals.json            # session signals (token usage, tool/turn counters)
  feedback.jsonl          # user feedback and ratings
  compaction_checkpoints/ # saved state from compaction (manual or auto)
  subagents/              # per-subagent metadata (meta.json); the child sessions live in the normal sessions tree

summary.json הוא רשומת האינדקס. הוא רושם את תקציר הסשן ואת הכותרת שנוצרה, את מזהה המודל, את חותמות הזמן של היצירה והעדכון, את ספירות ההודעות, והפניה לסשן אב עבור סשנים שפוצלו או שוחזרו. הוא גם רושם את תקציר התור האחרון העדכני ואת תמצית הסשן כדי שמשטחי רשימה יוכלו להציג אותם. updates.jsonl הוא יומן השיחה הסמכותי שמניע את /resume ואת שחזור הסשן. tool_definitions.json משמיט רשומות MCP מסוג server__tool כי המודל מגיע אליהן דרך search_tool ו-use_tool, שכן רשומים. סיכומי טוקנים ועלות לכל תור זמינים דרך grok usage.

#כותרות סשן

כותרת הסשן שמוצגת בלוח הבקרה וב-/resume נוצרת אוטומטית מהשיחה. המסגרת של הפרומפט מציגה כותרת רק אחרי /rename ידני, לצד הכיתוב Stashed כשטיוטה נשמרה בצד. יצירת הכותרת מתחילה מיד אחרי הפרומפט הראשון כדי שלסשן תמיד תהיה כותרת, ואז הכותרת נוצרת מחדש מכל השיחה בכמה תורות מוקדמים ומוקפאת. זה מאפשר לכותרת לעבור מעבר לפרומפט ראשון מעורפל ולשקף במה הסשן באמת עוסק, ולהישאר יציבה אחר כך כדי שלא תאבד את המעקב אחרי הסשנים. /rename ידני תמיד מנצח: אחרי שמשנים שם לסשן, יצירה אוטומטית לעולם לא דורסת אותו. השתמש ב-/rename --auto כדי להחזיר את הכותרת ליצירה אוטומטית.


#התחלה וסיום של סשנים

#סשן חדש

ה-TUI יוצר סשן חדש בכל הפעלה. כדי להתחיל במפורש מחדש באמצע סשן:

/new

זה מנקה את ההקשר הנוכחי ומתחיל שיחה חדשה. כינוי: /clear.

#יציאה

סיים את הסשן וצא מגרוק:

/quit

כינוי: /exit. כדי לעזוב את הסשן הנוכחי אבל להישאר בגרוק, השתמש ב-/home כדי לחזור למסך הפתיחה.

#מחיקת הסשן הנוכחי

/delete

מבקש אישור, ואז מסיר לצמיתות את היסטוריית הסשן. חוזר למסך הפתיחה, או ללוח הבקרה כשפתחת את הסשן מלוח הבקרה. מתוך /resume או רשימת הסשנים במסך הפתיחה, לחץ d ואז y. ברשימת לוח הסוכנים, Ctrl+X פעמיים (או ריחוף מעל [✗]) מוחק לצמיתות.


#חידוש סשנים

#מתוך ה-TUI

השתמש בפקודה /resume כדי לעיין בסשנים קודמים ולחדש אותם:

/resume [session-id-or-title]

בלי ארגומנט, זה פותח בורר סשנים שמציג סשנים אחרונים עבור סביבת העבודה הנוכחית. בחר סשן כדי לחדש אותו. מזהה סשן, או כותרת שבוחרת בדיוק סשן אחד לפי כללי grok --resume, מחדש את הסשן ישירות. אם גרוק הופעל עם --restore-code, המזהה של סשן מרוחק אומר למה במקום זאת כשהסשן הזה שוחזר בתיקייה הזו: כמו עם grok --resume, הקוד של סשן מרוחק נמשך רק לתוך worktree. במסלול ה-daemon, אם הסשן שה-daemon מוצא הופעל תחת פרופיל sandbox אחר, /resume אומר למה במקום זאת, אלא אם requirements.toml נועל את הפרופיל (ראה חידוש סשנים במצב sandbox). ה-daemon מחפש במאגר הסשנים של הפרופיל שגרוק רץ תחתיו: strict וכל פרופיל מותאם שומרים מאגר משלהם, ושאר הפרופילים המובנים חולקים מאגר אחד (ראה פרופילים מובנים). כל דבר אחר (כותרת שכמה סשנים חולקים, כותרת שאין לאף סשן, מזהה שלא נמצא, סשן שנשמר במאגר של פרופיל אחר, או סשן שאי אפשר לחדש מהתיקייה הזו) פותח את הבורר כשהטקסט שלך כבר מוקלד כחיפוש שלו. במצב צ'אט, /resume <text> תמיד פותח את הבורר כך, גם עבור מזהה סשן. בלוח הבקרה של סביבת העבודה, /resume <text> פותח את הבורר של לוח הבקרה מסונן לפי הטקסט במקום זאת.

הקלדה בבורר מצמצמת את הסשנים שהוא כבר הציג לאלה שמזהה הסשן או הכותרת שלהם מכילים את מה שמקלידים, או שהכותרת שלהם מכילה כל מילה שמקלידים בתחילת אחת מהמילים שלה, בכל סדר ובלי תלות במה שמפריד ביניהן, כך ש-login-fix שומר "Fix login bug" שמופיע ברשימה. סינית, יפנית, תאית וכתבים אחרים שנכתבים בלי רווחים בין מילים מריצים כמה מילים לאחת, כך שמילה שמקלידים יכולה גם להתחיל בתוך אחת ממילות הכותרת, בתו של כתב כזה או מיד אחריו: 登录 问题 שומר "修复登录问题" שמופיע ברשימה, ו-rust 重写 שומר "使用Rust重写" אבל לא "使用Trust重写". כשכל מילה שמקלידים היא תו יחיד מחוץ לכתבים האלה, כמו ב-c++ או C#, כותרת חייבת להכיל את הטקסט כפי שהוקלד או להכיל את אותן מילים באותו סדר, כך ש-C# שומר "C++" שמופיע ברשימה אבל לא "C notes". הוא גם מחפש בתוכן השיחה בזמן ההקלדה. התאמות תוכן מופיעות תחת כותרת "Extended search results". לחץ Ctrl+/ כדי לחפש מיד בלי ההשהיה הקצרה.

עבור הסשנים החיים ברמה העליונה ב-pager הזה (הורה ופיצולים): מעבר, שינוי שם, הצצה, שיגור, או סגירה, השתמש ב-לוח הסוכנים: /dashboard (כינויים /sessions, /agents-dashboard) או Ctrl+\.

#משורת הפקודה

חדש סשן מסוים לפי מזהה או כותרת:

grok --resume <session-id-or-title>

ערך שאינו מזהה סשן מותאם מול כותרות סשנים של התיקייה הנוכחית, בלי התחשבות ברישיות האותיות (השוואת אותיות קטנות פשוטה), וזה נוח אחרי /rename. כשאף כותרת לא תואמת במדויק, גם כותרת עם אותן מילים באותו סדר תואמת, בלי תלות במה שמפריד ביניהן, כך ש-grok --resume fix-login-bug מוצא את "Fix login bug". תחום במרכאות שם שמכיל רווחים. אם כמה סשנים תואמים, סשן יחיד ששמו שונה ידנית מנצח כפילויות שנוצרו אוטומטית. אחרת הפקודה נכשלת ומציגה עד עשרה התאמות, החדש ביותר ראשון, כל אחד עם המזהה, הכותרת, וזמן העדכון האחרון שלו. כשאף כותרת לא תואמת, השגיאה מציעה עד חמש כותרות דומות (כל מילה שהקלדת מתחילה מילה בכותרת, או מתחילה בתוך מילה בתו של כתב שנכתב בלי רווחים בין מילים או מיד אחרי תו כזה) עם המזהים שלהן. ערכים בצורת UUID תמיד מטופלים כמזהי סשן, אף פעם לא ככותרות. סקריפטים צריכים להעדיף מזהים.

במסלול ה-daemon, מזהה סשן מוצא גם סשן שה-daemon מחזיק באותו מקום ב-checkout הראשי של המאגר או באחד מ-worktree של grok -w (בשורש שלו, או בתת-התיקייה שממנה מריצים), ופותח אותו בתיקייה הזו. כך גם לגבי סשן שגרוק קודם או ה-Cursor CLI שמרו שם.

הרץ grok --resume בלי ערך כדי לחדש את הסשן האחרון ביותר עבור התיקייה הנוכחית.

במסלול ה-daemon, כש-grok --resume או grok -c לא מוצאים סשן לפתיחה (אין התאמה, כותרת שכמה סשנים חולקים, סשן שנמחק, או חיפוש שפג הזמן שלו), גרוק נשאר פתוח: הוא מראה למה בסשן חדש ופותח את בורר הסשנים כשהטקסט שלך כבר מוקלד כחיפוש שלו. בחר שם סשן, או סגור את הבורר כדי להמשיך לעבוד בסשן החדש. עם --fork-session או -w, הסשן שבוחרים שם מפוצל, או מחודש ב-worktree חדש, כפי שהדגל מבקש. הוא אף פעם לא מחודש במקום. אם הוא מצא את הסשן אבל לא הצליח לפתוח אותו (הוא הופעל תחת פרופיל sandbox אחר, גרוק אחר מחזיק אותו פתוח, שחזור סשן מרוחק נכשל, או הפיצול או ה-worktree נכשלו), הוא מראה למה בסשן חדש בלי הבורר. שום דבר שהעברת בשורת הפקודה או הקלדת בזמן שהחיפוש רץ לא נשלח: פרומפט אחד חוזר ל-composer של הסשן החדש, ויותר מזה מוצגים שם כלא נשלחו. אם רשימת הסשנים המקומיים של ה-daemon (צ'אטים של Cursor CLI וסשנים קודמים של גרוק) חלקית, למשל כי בתיקייה יש יותר מדי מהם, grok -c עדיין פותח את הסשן החדש ביותר שברשימה, עם או בלי --fork-session או -w.

#ממסך הפתיחה

כשמפעילים את grok, מסך הפתיחה מציג סשנים אחרונים עבור התיקייה הנוכחית. בחר אחד כדי לחדש אותו.


#פיצול ושינוי שם של סשנים

#פיצול

פצל את הסשן הנוכחי לסוכן עמית שמתחיל מעותק של השיחה:

/fork [--worktree|--no-worktree] [directive]

העבר directive אופציונלי כדי לקבוע את הפרומפט הראשון של הסשן החדש. השתמש ב---worktree או --no-worktree כדי לבחור אם הפיצול רץ ב-worktree חדש של git. השמט את שניהם כדי להישאל בכל פעם. הדגל --at <turn> לא נתמך בגרסה הזו.

/fork שומר את המודל ואת ה-effort של המקור שלו, גם כשגרוק הופעל עם -m או --effort.

#שינוי שם

שנה את כותרת הסשן הנוכחי:

/rename <title>
/rename --auto

כינוי: /title. /rename --auto מנקה כותרת ידנית ומפעיל מחדש כותרת אוטומטית.


#הפקודה /rewind

/rewind (כינוי /undo) מריץ את השיחה אחורה לתור מוקדם יותר, ומשמיט תורות מאוחרים יותר. שינויי קבצים שנעשו אחרי התור הזה נשארים כמו שהם בדיסק.

/rewind
/undo

כשמריצים /rewind או /undo (או לוחצים Esc Esc בתוך 800ms בזמן סרק עם פרומפט ריק והודעות שיחה), גרוק:

  1. מציג רשימה של נקודות rewind (אחת לכל פרומפט משתמש)
  2. נותן לבחור לאיזו נקודה להריץ אחורה
  3. חותך את היסטוריית השיחה עד לנקודה הזו

כש-Confirm before rewind פועל (ברירת המחדל ב-/settings), כל בחירה מבקשת אישור (Yes / Yes, and don't ask again / No). Yes, and don't ask again מכבה את ההגדרה הזו. כשההגדרה כבויה, הבחירות רצות מיד.

חשוב: /rewind לא משחזר קבצים בדיסק. רק היסטוריית השיחה נחתכת.


#הפקודה /compact

/compact דוחס את היסטוריית השיחה כדי לחסוך מקום בחלון ההקשר. השתמש בו בסשנים ארוכים שבהם הודעות מוקדמות כבר לא רלוונטיות.

/compact

#דחיסה אוטומטית

גרוק דוחס את השיחה אוטומטית כשחלון ההקשר מתקרב לגבול שלו. תראה התראה כשדחיסה אוטומטית מופעלת. ההגדרה context_window בתצורת המודל שלך שולטת מתי הסף הזה מושג.


#הפקודה /session-info

הצג פרטים על הסשן הנוכחי:

/session-info

זה מציג:

  • כותרת סשן (כשהיא מוגדרת)
  • גרסת ה-shell
  • שיטת אימות (OAuth מול מפתח API. סשנים עם מפתח API גם מציעים grok login עבור SuperGrok)
  • מזהה סשן
  • תיקיית עבודה
  • מודל (עם גיבוב מודל עבור מודלי קידוד)
  • backend של ה-API ופרופיל sandbox (כשהם מוגדרים)
  • שימוש בחלון ההקשר (טוקנים בשימוש וסה"כ, עם האחוז שבשימוש)

בלשונית פרטי הסשן, לחץ על ערך כדי להעתיק אותו, או גרור כדי לבחור טווח (אותה הדגשה כמו במציג הכלים). c מעתיק את מזהה הסשן ו-y מעתיק את כל הבלוק. ההעתקה משתמשת באותו מסלול לוח גזירים כמו שאר גרוק, כולל grok wrap.


#ניהול סשנים ב-headless

במצב headless, מנהלים סשנים דרך דגלי שורת פקודה:

# New session each time (default)
grok -p "Hello"

# Resume an existing session by ID or title (errors if it does not exist)
grok -p "Continue where we left off" -r <session-id-or-title>

# Continue the most recent session in the current directory
grok -p "What were we doing?" -c

במצב headless, חדש סשן קיים עם -r/--resume, שנכשל אם הסשן לא קיים, או המשך את הסשן האחרון ביותר בתיקייה הנוכחית עם -c/--continue. ערך שאינו מזהה מותאם מול כותרות סשנים של התיקייה הנוכחית, בלי התחשבות ברישיות האותיות. בלי התאמה מדויקת, גם אותן מילים שמחוברות במפרידים כלשהם תואמות, כך ש--r fix-login-bug מוצא את "Fix login bug" (התאמה יחידה ששמה שונה ידנית מנצחת בין כפילויות. כפילויות שנותרות נכשלות עם עד עשרה מהן, החדש ביותר ראשון, עם מזהים וזמני עדכון אחרונים. החטאה מציעה עד חמש כותרות דומות עם המזהים שלהן. ערכים בצורת UUID תמיד הולכים במסלול המזהה). סקריפטים צריכים להעביר ל--r את מזהה הסשן מפלט JSON (ראה בהמשך).

השתמש ב--s/--session-id רק כדי ליצור סשן חדש עם UUID (נכשל אם הערך אינו UUID, או אם למזהה הזה כבר יש סשן תחת תיקיית סשן היעד). הוא לא מחדש סשן קיים: זו הייתה התנהגות ה-upsert הנסתרת הישנה. השתמש ב--r/-c במקום זאת. שלב -s עם -r/-c רק כשמעבירים גם --fork-session (מפצל היסטוריה למזהה חדש. -s אופציונלי נותן שם ל-UUID של הילד). זה תואם למודל נגד הדריסה של Claude Code (בדיקה מקדימה של הלקוח תחת ה-cwd של הכתיבה. שימוש עוקב אמין, ואותו מזהה במקביל הוא best-effort).

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

grok -p "Hello" --output-format json | jq -r '.sessionId'

#ניהול סשנים ב-agent stdio

כשבונים עם ACP, סשנים מנוהלים דרך מתודות פרוטוקול:

// Create new session
const { sessionId } = await connection.request("session/new", {
  cwd: "/path/to/project",
  mcpServers: [],
});

// Load existing session
await connection.request("session/load", {
  sessionId: "existing-session-id",
  cwd: "/path/to/project",
  mcpServers: [],
});

// Change a live option (model or reasoning_effort).
// session/new and session/load already return the typed configOptions list.
await connection.request("session/set_config_option", {
  sessionId,
  configId: "model",
  value: { value: "grok-4.6" },
});

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


#פקודת המשנה grok sessions

הצג או חפש סשנים משורת הפקודה. grok sessions דורש פקודת משנה:

# List recent sessions for the current directory
grok sessions list

# Limit the number of results (default 20)
grok sessions list --limit 50

# Search sessions by keyword (matches titles and prompts)
grok sessions search "rate limit"

grok sessions list מציג סשנים עבור תיקיית העבודה הנוכחית, מקובצים לפי תווית worktree. כל שורה מציגה את מזהה הסשן, את תאריכי היצירה והעדכון, את סטטוס המקור, ואת התקציר. grok sessions search משלב אינדקס SQLite מקומי עם תוצאות מרוחקות.


#פקודת המשנה grok usage

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

# Your plan's usage limit, on the daemon route
grok usage

# Session totals plus every recorded turn
grok usage <session-id>

# One turn
grok usage <session-id> 3

בלי מזהה סשן, grok usage קורא את השימוש של התוכנית שלך משירות הרקע של גרוק, במסלול ה-daemon. שירות רקע ישן מדי מכדי לדווח על שימוש גורם ל-grok usage לומר ששירות הרקע של גרוק עדיין לא יכול לדווח על שימוש, ויוצא עם קוד 1.

במסלול ה-daemon, grok usage בלי מזהה סשן ובלי התחברות אומר שאינך מחובר, ב-stderr, ויוצא עם קוד 1 בלי כלום ב-stdout. במסלול ה-shell, grok usage בלי מזהה סשן מדפיס Error: `grok usage` can't show your plan's usage here yet. Run /usage inside grok instead. ב-stderr ויוצא עם קוד 1, בלי לקרוא את החשבון שלך. /usage ב-TUI מציג שם את השימוש של התוכנית. פריסה שמודדת את התורות שלה בעצמה מדפיסה Usage limits are managed by your team. בכל אחד מהמסלולים, ויוצאת עם קוד 0.

עם מזהה סשן, הפלט הוא JSON עם sessionId, updatedAt, session, ו-turns. תור מסוים משתמש באותה מעטפת עם איבר אחד ב-turns. סיכומי הסשן מכסים את כל השיחה, כולל היסטוריה שעברה בירושה מחידוש או מפיצול. costUsdTicks הוא 10¹⁰ תיקים לכל USD (חלק ב-1e10 כדי לקבל דולרים). מספר תור חסר הוא שגיאה.

#סשנים של worktree

כשעובדים עם subagents או עם פיצולי סשן, Grok יכול ליצור worktree מבודדים של git לכל סשן. לכל worktree יש עותק משלו של ספריית העבודה, ולכן שינויי קבצים בסשן אחד לא משפיעים על סשן אחר.

סשנים של worktree מנוהלים פנימית דרך שיטות ההרחבה x.ai/git/worktree/*. פעולות מרכזיות:

  • Create: יצירת worktree חדש לסשן מבודד
  • Apply: מיזוג שינויי ה-worktree בחזרה לספריית העבודה הראשית
  • Remove: ניקוי worktree כשהסשן הסתיים

מחדשים סשן ב-worktree חדש עם grok -w -r <session-id>.

worktree גם מחיל את כללי deny ו-ask של קובץ .claude/settings.local.json שמתעלמים ממנו ב-checkout הראשי (ראו היכן כללי ההרשאות נמצאים).

worktree גם משתמש בתשובות "never allow" השמורות של ה-checkout הראשי שלו, ובתשובות "always allow" השמורות שלו כל עוד [features] worktree_inherits_main_approvals פועל, כפי שהוא כברירת מחדל. Grok Desktop ו-workspaces מתארחים הם החריג: שער אישור הכלים שלהם בודק רק את התשובות של ה-worktree עצמו (ראו ההתמדה היא לפי פרויקט).

grok worktree create [NAME] יוצר את אותו worktree ש-grok -w [NAME] היה יוצר, בלי להתחיל סשן. הוא מדפיס את הספרייה שהסשן היה נפתח בה. הנתיב הזה הוא הפלט היחיד ב-stdout, ולכן cd "$(grok worktree create my-fix)" עובד. כברירת מחדל ה-worktree מתחיל מ-HEAD והשינויים שלא עברו commit מועתקים אליו. מעבירים --ref <ref> כדי להתחיל מ-checkout נקי של ענף, תג או commit. אם ל-worktree החדש חסרה הספרייה שממנה הרצתם, למשל checkout של --ref שקדם לה או ספרייה שמתעלמים ממנה, הפקודה מדפיסה את שורש ה-worktree.

#ניהול הפניות Grove

worktree של Grove יכול להפנות ספריות תוצרים שמתעלמים מהן, כמו target ו-node_modules, לאחסון מחוץ לעץ המוקרן. פקודות ההפניה מקבלות את נתיב ה-mount כארגומנט הראשון.

grok worktree redirect list /path/to/worktree
grok worktree redirect list /path/to/worktree --json
grok worktree redirect add /path/to/worktree target bind
grok worktree redirect del /path/to/worktree target
grok worktree redirect fixup /path/to/worktree
grok worktree redirect unmount /path/to/worktree target

list מדפיס את repo_path, type, mechanism, target, source ו-state. מריצים unmount בלי נתיב יחסי לריפו כדי להוריד כל הפניה על ה-mount. משתמשים ב-fixup --force כדי להחליף שאריות בבעלות Grove. משתמשים ב-fixup --strict כדי לסרב לספרייה רגילה שמאוכלסת.

כדי להפעיל את רשימת ההיתר הבטוחה על שיבוט Grove חדש, מעבירים --redirect-ignored. מוסיפים רשומות חוזרות עם --redirect-dir. ספריית הפניה נשארת לא פעילה אלא אם ההפניות מופעלות על ידי הפקודה או על ידי תצורת Grove.

grok clone https://example.com/org/repo.git --redirect-ignored
grok clone https://example.com/org/repo.git \
  --redirect-ignored --redirect-dir build --redirect-dir '**/node_modules'
grok clone https://example.com/org/repo.git --no-redirects

GROVE_REDIRECTS=0 נשאר מתג כיבוי בזמן ריצה. Grok לא שומר את מתג הכיבוי כבחירת ההפניה של השיבוט.

#בדיקת שימוש בדיסק

grok du (כינוי: grok disk-usage) מדווח כמה בית grok (~/.grok) תופס בדיסק. הוא מציג כל תיקייה ברמה העליונה, מהגדולה לקטנה, ואחר כך כל worktree עם הגודל, הסוג, הגיל, התווית והנתיב שלו. Worktrees שהרישום לא עוקב אחריהם מופיעים כ-untracked. העבירו --json כדי לקבל את אותו דוח כפלט קריא למכונה.

Disk usage for ~/.grok
    412.3 GB  worktrees
      1.2 GB  sessions
    412.0 MB  (top-level files)
    413.9 GB  total
  Worktree clones share storage with their source, so the total can exceed real disk use.

Worktrees
        SIZE  TYPE                AGE        LABEL  PATH
    380.0 GB  session             12d ago    my-fix ~/.grok/worktrees/xai/worktree-abc
     32.3 GB  untracked (session) 40d ago           ~/.grok/worktrees/xai/worktree-old

To reclaim space, run `grok worktree gc --max-age 7d --dry-run`, then the same command without `--dry-run`. Without `--max-age`, gc expires nothing, and it keeps a worktree whose work it cannot find elsewhere, naming each one.
Untracked rows are not in the registry, so gc never visits them. Remove one with `grok worktree rm --dry-run <path>`, then without `--dry-run`.

אחרי טבלת בית grok, grok du עשוי להדפיס Redirections, Orphaned redirections ו-Unattributed redirect directories. הבייטים האלה נמצאים בכלאי בריחה של Grove, לא בסך בית grok. סריקה ריקה לא מדפיסה דבר. שחררו כלא חי עם grok worktree clean-artifacts. מחקו כלאיים חיים וגם יתומים מוכחים עם grok du --clean --yes. מחקו רק יתומים מוכחים עם grok du --clean-orphaned --yes. דמון Grove הרץ מסווג ומודד את הכלאיים, ורק את אלה בתיקיית הנתונים שלו, שהדוח מציין בשמה. כלאיים בתיקיות נתונים אחרות של Grove, או בכל תיקייה כשאין דמון רץ, מוצגים לקריאה בלבד תחת תיקיית הנתונים שלהם עם גדלים בלבד. --clean, --clean-orphaned ו-grok worktree clean-artifacts מבקשים מהדמון לבצע את המחיקה. בלי דמון רץ הם מסרבים, אז הפעילו אותו עם grove daemon ונסו שוב.

AGE הוא הערך ש-grok worktree gc מודד: הזמן מאז הגישה האחרונה ל-worktree, או מאז שנוצר כשזה מאוחר יותר. פעילות של session ושל agent מעדכנת אותו. מעטפת או עורך שנשארו פתוחים בתיקייה לא מעדכנים אותו. ל-worktree לא מעוקב אין רשומה ברישום, ולכן הגיל שלו מגיע מהקובץ החדש ביותר שמתחתיו.

הגדלים הם ספירות בלוקים פיזיים ב-Unix וגדלי קבצים לוגיים במקומות אחרים, בהתאם למה ש-grok worktree show מדווח. שכפול worktree חולק אחסון עם המקור שלו וכל עותק נספר במלואו, ולכן הסך יכול לעבור גם את du -sh וגם את המקום שבאמת בשימוש. כשהסך עובר את המקום שבשימוש באמצעי האחסון, הדוח אומר זאת. --json נושא את אותם מספרים כ-volume_capacity_bytes ו-volume_available_bytes. עבור worktree של Grove, grok worktree show במקום זאת שואל את דמון Grove שבבעלותו את שימוש הדיסק של הגיבוי שלו (upper, git ואחרים) ושל ההפניות שלו, ולעולם לא סורק את ה-mount. כשאין דמון שעונה, הוא מדפיס unavailable עם הסיבה, ונתיב שאף mount של Grove לא משרת (לדוגמה אחרי detach) מקבל גם שורת Local Size: עם הגודל של התיקייה עצמה.

הדוח מודד מערכת קבצים אחת, זו שמחזיקה את בית grok. תיקייה בכל מערכת קבצים אחרת נשארת מחוץ לסך ונמנית ב-other_filesystem_dirs, ושורות ה-worktree שלה מציגות - לגודל (null ב---json). קישור סימבולי ברמה העליונה אל תיקייה, כגון worktrees שהועבר, נמנה ב-unfollowed_dir_symlinks. היעד שלו נשאר מחוץ לסך, אף שהשורות שמתחתיו עדיין נמדדות. תיקיות ורשומות שהדוח לא הצליח לקרוא נמנות ב-unreadable_dirs וב-unstatable_entries. הריצו RUST_LOG=debug grok du כדי לנקוב בשם כל אחת מהן.

כל שורת worktree ב---json נושאת גם created_at, last_accessed_at ו-last_modified_at בשניות unix, וגם repo_name ו-git_ref. שדות הרישום הם null עבור שורות לא מעוקבות. git_ref הוא הענף שנרשם כשה-worktree נרשם, לא הענף שנמצא ב-checkout עכשיו.

כשהרישום לא זמין, כל שורה מופיעה כ-untracked והדוח מציין את הסיבה. השדה registry ב---json נושא את אותו ערך: read, absent, busy, unopenable או corrupt. רישום busy מוחזק על ידי תהליך אחר, אז נסו שוב. רישום unopenable סובל מבעיית הרשאה או קלט/פלט, אז בדקו את הקובץ. רישום corrupt הוא המקרה היחיד שמצריך מחיקה: הסירו את הקובץ שהדוח מציין בשמו, ואז הריצו grok worktree db rebuild. הבנייה מחדש רושמת רק את ה-worktrees תחת התיקיות worktrees ו-worktree_pool של בית grok, רגילים או Grove. היא מדלגת על כל דבר שהיא מוצאת מחוץ להן, כגון worktree של Grove מבית grok אחר או אחד שנוצר בנתיב מחוץ לתיקיות האלה, וסופרת אותם תחת Skipped.

כדי לשחרר מקום, הריצו grok worktree gc --max-age 7d, שמסיר worktrees מעוקבים ישנים יותר מהגיל שאתם נותנים. בלי --max-age, gc לא מפקיע דבר, והוא מבקר רק worktrees שהרישום עוקב אחריהם. חריג אחד חל ב-macOS וב-Linux כשבית grok נמצא בדיסק מקומי. אם grok יוצא או נהרג בזמן העתקת worktree, הרצת gc הבאה מסירה אותו. זה קורה עם או בלי --max-age. דוח gc סופר אותו תחת Unfinished copies removed. worktree של Grove או overlay שכבר היה מחובר כ-mount כש-grok יצא נשאר, ו-gc מציג אותו כשמור (mounted). כך גם עותק שנהרג לפני שכתב את .git שלו, כגון הקבצים הראשונים של עותק רגיל: gc מציג אותו כשמור (no-repo) בכל הרצה. הסירו את התיקייה הזו עם grok worktree rm <path>, והרצת gc הבאה מפסיקה להציג אותה. הסירו worktree לא מעוקב עם grok worktree rm <path>. שתי הפקודות מקבלות --dry-run ומדווחות מה היו עושות: gc סופר את ה-worktrees שהיה מסיר, ו-rm מציין את הנתיב ומסמן worktree עם עבודה שלא נשמרה, לדוגמה (unsaved work: dirty). זה כולל reflog-only-commits: קומיטים שרק ה-reflog של worktree מקושר עדיין מציין בשמם (אחרי amend, rebase או reset), או רק שורת FETCH_HEAD ש-fetch ביקש, כגון git fetch <url> <branch>. הסרת ה-worktree מאבדת את הקומיטים האלה. בלי -f, rm --dry-run מסמן גם worktree שתהליך רץ או session פתוח ב-TUI של grok עובדים בתוכו (הרצה headless נספרת רק כש-GROK_TRACK_HEADLESS מוגדר), כ-(in use: a process or a session open in the grok TUI works inside it). הוא מדפיס would keep: לכל worktree ש-rm היה שומר. worktree של Grove נשפט על ידי דמון Grove שלו, שיכול גם לענות (removal refused: ...). הוא מדפיס unsaved work unknown כשהוא לא יכול לשפוט: mount של FUSE או NFS, כגון mount של Grove (git אף פעם לא רץ בתוכו), תיקייה שאינה git worktree, או בדיקה שלא הסתיימה או לא יכלה לומר. שכפול Grove מסומן unsaved work not checked.

כל הרצה שופטת כמה worktrees שהיא יכולה בתוך כדקה, כי אותו מעבר רץ על טיימר לצד ה-session שלכם וקריאת עץ עבודה שלם אינה בחינם. כל מה שהיא לא הגיעה אליו נספר כ-Not judged this pass ומחכה להרצה הבאה, אז במכונה עם הרבה לשחרר, הריצו gc שוב עד שהמספר הזה הוא אפס.

לפני הסרת worktree שפג תוקפו, gc בודק אם ההסרה תהרוס עבודה: קבצים שלא עברו commit, לא מעוקבים או מוחרגים, קומיט שאף ref שורד לא מחזיק, או מצב שנשמר רק בתיקיית git של אותו worktree. worktree שהוא לא יכול לבדוק נשמר גם הוא. הדוח סופר worktrees שנשמרו ומציין את הסיבה, בנפרד מאלה שתהליך חי או session פתוח ב-TUI של grok עיכבו. --force לא מדלג על הבדיקה.

בלי -f, grok worktree rm שומר worktree שתהליך רץ או session פתוח ב-TUI של grok עובדים בתוכו, או אחד עם עבודה שלא נשמרה. יוצר רץ לבדו לא שומר אותו, כי תהליך Desktop או TUI אחד יוצר worktrees עבור sessions רבים ומאריך ימים אחריהם. rm מדפיס kept: <path> (reason); pass -f to remove it anyway לכל worktree שהוא שומר, ואז יוצא עם 1. לפעמים grok לא יכול לדעת אם התיקייה עדיין מחוברת כ-mount. השורה אז אומרת שגם -f לא יסיר אותה. עבור worktree בשימוש, השורה גם מציינת כל עבודה שלא נשמרה ש--f היה משליך.

בלי -f, rm שומר גם worktree כשהבדיקה שלו נכשלה או לא הסתיימה, כי ייתכן שהבדיקה פספסה עבודה שלא נשמרה. שורת השמירה מציינת:

  • unsaved work unknown: check-failed (לדוגמה תיקייה שהוא לא יכול לקרוא)
  • unsaved work unknown: gate-timed-out (הבדיקה לקחה יותר מ-30 שניות)
  • unsaved work unknown: check did not finish: ... (הבדיקה נעצרה לפני שענתה. זו לא פקיעת זמן)
  • unsaved work unknown: mount table unreadable, not inspected
  • unsaved work unknown: path could not be resolved in time, not inspected
  • unsaved work unknown: unreadable symlink (...), not inspected

הערות אחרות לא שומרות worktree בפני עצמן:

  • in use unknown, תהיה הסיבה שאחריו אשר תהיה, כגון check did not finish: ... של סריקת התהליכים
  • סיבת unsaved work unknown שאינה אחת משש אלה, כגון not a git worktree או FUSE or NFS mount, not inspected
  • תשובה לא ידועה מדמון של worktree ב-Grove, אפילו unsaved work unknown: gate-timed-out

כשאין דמון רץ שמחזיק את ה-worktree של Grove, או שהפנייה לדמון שלו נכשלת, rm מסרב במקום זאת, כמתואר בהמשך. שכפול Grove לא נבדק. rm -f מדלג על הבדיקות האלה ומסיר את ה-worktree שאתם מציינים. הוא עדיין נכשל כש-grok לא יכול לקרוא את טבלת ה-mount, כי grok לא ימחק תיקייה שאולי עדיין מחוברת כ-mount.

ב-jj 0.46.0, jj workspace add במאגר ששומר jj ו-git באותו checkout גם הופך את ה-workspace החדש ל-git worktree. בלי -f, rm שומר את ה-workspace הזה, והשורה אומרת unsaved work: ignored-content: .jj.

session נחשב פתוח עד שהלשונית שלו נסגרת או ש-grok יוצא. grok worktree gc --force מתעלם מ-sessions פתוחים. בלעדיו, הרצת gc --max-age שלא יכולה לקרוא את רשימת ה-sessions הפתוחים של grok לא מפקיעה דבר והדוח שלה אומר למה תחת Age expiry skipped. כש-session חדש מוצא JSON פגום ב-~/.grok/active_sessions.json, Grok שומר את המקור כ-active_sessions.json.corrupt, מציל שורות session שלמות, ורושם את ה-session החדש. שורות שניזוקו מהפגם עשויות להיות חסרות. כל עוד הגיבוי קיים, gc לפי גיל נשאר מושבת כדי שהשורות החסרות האלה לא יחשפו worktree של session רץ אחר להפקעה. פתחו מחדש sessions רצים אחרים, ואז הסירו את ~/.grok/active_sessions.json.corrupt כדי להפעיל מחדש הפקעה לפי גיל. Grok משאיר JSON תקין עם סכמת session לא תואמת בלי לגעת בו. ב-Windows אף session לא נספר. Grok לא יכול לבדוק שהתהליך עדיין רץ שם. gc לא קורא את הרשימה. rm עדיין קורא אותה. בלי רשימת תהליכים ב-Windows שורת removed: שלו כבר אומרת in use unknown. רשימה שהוא לא יכול לקרוא מוסיפה את הסיבה שלה שם.

rm גם מסרב לשם או לנתיב שהרישום לא עוקב אחריו, עם או בלי -f. הוא עדיין מסיר תיקייה לא מעוקבת ב-~/.grok/worktrees/<repo>/<name> או ב-~/.grok/worktree_pool/<repo>/<name>. לדוגמה, אחרי שה-worktree docs נעלם, grok worktree rm docs מדווח not a grok worktree: docs; grok removes only worktrees it made. הוא משאיר את תיקיית docs של ה-checkout שלכם במקומה. כדי למחוק תיקייה ש-grok לא יצר, השתמשו ב-rm -r או ב-git worktree remove. גם ה-checkout של מאגר עצמו (כגון . בשורש מאגר) וגם נתיב לא רשום עם .. נדחים, עם או בלי -f.

worktree של Grove מקבל את אותה בדיקה מדמון Grove שלו, מחובר כ-mount או לא. gc לעולם לא קורא את ה-mount או את האחסון שלו בעצמו. הדמון גם שומר worktree שיומן הכתיבה שלו ראה בו שינוי בתוך חלון הגיל (recently-written, גם עם --force), אחד עם קבצים פתוחים דרך ה-mount שלו (in-use), ואחד שהוא היה מסרב להסיר, כגון worktree שאחר פוצל ממנו או אחד עם fetch רץ. ההסרה היא צעד דמון יחיד שבודק שוב קודם, כך שכתיבה שמגיעה אחרי הבדיקה של gc שומרת את ה-worktree. ההסרות האלה נספרות כ-Grove worktrees removed, והמעבר האוטומטי מבצע אותן גם הוא. כשאין דמון Grove שעונה, או שאף אחד מהדמונים הרצים אין לו שורה עבור ה-worktree, gc משאיר אותו וסופר אותו כ-Skipped (no Grove daemon). הפעילו את הדמון שבבעלותו והריצו gc שוב. worktree שאף דמון לא יחזיק שוב לעולם (תיקיית הנתונים שלו נעלמה) נשאר בספירה הזו בכל מעבר עד ש-grok worktree rm --force מוחק את הרשומה של grok עבורו. grok worktree rm --dry-run שואל את הדמון את אותה שאלה עבור worktree של Grove ומסמן את השורה, לדוגמה (unsaved work: dirty) או (removal refused: ...). grok worktree rm מסיר worktree של Grove רק דרך הדמון שמחזיק אותו, וסירוב מהדמון הזה סופי. כשאין דמון רץ שמחזיק את ה-worktree, rm מסרב: הדמון שבבעלותו אולי עצור, אז הפעילו אותו ונסו שוב. הוא גם מסרב כשבדיקה של דמון נכשלת. הפעילו מחדש או שדרגו את הדמון הזה ונסו שוב. rm --force אז מוחק רק את רשומת הרישום של grok ואומר זאת. הוא משאיר את התיקייה ואת האחסון של Grove בלי לגעת בהם. gc לעולם לא מוחק worktree של Grove על סמך ניחוש משלו.

קבצים מוחרגים נחשבים עבודה, עם חריג אחד: תיקייה שכללי ה-ignore של המאגר עצמו מחריגים, ושאו נושאת תג מטמון של כלי או שנקראת כמו אחת מתיקיות הפלט שלו (target, node_modules, .venv, והשאר). שם לבדו אף פעם לא מספיק, אז build/ שנכתב ביד ושאיש לא החריג עדיין שומר את ה-worktree.

קומיט שרק ה-reflog של worktree מציין בשמו, וזה מה ש-reset --hard או amend משאירים מאחור, מקבל שם מתמשך תחת refs/grok/reclaimed/<worktree>/<reclaim-ts>/<object> במאגר שממנו ה-worktree הגיע. Git סופר reflog כנגישות כשהוא גוזם, אז בלי השם הזה הסרת ה-worktree היא מה שהיה הופך את הקומיט לבלתי נגיש. השמות מכסים גם קומיט שרק שורת FETCH_HEAD ש-fetch ביקש מציינת בשמו, כגון git fetch <url> <branch>, פתרון notes-merge שנעצר, תג שרק ה-worktree מגיע אליו, וכל tree או blob שהוא מציין בשמו ישירות. עיינו בקומיטים שקיבלו שם עם git log --glob=refs/grok/reclaimed, וציינו כל שם, כולל אלה בתגים, ב-trees וב-blobs, עם git for-each-ref refs/grok/reclaimed. שחזרו אחד עם git branch <name> <commit>. git branch צריך קומיט, אז עבור שם בתג, ב-tree או ב-blob השתמשו ב-git tag <name> <id>. לקומיט של פתרון notes-merge יש תאריך קבוע של 1970, אז git log מציג אותו תחת 1970.

השמות האלה לא מצטברים. כל מעבר של gc מוחק את אלה שכבר לא מחזיקים דבר: הקומיט שלו נגיש עכשיו מ-ref אמיתי, התג שלו נגיש עכשיו מ-ref, או שהוא בן יותר מ-30 יום. שם ב-tree או ב-blob יכול להישאר עד שהוא בן 30 יום, גם אחרי ש-ref מגיע אליו. הדוח סופר אותם כ-names_collected.

grok worktree list רגיל (בלי --json, --repo או --type) מציין בשם כל עותק שלא הושלם ש-grok worktree gc --dry-run סופר. הוא אומר ש-gc מסיר אותו. הוא משמיט עותק ש-gc שומר (mounted, no-repo, check-failed) ועץ שתהליך רץ נמצא בתוכו. אם כל הרשימה לא מסתיימת בתוך 10 שניות, לדוגמה על mount רשת תקוע, הרשימה לא מציינת אף שם. היא גם לא מציינת אף שם כשהרישום עדיין busy אחרי המתנה קצרה בפתיחה. חיפוש רישום שנכשל עבור עותק אחד משמיט רק את העותק הזה.


#פרטי אחסון של Session

#תבנית שמירה

Grok שומר את השיחה כ-JSON מופרד בשורות חדשות (JSONL). כל שורה ב-updates.jsonl היא אירוע עדכון session של ACP עצמאי. התבנית הזו תומכת ב:

  • כתיבות מצטברות (append-only במהלך session)
  • קריאות הזרמה יעילות (לשחזור session)
  • ניפוי שגיאות קל (כל שורה היא JSON תקין)

קבצי המצב הקטנים יותר, summary.json, plan.json ו-signals.json, הם JSON רגיל ולא JSONL. JSONL הוא מקור האמת לתוכן ה-session. grok sessions search בנוסף מתחזק אינדקס SQLite FTS5 מקומי על כותרות ופרומפטים של sessions לחיפוש מילות מפתח מהיר.

#מטא נתונים של Session

summary.json רושם, בין שאר השדות:

  • info: מזהה ה-session ותיקיית העבודה
  • session_summary ו-generated_title: סיכום ה-session והכותרת שנוצרה על ידי המודל
  • title_is_manual: true כשהכותרת הוגדרה על ידי /rename ידני (כך שהיצירה האוטומטית משאירה אותה במקומה)
  • created_at ו-updated_at: חותמות זמן של יצירה ושל עדכון אחרון
  • num_messages ו-num_chat_messages: ספירות עדכונים והודעות צ'אט
  • current_model_id: המודל שבשימוש
  • parent_session_id: ה-session המקור עבור fork או restore
  • agent_name: סוכנים בעלי שם שומרים רק את זה. session של --agent-profile מוטמע שומר גם JSON של agent_profile
  • last_turn_summary: סיכום קצר במיוחד של התור האחרון
  • last_recap: תצוגה מקדימה חסומה של ה-recap האחרון של ה-session

#שימוש בדיסק

היסטוריית session (updates.jsonl, chat_history.jsonl) שולטת בשימוש בדיסק ב-sessions ארוכים. השתמשו ב-/compact כדי להקטין את גודל ההיסטוריה.


#טיפים

  • השתמשו ב-/new כדי להתחיל מחדש כשההקשר הנוכחי שלכם כבר לא רלוונטי.
  • השתמשו ב-/compact מראש ב-sessions ארוכים כדי לשמור על חלון ההקשר יעיל.
  • השתמשו ב-/rewind כדי לבטל טעויות. הוא מחזיר את השיחה לתור מוקדם יותר (שינויי קבצים מתורים שהוסרו נשארים כמו שהם).
  • במצב headless, לכדו את sessionId מפלט JSON והעבירו אותו ל--r כדי לבנות אוטומציות מרובות שלבים ששומרות הקשר.
  • בדקו את /session-info כדי לראות כמה מחלון ההקשר שלכם נוצל.