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

תיעוד 1

מצב headless וסקריפטים

#מצב headless

השתמשו במצב headless לסקריפטים, לבוטים או למשימות אחרות שמותאמות למכונה.

grok -p "Your prompt here"

דגלים נפוצים:

דגלמה הוא עושה
-p, --single <PROMPT>שולח פרומפט אחד
-m, --model <MODEL>בוחר מודל
-s, --session-id <ID>יוצר או ממשיך סשן headless עם שם
-r, --resume <ID>ממשיך סשן קיים
-c, --continueממשיך את הסשן האחרון בתיקייה הנוכחית
--cwd <PATH>מגדיר את תיקיית העבודה
--output-format <FMT>בוחר plain, json או streaming-json
--always-approveמאשר אוטומטית הרצות של כלים
--no-alt-screenרץ בשורה (בלי מסך חלופי / השתלטות TUI על המסך המלא)

סשנים: סשני headless (דרך --session-id, --resume, --continue) נשמרים ב-~/.grok/sessions.

דיכוי עדכונים ב-xai-grok-shell: כשמשתמשים במצב headless (-p) או ב-ACP (grok agent stdio) בסקריפטים, ב-CI או בסביבות אוטומטיות אחרות, העבירו --no-auto-update (לדוגמה grok --no-auto-update -p "...") כדי לדלג על בדיקות עדכון ברקע. אפשר גם לכבות אותן באופן קבוע על ידי הגדרת auto_update = false תחת המקטע [cli] בקובץ ~/.grok/config.toml.

#פורמטי פלט

  • plain: טקסט קריא לאדם
  • json: אובייקט JSON אחד בסוף
  • streaming-json: אירועי JSON מופרדים בשורות חדשות
grok -p "List TODO comments" --output-format json
grok -p "Explain the architecture" --output-format streaming-json

JSON בזרימה פולט אירועים הדרגתיים כשהם מגיעים.

#ACP

השתמשו ב-ACP כשרוצים שילוב עם IDE או עם כלי, במקום סשן מסוף.

grok agent stdio

זה מריץ את Grok כסוכן ACP מעל JSON-RPC על stdin/stdout. הדוגמה למטה מניחה ש-grok כבר מאומת מקומית, או ש-XAI_API_KEY מוגדר. session/prompt מחזיר מטא נתונים של השלמה. טקסט העוזר עצמו מגיע כמקטעי session/update.

import { spawn } from "node:child_process";
import readline from "node:readline";
import process from "node:process";

const proc = spawn("grok", ["agent", "stdio"], { stdio: ["pipe", "pipe", "pipe"] });
const rl = readline.createInterface({ input: proc.stdout });
const pending = new Map();
let nextId = 1;
let text = "";

proc.stderr.on("data", chunk => process.stderr.write(chunk));

rl.on("line", line => {
  const message = JSON.parse(line);

  if (message.method === "session/update") {
    const update = message.params?.update;
    if (update?.sessionUpdate === "agent_message_chunk" && update.content?.text) {
      text += update.content.text;
    }
    return;
  }

  const pendingRequest = pending.get(message.id);
  if (!pendingRequest) return;

  pending.delete(message.id);
  if (message.error) {
    pendingRequest.reject(new Error(message.error.message ?? JSON.stringify(message.error)));
  } else {
    pendingRequest.resolve(message.result ?? {});
  }
});

function request(method, params, timeoutMs = 30000) {
  const id = nextId++;

  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      pending.delete(id);
      reject(new Error(`${method} timed out`));
    }, timeoutMs);

    pending.set(id, {
      resolve(result) {
        clearTimeout(timer);
        resolve(result);
      },
      reject(error) {
        clearTimeout(timer);
        reject(error);
      },
    });

    proc.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
  });
}

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

try {
  const init = await request("initialize", {
    protocolVersion: 1,
    clientCapabilities: {
      fs: { readTextFile: true, writeTextFile: true },
      terminal: true,
    },
  });

  const authMethods = new Set((init.authMethods ?? []).map(method => method.id));
  const methodId =
    process.env.XAI_API_KEY && authMethods.has("xai.api_key")
      ? "xai.api_key"
      : authMethods.has("cached_token")
        ? "cached_token"
        : null;

  if (!methodId) {
    throw new Error("Run `grok login` first, or set XAI_API_KEY.");
  }

  await request("authenticate", { methodId, _meta: { headless: true } });

  const { sessionId } = await request("session/new", {
    cwd: process.cwd(),
    mcpServers: [],
  });

  const prompt = await request("session/prompt", {
    sessionId,
    prompt: [{ type: "text", text: "Say hello in one short sentence." }],
  });

  let lastLength = -1;
  let stableChecks = 0;
  while (stableChecks < 2) {
    await sleep(150);
    if (text.length === lastLength) {
      stableChecks += 1;
    } else {
      lastLength = text.length;
      stableChecks = 0;
    }
  }

  console.log(text.trim() || `No text returned (stopReason=${prompt.stopReason})`);
} finally {
  rl.close();
  proc.kill();
}