Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/codex-local-socket-guidance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grok-bot-cli": patch
---

Explain local Codex socket placement, CODEX_APP_SERVER_SOCK, and machine-targeted Grok Bot Shell use in missing-socket errors.
5 changes: 5 additions & 0 deletions .changeset/codex-model-new-thread.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grok-bot-cli": patch
---

Support model and reasoning effort overrides for Codex sends and add local new-thread CLI and MCP routes.
5 changes: 5 additions & 0 deletions .changeset/codex-plugin-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grok-bot-cli": patch
---

Add Claude Code and Cursor slash commands for sending to, listing, and waiting on Codex threads.
5 changes: 5 additions & 0 deletions .changeset/codex-queue-158.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grok-bot-cli": patch
---

Update Codex queue guidance and API pin for 0.158.0, with clear experimental-gate and unsupported-method errors.
5 changes: 5 additions & 0 deletions .changeset/codex-wait-reconcile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"grok-bot-cli": patch
---

Keep Codex wait observing through notification floods, reconcile completion from turn history, and allow two-hour caller timeouts.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,18 @@ codex app-server daemon start # once per machine session
gbot codex status # socket, daemon version, reachability
gbot codex list-threads --limit 10 # id, status, cwd, preview
gbot codex send <threadId> "Grok here: the build is green, please continue."
gbot codex send --model gpt-6-astra --effort high <threadId> "Review this change"
gbot codex new --cwd /path/to/project --model gpt-6-astra --effort high "Start here"
gbot codex wait <threadId> <turnId> --timeout-ms 1800000
```

`send` resumes the thread, starts a turn with your text, prints the turn id, and returns; Codex keeps working after `gbot` disconnects. Every command accepts `--json`.

**Which Codex you reach.** `gbot` connects to `$CODEX_HOME/app-server-control/app-server-control.sock` (default `~/.codex/...`) with a built-in WebSocket client. The daemon must be started by `codex app-server daemon start`. `list-threads` shows the threads recorded under `CODEX_HOME` (CLI, TUI, VS Code); `send` uses the resumed thread state and selected busy policy: ordinary sends reject active work, while explicitly selected guarded steering can deliver into the active turn. Method and parameter names are pinned to the Codex release recorded in `src/core/codex-bridge.js` (`codex app-server generate-json-schema`); `status` prints the daemon and CLI versions so a stale daemon is visible, and `codex app-server daemon restart` picks up the installed CLI. Native Windows is not supported yet (AF_UNIX control socket); use WSL, Linux, or macOS.
`send` and MCP `codex_send` accept optional `model` and `effort` overrides (`none`, `minimal`, `low`, `medium`, `high`, `xhigh`). `gbot codex new` and MCP `codex_new` use `thread/start` to create a thread with a required cwd and optional model, effort, and first message. Use `--expected-cwd` to guard the selected directory. `wait` accepts a caller timeout up to two hours and reconciles turn history after notification floods.

**User machines, not the Grok Bot box.** Codex (and Claude) sessions live on the user's registered computers — for example their Linux desktop or Mac — not on the Grok Bot agent's sandbox VM (`HOME=/home/box`, no Codex install). gbot has **no remote transport**; it only dials a local Unix socket. When this process is on the box, do not call the Codex/Claude MCP tools there — run the `gbot` CLI on the user's machine through **Grok Bot Shell with a machineId**. On that machine, start the daemon with `codex app-server daemon start` (or bootstrap). Auth stays with each machine's native login; gbot does not store or export credentials.
**Which Codex you reach.** `gbot` connects to `$CODEX_HOME/app-server-control/app-server-control.sock` (default `~/.codex/...`) or the existing local socket set by `CODEX_APP_SERVER_SOCK`, with a built-in WebSocket client. The daemon must be started by `codex app-server daemon start`. `list-threads` shows the threads recorded under `CODEX_HOME` (CLI, TUI, VS Code); `send` uses the resumed thread state and selected busy policy: ordinary sends reject active work, while explicitly selected guarded steering can deliver into the active turn. Method and parameter names are pinned to the Codex release recorded in `src/core/codex-bridge.js` (`codex app-server generate-json-schema`); `status` prints the daemon and CLI versions so a stale daemon is visible, and `codex app-server daemon restart` picks up the installed CLI. Native Windows is not supported yet (AF_UNIX control socket); use WSL, Linux, or macOS.

**User machines, not the Grok Bot box.** Codex must run on the same machine as gbot. Codex (and Claude) sessions live on the user's registered computers — for example their Linux desktop or Mac — not on the Grok Bot agent's sandbox VM (`HOME=/home/box`, no Codex install). gbot has **no remote transport**; it only dials a local Unix socket. When this process is on the box, do not call the Codex/Claude MCP tools there — run the `gbot` CLI on the user's machine through **Grok Bot Shell with a machineId**. On that machine, start the daemon with `codex app-server daemon start` (or bootstrap). Auth stays with each machine's native login; gbot does not store or export credentials.

**ChatGPT Desktop limitation.** Desktop runs its own private stdio app-server and does not publish the shared control socket, so external clients cannot reach live Desktop tasks. When the socket is absent, `gbot codex status` exits 1 and says so, naming the upstream issues: [openai/codex#41014](https://github.com/openai/codex/issues/41014) and [openai/codex#41112](https://github.com/openai/codex/issues/41112). `gbot` never reads Desktop's temporary `CODEX_APP_TOOLS_PIPE_PATH` sockets under `/tmp/codex-browser-use/`; that channel is private to Desktop.

Expand All @@ -219,7 +224,7 @@ Install copies the scripts out of the package into durable `~/.codex/bin/` paths

Fail-open runs only before any stdin byte is consumed and no daemon payload was committed to stdout: the wrapper preflights the daemon socket (3 s deadline) and runs the bridge as a child — never `exec` — falling through to the real standalone `codex` for every non-`app-server` spawn, every preflight failure, and every pre-session bridge failure (exit 1), always on pristine stdio+stdout. The bridge's connect + WebSocket-upgrade handshake runs under one absolute monotonic deadline (`CODEX_BRIDGE_CONNECT_TIMEOUT`, default 10 s) requiring `HTTP/1.1 101` plus a matching `Sec-WebSocket-Accept` (a `200` fails even with a valid hash), and a first-response deadline (`CODEX_BRIDGE_FIRST_MESSAGE_TIMEOUT`, default 30 s) bounds connect-to-matching-daemon-response covering the first RPC — an unrelated notification or foreign response never satisfies it, only the matching response/error (or timeout) clears it — preflight (3 s) + upgrade (10 s) + first RPC (30 s) stays far below a daemon-lock hang, and preflight and upgrade leave stdin untouched. Reads after a successful init block with no timeout so healthy idle sessions survive silence; every mid-session socket send and stdout write runs under its own write budget (`CODEX_BRIDGE_IO_TIMEOUT`, default 30 s), so a wedged or non-reading peer cannot hang Desktop. The commit point is byte-precise on input OR output, committed before the stdout write: the bridge counts every stdin byte read (buffered readahead included, even an unforwarded blank line) and marks stdout used before writing any forwarded daemon payload via a bounded write, so the fallback only ever runs on truly pristine stdio+stdout. Buffered EOF-tail data flushes before the WS Close. A mid-session bridge failure (exit 2+) makes the wrapper exit promptly so Desktop reconnects; the fallback never runs on half-consumed stdin or dirty stdout. The wrapper never starts the daemon on the spawn path (a wedged daemon lock must not block Desktop) — upkeep belongs to the LaunchAgent login script and install, which share one `CODEX_HOME` for the GUI domain and the daemon they start; if the socket is absent, Desktop simply runs stock Codex until the daemon is started.

Residual risks, stated honestly: requests without both matching thread and turn IDs remain unanswered; a Codex client must handle those requests. A daemon that speaks framing-valid but semantically unexpected JSON-RPC (unknown methods, id-less responses) is treated as transport; pins are to app-server schema 0.154.0. The bridge trusts the local control socket; a malicious local daemon could hold the session up to the stated budgets, not past them.
Residual risks, stated honestly: requests without both matching thread and turn IDs remain unanswered; a Codex client must handle those requests. A daemon that speaks framing-valid but semantically unexpected JSON-RPC (unknown methods, id-less responses) is treated as transport; pins are to app-server schema 0.158.0. The bridge trusts the local control socket; a malicious local daemon could hold the session up to the stated budgets, not past them.

Current shim limitation: Desktop's spawn-time app-tools MCP `-c` overrides are not forwarded to the already-running managed daemon. No restoration path or app-tools parity has been demonstrated here; this is not a claim of permanent protocol impossibility. Fully quit and relaunch ChatGPT.app after install (or login) so it inherits `CODEX_CLI_PATH`. `status` reads the macOS GUI-domain value via `launchctl getenv` (what Desktop actually inherits) alongside the calling shell's value. LaunchAgent persistence is macOS-first; elsewhere install still writes the wrapper and bridge but leaves `CODEX_CLI_PATH` for you to export. `~/.codex/bin` holds scripts only — there is no extra revert note to clean up; revert is `gbot codex desktop-shim uninstall` plus this section.

Expand All @@ -238,7 +243,7 @@ gbot codex send --correlation-id M --reply-to M --hop 1 <threadId> "ack" # the a

Sends at `hop >= GROK_BOT_MAX_HOPS` (default 4) are refused with `reason: "hop-limit"` before anything reaches the daemon, so two agents cannot acknowledge each other forever; `gbot` never auto-acknowledges. `--envelope` (implied by any envelope flag) prepends a one-line `[gbot msg=… corr=… reply-to=… hop=… from=user@host]` header so the receiving agent can quote the ids back. That header is caller-authored provenance for the reader, not authentication: the daemon authenticates the local user through the socket, nothing else. Private ChatGPT Desktop pipes and arbitrary ChatGPT chats stay out of scope; only Codex threads on a reachable app-server daemon are routes.

**Busy threads.** `send` reads the thread status on resume. Only `idle` and `notLoaded` threads start a turn. An `active` thread (a turn in progress, or waiting on approval / user input) is refused with `reason: "busy"`: in app-server 0.154.0 a `turn/start` on an active thread steers that turn rather than queueing behind it, by default. Explicit guarded steering and managed bridge routes can deliver into active work; they never interrupt a turn. Either wait for `list-threads` to show `idle` and resend, or pass `--when-busy queue` to hand the message to the daemon's own queue through Codex's experimental `thread/queue/add` — that needs `GROK_BOT_CODEX_EXPERIMENTAL=1`, returns `delivery: "queued"` with `queuedSubmissionId`, and `gbot codex queue <threadId>` shows what is still waiting. `systemError` threads are refused with `reason: "thread-error"`, statuses this version does not know with `reason: "unknown-status"`. Receipts distinguish `delivery: "accepted"` (turn started; `turnId`, `turnStatus`), `"queued"`, `"rejected"` (nothing was sent; see `reason`), and `"unknown"` (the request left but no acknowledgment came back — look for `messageId` in the thread or queue before resending). The decision record, with the schema evidence and a live probe of the queue API, is in [`docs/codex-busy-threads.md`](docs/codex-busy-threads.md).
**Busy threads.** `send` reads the thread status on resume. Only `idle` and `notLoaded` threads start a turn. An `active` thread (a turn in progress, or waiting on approval / user input) is refused with `reason: "busy"`: in app-server 0.158.0 a `turn/start` on an active thread steers that turn rather than queueing behind it, by default. Explicit guarded steering and managed bridge routes can deliver into active work; they never interrupt a turn. Either wait for `list-threads` to show `idle` and resend, or pass `--when-busy queue` to hand the message to the daemon's own queue through Codex's experimental `thread/queue/add` — that needs `GROK_BOT_CODEX_EXPERIMENTAL=1`, returns `delivery: "queued"` with `queuedSubmissionId`, and `gbot codex queue <threadId>` shows what is still waiting. `systemError` threads are refused with `reason: "thread-error"`, statuses this version does not know with `reason: "unknown-status"`. Receipts distinguish `delivery: "accepted"` (turn started; `turnId`, `turnStatus`), `"queued"`, `"rejected"` (nothing was sent; see `reason`), and `"unknown"` (the request left but no acknowledgment came back — look for `messageId` in the thread or queue before resending). The decision record, with the schema evidence and a live probe of the queue API, is in [`docs/codex-busy-threads.md`](docs/codex-busy-threads.md).

**Failure modes.** Every `send` and `codex` outcome under `--json` is one document on stdout with `exitCode`; failures include `{ error, delivery, reason, messageId, correlationId, hop, exitCode: 1, … }` and the process exits 1. Framework argument/schema errors remain on stderr and exit 2. `--json` is reserved anywhere before `--`; put `--` before flag-like message text. `reason` values are stable:

Expand All @@ -257,7 +262,7 @@ The npm package is also an [Agent Bundle](https://scriptedalchemy.github.io/agen
that gives Codex, Claude Code, and Cursor a `grok-bot` MCP server with messaging,
Codex conversation, and managed bridge tools, plus a `talk-to-grok-bot` skill.
`gbot_send` and `gbot_thread` handle Grok conversations; `codex_threads`,
`codex_send`, `codex_wait`, and `codex_watch` handle Codex conversations.
`codex_send`, `codex_new`, `codex_wait`, and `codex_watch` handle Codex conversations. Claude Code and Cursor bundles also include `/gbot:codex-send`, `/gbot:codex-threads`, and `/gbot:codex-wait` commands under `commands/`.
`gbot_bridge_start`, `gbot_bridge_status`, `gbot_bridge_stop`, and
`gbot_codex_respond` manage automatic delivery and scoped operator responses.
The tools bundle this repository's gateway client and worker, so the installed
Expand Down
2 changes: 1 addition & 1 deletion artifact/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"author":{"name":"Zack Jackson"},"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.","displayName":"gbot","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","mcpServers":"./.cursor-plugin/mcp.json","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","rules":"./rules/","skills":"./skills/","version":"0.10.1"}
{"author":{"name":"Zack Jackson"},"commands":"./commands/","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.","displayName":"gbot","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","mcpServers":"./.cursor-plugin/mcp.json","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","rules":"./rules/","skills":"./skills/","version":"0.10.1"}
2 changes: 1 addition & 1 deletion artifact/agent-bundle.compile-evidence.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion artifact/agent-bundle.manifest.json

Large diffs are not rendered by default.

Loading