grok-bot-cli 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grok-bot-cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "CLI and Agent Bundle plugin for Grok Bot agents and groups: create, update, message, inspect threads, and automate cleanup",
5
5
  "type": "module",
6
6
  "engines": {
@@ -46,7 +46,7 @@
46
46
  "@agent-bundle/runtime": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@899755dc6d",
47
47
  "@changesets/cli": "3.0.3",
48
48
  "@modelcontextprotocol/server": "2.1.0",
49
- "@rstest/core": "0.11.12",
49
+ "@rstest/core": "0.12.2",
50
50
  "@types/node": "^24.0.0",
51
51
  "@types/react": "^19.2.18",
52
52
  "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@899755dc6d",
package/dist/plugin.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json","author":{"name":"Zack Jackson","url":"https://github.com/ScriptedAlchemy"},"description":"Message Grok Bot from Codex, Claude Code, and Cursor, with managed automatic replies and explicit Codex conversation links.","homepage":"https://github.com/ScriptedAlchemy/grok-bot-cli#readme","keywords":["grok","grok-bot","grokbot","gbot","cursor","ai-agents","automation","terminal","cli","agent-bundle"],"license":"MIT","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","version":"0.10.0"}
1
+ {"$schema":"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json","author":{"name":"Zack Jackson","url":"https://github.com/ScriptedAlchemy"},"description":"Message Grok Bot from Codex, Claude Code, and Cursor. Codex/Claude tools use local sockets on the user's registered machines only (no remote transport); from the Grok Bot box, run gbot via Grok Bot Shell with a machineId.","homepage":"https://github.com/ScriptedAlchemy/grok-bot-cli#readme","keywords":["grok","grok-bot","grokbot","gbot","cursor","ai-agents","automation","terminal","cli","agent-bundle"],"license":"MIT","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","version":"0.10.2"}
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: Codex and Claude tools run on the user's registered machines via local sockets — never on the Grok Bot box
3
+ alwaysApply: true
4
+ ---
5
+ # Codex and Claude run on the user's machines
6
+
7
+ `codex_*` and `claude_send` talk only to a **local** Unix socket on the machine
8
+ where the process runs. gbot has **no remote transport**.
9
+
10
+ - Codex/Claude sessions live on the user's registered computers (Linux desktop,
11
+ Mac, …), not on the Grok Bot agent box (`HOME=/home/box`, no Codex install).
12
+ - When you are on the box, **do not** call those MCP tools. Run the `gbot` CLI on
13
+ the user's machine through **Grok Bot Shell with a machineId** (the host's
14
+ machine-targeted shell).
15
+ - On that machine, start the daemon with `codex app-server daemon start` (or
16
+ bootstrap) so `$CODEX_HOME/app-server-control/app-server-control.sock` exists.
17
+ - Auth stays with each machine's native Codex or Claude login. Do not invent
18
+ token files or export credentials.
@@ -22134,7 +22134,8 @@ var __webpack_modules__ = {
22134
22134
  var _package_json__rspack_import_6 = __webpack_require__("./package.json");
22135
22135
  var _codex_contract_js__rspack_import_7 = __webpack_require__("./src/core/codex/contract.js");
22136
22136
  var _desktop_shim_js__rspack_import_8 = __webpack_require__("./src/core/desktop-shim.js");
22137
- const PINNED_CODEX_VERSION = "0.154.0";
22137
+ var _user_machine_guidance_js__rspack_import_9 = __webpack_require__("./src/core/user-machine-guidance.js");
22138
+ const PINNED_CODEX_VERSION = "0.158.0";
22138
22139
  const UPSTREAM_DESKTOP_ISSUES = [
22139
22140
  "https://github.com/openai/codex/issues/41014",
22140
22141
  "https://github.com/openai/codex/issues/41112"
@@ -22167,20 +22168,34 @@ var __webpack_modules__ = {
22167
22168
  function singleLine(text) {
22168
22169
  return stripTerminalControls(text).replace(/[\t\n\r\u2028\u2029]+/g, " ");
22169
22170
  }
22170
- function unreachableMessage(path, desktopAttached = "unknown") {
22171
+ function boxUnreachableMessage(path) {
22172
+ return [
22173
+ "No Codex app-server control socket at " + path + ".",
22174
+ _user_machine_guidance_js__rspack_import_9.M
22175
+ ].join("\n");
22176
+ }
22177
+ function unreachableMessage(path, desktopAttached = "unknown", env = process.env) {
22178
+ if ((0, _user_machine_guidance_js__rspack_import_9.R)({
22179
+ path,
22180
+ env,
22181
+ home: env.HOME || (0, node_os__rspack_import_3.homedir)()
22182
+ })) {
22183
+ return boxUnreachableMessage(path);
22184
+ }
22171
22185
  if (desktopAttached === "private-stdio") {
22172
22186
  return [
22173
22187
  "ChatGPT Desktop is running its private stdio app-server, which external clients cannot reach",
22174
22188
  "(" + UPSTREAM_DESKTOP_ISSUES.join(", ") + ").",
22175
- "No Codex app-server control socket at " + path + ": start a managed standalone daemon with `codex app-server daemon start`.",
22176
- "gbot codex targets daemon-managed threads only."
22189
+ "No Codex app-server control socket at " + path + ": start a managed standalone daemon with `codex app-server daemon start` (or bootstrap).",
22190
+ "gbot codex targets daemon-managed threads only; gbot has no remote transport."
22177
22191
  ].join("\n");
22178
22192
  }
22179
22193
  return [
22180
22194
  "No Codex app-server control socket at " + path + ".",
22181
- "Either no daemon is running (start one with `codex app-server daemon start`),",
22195
+ "Either no daemon is running (start one with `codex app-server daemon start` or bootstrap),",
22182
22196
  "or ChatGPT Desktop is running a private stdio app-server that external clients cannot reach",
22183
22197
  "(" + UPSTREAM_DESKTOP_ISSUES.join(", ") + ").",
22198
+ "Codex must run on the same machine as gbot. Set CODEX_APP_SERVER_SOCK to an existing local control socket if it is elsewhere; gbot has no remote transport.",
22184
22199
  "gbot codex targets daemon-managed threads only."
22185
22200
  ].join("\n");
22186
22201
  }
@@ -22824,6 +22839,47 @@ var __webpack_modules__ = {
22824
22839
  };
22825
22840
  }
22826
22841
  const openSession = openCodexSession;
22842
+ async function startCodexThread({ cwd, expectedCwd, model, effort, message, env = process.env, signal } = {}) {
22843
+ validateModelEffort(model, effort);
22844
+ if (typeof cwd !== "string" || !cwd.trim()) throw new RangeError("--cwd is required for a new Codex thread");
22845
+ const resolvedCwd = realpathSync(cwd);
22846
+ if (expectedCwd !== undefined && realpathSync(expectedCwd) !== resolvedCwd) throw new RangeError("New Codex thread cwd does not match expectedCwd");
22847
+ if (message !== undefined && (typeof message !== "string" || !message.trim())) throw new RangeError("Message must contain text");
22848
+ const { client } = await openSession(env, {
22849
+ signal
22850
+ });
22851
+ let threadId, started;
22852
+ try {
22853
+ started = await client.request("thread/start", {
22854
+ cwd: resolvedCwd,
22855
+ ...model ? {
22856
+ model
22857
+ } : {},
22858
+ ...effort ? {
22859
+ config: {
22860
+ model_reasoning_effort: effort
22861
+ }
22862
+ } : {}
22863
+ });
22864
+ threadId = started?.thread?.id;
22865
+ if (typeof threadId !== "string" || !ID_PATTERN.test(threadId)) throw new CodexProtocolError("thread/start", "missing `thread.id`");
22866
+ } finally{
22867
+ client.close();
22868
+ }
22869
+ if (message === undefined) return {
22870
+ threadId,
22871
+ cwd: resolvedCwd,
22872
+ model: started.model ?? model,
22873
+ exitCode: 0
22874
+ };
22875
+ return await sendToCodexThread(threadId, message, {
22876
+ env,
22877
+ expectedCwd: resolvedCwd,
22878
+ model,
22879
+ effort,
22880
+ signal
22881
+ });
22882
+ }
22827
22883
  const CODEX_VERSION_PROBE_TIMEOUT_MS = 3000;
22828
22884
  function probeLocalCodexVersion(timeoutMs = CODEX_VERSION_PROBE_TIMEOUT_MS) {
22829
22885
  const out = spawnSync("codex", [
@@ -22913,7 +22969,7 @@ var __webpack_modules__ = {
22913
22969
  session = await openSession(env);
22914
22970
  } catch (err) {
22915
22971
  if (err instanceof CodexRouteError) {
22916
- const message = err.mode === "socket-absent" ? unreachableMessage(path, desktopAttached) : err.message;
22972
+ const message = err.mode === "socket-absent" ? unreachableMessage(path, desktopAttached, env) : err.message;
22917
22973
  return withStatusExitCode({
22918
22974
  ...base,
22919
22975
  reachable: false,
@@ -23122,7 +23178,7 @@ var __webpack_modules__ = {
23122
23178
  }
23123
23179
  function requireExperimental(env, what) {
23124
23180
  if (experimentalEnabled(env)) return;
23125
- throw new CodexSendError(what + " uses Codex's experimental app-server API (thread/queue/*), which is off by default. " + "Set GROK_BOT_CODEX_EXPERIMENTAL=1 to opt in; method names are pinned to Codex " + PINNED_CODEX_VERSION + ".", {
23181
+ throw new CodexSendError(what + " needs thread/queue/add, which is experimental and absent from Codex " + PINNED_CODEX_VERSION + "'s stable API. " + "Use --when-busy steer with an expected turn ID, wait until the thread is idle, or opt in with GROK_BOT_CODEX_EXPERIMENTAL=1 on a Codex daemon that supports the experimental queue API.", {
23126
23182
  delivery: "rejected",
23127
23183
  reason: "experimental-disabled"
23128
23184
  });
@@ -23130,7 +23186,7 @@ var __webpack_modules__ = {
23130
23186
  function unsupportedOrRpc(err, method, threadId, envelope, turnId) {
23131
23187
  const guarded = method === "turn/steer";
23132
23188
  if (err instanceof CodexRpcError && err.rpc && err.rpc.code === -32601) {
23133
- return new CodexSendError("Codex app-server does not offer " + method + " (daemon predates it, or experimentalApi was not granted). " + (guarded ? "Upgrade Codex before retrying guarded steering." : "Upgrade Codex or send without --when-busy queue."), {
23189
+ return new CodexSendError("Codex app-server does not offer " + method + " (daemon predates it, or experimentalApi was not granted). " + (guarded ? "Upgrade Codex before retrying guarded steering." : "Use --when-busy steer with an expected turn ID, wait for idle, or use a Codex daemon with experimental queue support and GROK_BOT_CODEX_EXPERIMENTAL=1."), {
23134
23190
  delivery: "rejected",
23135
23191
  reason: "unsupported",
23136
23192
  threadId,
@@ -23187,7 +23243,7 @@ var __webpack_modules__ = {
23187
23243
  }
23188
23244
  async function sendToCodexThread(threadId, text, { env = process.env, envelope = buildEnvelope({
23189
23245
  env
23190
- }), whenBusy = "reject", session, expectedTurnId, expectedCwd, signal } = {}) {
23246
+ }), whenBusy = "reject", session, expectedTurnId, expectedCwd, model, effort, signal } = {}) {
23191
23247
  try {
23192
23248
  const receipt = await sendToCodexThreadInner(threadId, text, {
23193
23249
  env,
@@ -23196,6 +23252,8 @@ var __webpack_modules__ = {
23196
23252
  session,
23197
23253
  expectedTurnId,
23198
23254
  expectedCwd,
23255
+ model,
23256
+ effort,
23199
23257
  signal
23200
23258
  });
23201
23259
  return (0, _codex_contract_js__rspack_import_7.Dz)(receipt);
@@ -23207,7 +23265,19 @@ var __webpack_modules__ = {
23207
23265
  return (0, _codex_contract_js__rspack_import_7.DG)(err);
23208
23266
  }
23209
23267
  }
23210
- async function sendToCodexThreadInner(threadId, text, { env, envelope, whenBusy, session, expectedTurnId, expectedCwd, signal }) {
23268
+ function validateModelEffort(model, effort) {
23269
+ if (model !== undefined && (typeof model !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(model))) throw new RangeError("--model must be a nonempty model ID");
23270
+ if (effort !== undefined && ![
23271
+ "none",
23272
+ "minimal",
23273
+ "low",
23274
+ "medium",
23275
+ "high",
23276
+ "xhigh"
23277
+ ].includes(effort)) throw new RangeError("--effort must be none, minimal, low, medium, high, or xhigh");
23278
+ }
23279
+ async function sendToCodexThreadInner(threadId, text, { env, envelope, whenBusy, session, expectedTurnId, expectedCwd, model, effort, signal }) {
23280
+ validateModelEffort(model, effort);
23211
23281
  if (![
23212
23282
  "reject",
23213
23283
  "queue",
@@ -23253,7 +23323,15 @@ var __webpack_modules__ = {
23253
23323
  try {
23254
23324
  resumed = await client.request("thread/resume", {
23255
23325
  threadId,
23256
- excludeTurns: true
23326
+ excludeTurns: true,
23327
+ ...model ? {
23328
+ model
23329
+ } : {},
23330
+ ...effort ? {
23331
+ config: {
23332
+ model_reasoning_effort: effort
23333
+ }
23334
+ } : {}
23257
23335
  });
23258
23336
  } catch (err) {
23259
23337
  assertNotCancelled();
@@ -23386,7 +23464,13 @@ var __webpack_modules__ = {
23386
23464
  }
23387
23465
  ],
23388
23466
  clientUserMessageId: envelope.messageId,
23389
- turnTrigger: "gbot"
23467
+ turnTrigger: "gbot",
23468
+ ...model ? {
23469
+ model
23470
+ } : {},
23471
+ ...effort ? {
23472
+ effort
23473
+ } : {}
23390
23474
  });
23391
23475
  } catch (err) {
23392
23476
  if (err instanceof CodexSendError) throw err;
@@ -23655,10 +23739,10 @@ var __webpack_modules__ = {
23655
23739
  ];
23656
23740
  if (afterMessageId !== undefined) boundedInteger(anchors.length, 200, 'afterMessageId count');
23657
23741
  for (const anchor of anchors)conversationId(anchor, 'afterMessageId');
23658
- boundedInteger(timeoutMs, 600000, 'timeoutMs');
23742
+ boundedInteger(timeoutMs, 7200000, 'timeoutMs');
23659
23743
  boundedInteger(maxOutputBytes, BUDGET, 'maxOutputBytes');
23660
23744
  if (waitSignal !== undefined && !(waitSignal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
23661
- let done = false, status = acceptedTurns.has(turnId) ? 'inProgress' : undefined, error, historyError, itemBytes = 0, truncated = overflow;
23745
+ let done = false, status = acceptedTurns.has(turnId) ? 'inProgress' : undefined, error, historyError, itemBytes = 0, truncated = false;
23662
23746
  const items = new Map();
23663
23747
  const add = (item)=>{
23664
23748
  if (!item || typeof item.id !== 'string' || typeof item.type !== 'string') throw new Error('Invalid history item');
@@ -23705,6 +23789,7 @@ var __webpack_modules__ = {
23705
23789
  };
23706
23790
  const result = (state, detail)=>{
23707
23791
  const interactions = scan();
23792
+ const overflowUncertain = state === 'unknown' && /Notification coverage overflow/.test(detail ?? '');
23708
23793
  const candidates = [
23709
23794
  ...items.values()
23710
23795
  ].map((x)=>x.item);
@@ -23713,7 +23798,7 @@ var __webpack_modules__ = {
23713
23798
  const reply = {
23714
23799
  text: '',
23715
23800
  items: [],
23716
- truncated: truncated || overflow
23801
+ truncated: truncated || overflowUncertain
23717
23802
  };
23718
23803
  for (const item of selected){
23719
23804
  const text = reply.text ? `${reply.text}\n${item.text}` : item.text;
@@ -23746,7 +23831,7 @@ var __webpack_modules__ = {
23746
23831
  interactions
23747
23832
  };
23748
23833
  };
23749
- let timer, notify;
23834
+ let timer, pollTimer, notify;
23750
23835
  const abortSignals = [
23751
23836
  signal,
23752
23837
  waitSignal
@@ -23762,10 +23847,18 @@ var __webpack_modules__ = {
23762
23847
  'Codex connection closed'
23763
23848
  ]);
23764
23849
  };
23765
- timer = setTimeout(()=>resolve([
23850
+ timer = setTimeout(()=>resolve(overflow ? [
23851
+ 'unknown',
23852
+ 'Notification coverage overflow; pending interaction status is uncertain'
23853
+ ] : [
23766
23854
  'timeout',
23767
23855
  'Observation deadline reached'
23768
23856
  ]), timeoutMs);
23857
+ pollTimer = setInterval(()=>{
23858
+ for (const listener of [
23859
+ ...wake
23860
+ ])listener();
23861
+ }, 2000);
23769
23862
  for (const s of abortSignals)s.addEventListener('abort', notify, {
23770
23863
  once: true
23771
23864
  });
@@ -23836,19 +23929,51 @@ var __webpack_modules__ = {
23836
23929
  historyError
23837
23930
  ];
23838
23931
  }
23932
+ let lastPoll = 0;
23839
23933
  while(!done){
23840
23934
  const interactions = scan();
23841
23935
  if (terminal(status)) return [
23842
23936
  status,
23843
23937
  error ?? historyError
23844
23938
  ];
23845
- if (historyError || overflow) return [
23939
+ if (historyError) return [
23846
23940
  'unknown',
23847
- historyError ?? 'Notification coverage overflow'
23941
+ historyError
23848
23942
  ];
23849
23943
  if (interactions.length) return [
23850
23944
  'waiting-for-input'
23851
23945
  ];
23946
+ if (Date.now() - lastPoll >= 2000) {
23947
+ lastPoll = Date.now();
23948
+ try {
23949
+ await visitCodexHistory(session, threadId, 'thread/turns/list', {}, (data)=>{
23950
+ const turn = data.find((t)=>t?.id === turnId);
23951
+ if (!turn) return false;
23952
+ if (terminal(turn.status)) {
23953
+ status = turn.status;
23954
+ error = turn.error;
23955
+ }
23956
+ return true;
23957
+ }, {
23958
+ stopped: ()=>done
23959
+ });
23960
+ if (terminal(status)) {
23961
+ await visitCodexHistory(session, threadId, 'thread/items/list', {
23962
+ turnId,
23963
+ sortDirection: 'asc'
23964
+ }, (data)=>{
23965
+ for (const row of data)if (row?.turnId === turnId && row.item) add(row.item);
23966
+ return false;
23967
+ }, {
23968
+ stopped: ()=>done
23969
+ });
23970
+ continue;
23971
+ }
23972
+ } catch (err) {
23973
+ historyError = err.message;
23974
+ truncated = true;
23975
+ }
23976
+ }
23852
23977
  await new Promise((resolve)=>{
23853
23978
  const listener = ()=>{
23854
23979
  wake.delete(listener);
@@ -23871,6 +23996,7 @@ var __webpack_modules__ = {
23871
23996
  } finally{
23872
23997
  done = true;
23873
23998
  clearTimeout(timer);
23999
+ clearInterval(pollTimer);
23874
24000
  wake.delete(notify);
23875
24001
  for (const s of abortSignals)s.removeEventListener('abort', notify);
23876
24002
  for (const listener of [
@@ -23918,7 +24044,7 @@ var __webpack_modules__ = {
23918
24044
  close,
23919
24045
  async send (text, { envelope = (0, _codex_bridge_js__rspack_import_2.nq)({
23920
24046
  env
23921
- }), whenBusy = 'reject', expectedTurnId, signal: sendSignal } = {}) {
24047
+ }), whenBusy = 'reject', expectedTurnId, model, effort, signal: sendSignal } = {}) {
23922
24048
  if (closed) return (0, _contract_js__rspack_import_0.DG)(Object.assign(new Error('Conversation closed'), {
23923
24049
  delivery: 'rejected',
23924
24050
  reason: 'closed',
@@ -23937,6 +24063,8 @@ var __webpack_modules__ = {
23937
24063
  expectedTurnId,
23938
24064
  session,
23939
24065
  expectedCwd,
24066
+ model,
24067
+ effort,
23940
24068
  signal: submissionSignal
23941
24069
  });
23942
24070
  if (receipt.delivery === 'accepted' && receipt.turnId) {
@@ -25227,6 +25355,12 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
25227
25355
  whenBusy: active ? "steer" : "reject",
25228
25356
  ...active ? {
25229
25357
  expectedTurnId: active
25358
+ } : {},
25359
+ ...record.model ? {
25360
+ model: record.model
25361
+ } : {},
25362
+ ...record.effort ? {
25363
+ effort: record.effort
25230
25364
  } : {}
25231
25365
  });
25232
25366
  if (!active || receipt.delivery !== "rejected" || receipt.reason !== "rejected" || !/guard|expected.*turn|turn.*mismatch|stale/i.test(receipt.error ?? "")) return receipt;
@@ -26369,6 +26503,12 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
26369
26503
  threadId: r.threadId,
26370
26504
  expectedCwd: r.expectedCwd,
26371
26505
  busyPolicy: r.busyPolicy,
26506
+ ...input.model ? {
26507
+ model: input.model
26508
+ } : {},
26509
+ ...input.effort ? {
26510
+ effort: input.effort
26511
+ } : {},
26372
26512
  bindingId: r.bindingId ?? (r.id?.startsWith("binding:") ? r.id : null),
26373
26513
  text,
26374
26514
  sourceIds: input.sourceIds ?? [],
@@ -26461,6 +26601,15 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
26461
26601
  "steer",
26462
26602
  "reject"
26463
26603
  ]),
26604
+ model: zod__rspack_import_3.YjP().regex(/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/).optional(),
26605
+ effort: zod__rspack_import_3.k5n([
26606
+ "none",
26607
+ "minimal",
26608
+ "low",
26609
+ "medium",
26610
+ "high",
26611
+ "xhigh"
26612
+ ]).optional(),
26464
26613
  bindingId: relayId.nullable(),
26465
26614
  text,
26466
26615
  sourceIds: zod__rspack_import_3.YOg(relayId).max(200),
@@ -27365,9 +27514,30 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
27365
27514
  fp: ()=>redactSecrets
27366
27515
  });
27367
27516
  },
27517
+ "./src/core/user-machine-guidance.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
27518
+ const USER_MACHINE_CODEX_CLAUDE_GUIDANCE = [
27519
+ "Codex and Claude sessions live on the user's registered machines (for example their Linux desktop or Mac), not on the Grok Bot agent box (/home/box).",
27520
+ "Codex must run on the same machine as gbot. Set CODEX_APP_SERVER_SOCK to an existing local control socket, or use $CODEX_HOME/app-server-control/app-server-control.sock. There is no remote transport.",
27521
+ "When running on the box (HOME=/home/box), do not call codex_* or claude_send there. Run the gbot CLI on the user's machine through Grok Bot Shell with a machineId (the host's machine-targeted shell).",
27522
+ "On that machine, provide the socket with `codex app-server daemon start` (or bootstrap). Auth stays with each machine's native Codex or Claude login; gbot does not store or export credentials."
27523
+ ].join("\n");
27524
+ function looksLikeGrokBotBox({ path = "", env = process.env, home = env.HOME || "" } = {}) {
27525
+ const values = [
27526
+ home,
27527
+ env.HOME,
27528
+ path
27529
+ ].filter((value)=>value != null && value !== "").map(String);
27530
+ return values.some((value)=>value === "/home/box" || value.startsWith("/home/box/"));
27531
+ }
27532
+ __webpack_require__.d(__webpack_exports__, {
27533
+ R: ()=>looksLikeGrokBotBox
27534
+ }, {
27535
+ M: USER_MACHINE_CODEX_CLAUDE_GUIDANCE
27536
+ });
27537
+ },
27368
27538
  "./package.json" (module) {
27369
27539
  module.exports = {
27370
- "rE": "0.10.0"
27540
+ "rE": "0.10.2"
27371
27541
  };
27372
27542
  }
27373
27543
  };
@@ -4,8 +4,23 @@ description: Message Grok Bot, Codex threads, or opted-in local Claude Code chan
4
4
  ---
5
5
  # Talk to Grok Bot
6
6
 
7
- The `grok-bot` MCP server and `gbot` CLI share Grok gateway access and local
8
- Codex/Claude transports.
7
+ The `grok-bot` MCP server and `gbot` CLI share Grok gateway access. Codex and
8
+ Claude tools use **local sockets only** on the user's registered machines.
9
+
10
+ ## MCP instructions (Codex / Claude)
11
+
12
+ gbot connects only to a local Unix socket
13
+ (`$CODEX_HOME/app-server-control/app-server-control.sock`, or
14
+ `CODEX_APP_SERVER_SOCK`). There is **no remote transport**.
15
+
16
+ - Codex app-server threads and opted-in Claude Code channels live on the user's
17
+ registered computers (Linux desktop, Mac, …) — **never** on the Grok Bot agent
18
+ box (`HOME=/home/box`, no Codex install).
19
+ - When this MCP server is running on the box, **do not** call `codex_*` or
20
+ `claude_send`. Run the `gbot` CLI on the user's machine through **Grok Bot Shell
21
+ with a machineId** (the host's machine-targeted shell).
22
+ - On that machine, provide the socket with `codex app-server daemon start` (or
23
+ bootstrap). Auth stays with each machine's native Codex or Claude login.
9
24
 
10
25
  ## When to load this
11
26
 
@@ -49,12 +64,12 @@ which source is present.
49
64
 
50
65
  ## Claude Code channel
51
66
 
52
- `claude_send` sends to a named live Claude Code session on this machine and waits
53
- for its explicit `claude_reply`. The destination must enable the native
54
- `claude-channel` with `GROK_BOT_CLAUDE_CHANNEL=NAME` and Claude's development-channel
55
- opt-in. Supply `name`, `message`, and optional `timeoutMs` (1..120000). `replied`
56
- means the reply tool ran; `unknown` is not rejection and must not be automatically
57
- retried. Normal Claude tool approvals remain in its session. This does not attach
58
- to arbitrary Claude Desktop chats or connect a remote Grok runtime to local tools.
59
- CLI: `gbot claude send NAME "message" --json`.
60
-
67
+ `claude_send` sends to a named live Claude Code session on the user's registered
68
+ machine (local socket under `~/.grok-bot-cli/claude/`) and waits for its explicit
69
+ `claude_reply`. From the Grok Bot box, do not call this tool — use Grok Bot Shell
70
+ with a machineId to run `gbot claude send` on that machine instead. The destination
71
+ must enable the native `claude-channel` with `GROK_BOT_CLAUDE_CHANNEL=NAME` and
72
+ Claude's development-channel opt-in. Supply `name`, `message`, and optional
73
+ `timeoutMs` (1..120000). `replied` means the reply tool ran; `unknown` is not
74
+ rejection and must not be automatically retried. Normal Claude tool approvals remain
75
+ in its session. CLI: `gbot claude send NAME "message" --json`.
@@ -30,9 +30,14 @@ cookie/payment approvals and other unsupported requests require the owning Grok
30
30
  ## Codex conversation tools
31
31
 
32
32
  The generated Codex, Cursor, and Claude plugins and portable MCP artifact expose these
33
- additional tools on the same `grok-bot` MCP server. Codex tools use the local Codex
34
- app-server control socket; Grok tools use the Grok gateway. Portable MCP artifacts
35
- must be configured in an MCP-capable host; they are not automatically loaded by the Grok app.
33
+ additional tools on the same `grok-bot` MCP server. Codex tools connect only to a
34
+ **local** Codex app-server control socket on the process's machine
35
+ (`$CODEX_HOME/...` or `CODEX_APP_SERVER_SOCK`). gbot has **no remote transport**.
36
+ When the MCP server runs on the Grok Bot agent box (`HOME=/home/box`), do not call
37
+ these tools — run the `gbot` CLI on the user's registered machine through Grok Bot
38
+ Shell with a machineId, after `codex app-server daemon start` (or bootstrap) there.
39
+ Grok tools use the Grok gateway. Portable MCP artifacts must be configured in an
40
+ MCP-capable host; they are not automatically loaded by the Grok app.
36
41
 
37
42
  - `codex_threads`: bounded discovery of daemon-managed Codex threads.
38
43
  - `codex_send`: submit a message with a correlation envelope. Default delivery is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grok-bot-cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "CLI and Agent Bundle plugin for Grok Bot agents and groups: create, update, message, inspect threads, and automate cleanup",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,7 +58,7 @@
58
58
  "@agent-bundle/runtime": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@899755dc6d",
59
59
  "@changesets/cli": "3.0.3",
60
60
  "@modelcontextprotocol/server": "2.1.0",
61
- "@rstest/core": "0.11.12",
61
+ "@rstest/core": "0.12.2",
62
62
  "@types/node": "^24.0.0",
63
63
  "@types/react": "^19.2.18",
64
64
  "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@899755dc6d",