Skip to content

feat(codex): add gbot codex status, list-threads, and send - #28

Merged
ScriptedAlchemy merged 6 commits into
mainfrom
feat/codex-bridge
Sep 15, 2026
Merged

ScriptedAlchemy merged 6 commits into
mainfrom
feat/codex-bridge

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Why

Grok Bot agents need a way to wake a Codex thread without a human relaying context (#24). This adds gbot codex status, gbot codex list-threads [--limit N], and gbot codex send <threadId> <message...>, which attach to the local Codex app-server daemon and start a turn with the documented JSON-RPC methods.

Closes #26. Parent: #24.

Scope

  • src/codex-bridge.js: socket discovery under CODEX_HOME, a minimal RFC 6455 client over net (no new dependency), connectCodexAppServer, codexStatus, listCodexThreads, sendToCodexThread. Method and parameter names are pinned to Codex 0.154.0 from codex app-server generate-json-schema.
  • src/cli.js: the codex command branch, --json support, help text.
  • test/codex-bridge.test.js: thirteen tests against an in-process fake app-server listening on a Unix socket, plus RFC 6455 known-answer vectors for masking, length headers, and Sec-WebSocket-Accept.
  • README.md: "Messaging Codex threads from Grok Bot" with the Desktop limitation, upstream issues, and failure modes. One minor changeset.
  • Out of scope: injecting into live ChatGPT Desktop tasks (blocked by [macOS][regression] codex_app MCP override makes CODEX_APP_SERVER_USE_LOCAL_DAEMON=1 unreachable openai/codex#41014 and #41112) and Desktop's private CODEX_APP_TOOLS_PIPE_PATH sockets. The CLI explains both when the control socket is absent.

Tradeoffs

  • Direct Unix socket instead of codex app-server proxy. The spike showed the proxy is byte-transparent: the control socket speaks WebSocket, so JSON lines written to the proxy's stdin get no reply. A WebSocket client is needed either way, and Node's built-in WebSocket cannot dial Unix sockets, so the bridge carries a ~60-line client over net and skips the extra process.
  • send resumes then starts a turn and returns without waiting. turn/start on a thread that is not loaded returns "thread not found", and the daemon keeps running a turn after the client disconnects, so resume-first with an immediate return is both required and sufficient.
  • Approvals are refused, not auto-answered. A server request arriving while connected gets a JSON-RPC error, and send exits 1 naming the turn id and the approval_policy = "never" remedy. send disconnects once the turn starts, so later requests stay with the daemon for a Codex client to answer; the README says so.
  • thread/list uses useStateDbOnly: true. The default rescans every rollout file and took 26 s on this machine; the state DB answers in milliseconds with the same rows.

Blast Radius

New command branch only; existing Grok Bot commands and the gateway backend are untouched. codex dispatches before openBackend, so it needs no Grok Bot auth. Package stays zero-dependency.

Verification

  • npm test: 71 pass on the rebased branch (13 new).
  • npx publint@0.3.24: All good. npm pack + global install + gbot --help lists the codex commands.
  • Live, Codex 0.154.0 daemon started with codex app-server daemon start:
    • gbot codex status → reachable, daemon 0.154.0, cli 0.154.0.
    • gbot codex list-threads --limit 5 → five threads with status, cwd, preview.
    • gbot codex send 01a0a283-6b74-7d60-b041-510313dcf6e4 'automated smoke from gbot bridge' → turn 01a0a28f-cebb-7b23-b149-5f96bdc49ed1 inProgress; read-back over thread/read shows the userMessage and the agent reply ack.
    • Unknown thread → exit 1 "Unknown Codex thread …"; thread held by VS Code → exit 1 "open in another client".
    • Daemon stopped (socket absent, Desktop stdio app-servers still running) → status, list-threads, send all exit 1 with the Desktop explanation and upstream links.
  • Raw JSON-RPC captures from the spike and the live outputs are on the dev machine under /fast/tmp/grokbot-run/bridge-spike/ and /fast/tmp/grokbot-run/bridge-evidence/.

@changeset-bot

changeset-bot Bot commented Sep 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fd7f07b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
grok-bot-cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-15T01:01:42.790099Z ef1c37f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef1c37f664

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex-bridge.js
Comment on lines +299 to +300
const turn = await client.request("turn/start", { threadId, input: [{ type: "text", text }] });
if (client.refused.length) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the session open for approval requests

When turn/start returns an inProgress turn, the model generally has not generated any command or file-change approval request yet. Checking client.refused immediately therefore misses requests that arrive after the response, and the finally block closes the socket, so a turn using an approval-requiring policy can be reported as successfully started while it later stalls or aborts without the advertised refusal error. Keep the connection open until an appropriate turn lifecycle event, or reject such sends up front based on resumed.approvalPolicy.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gbot codex / bridge: inject messages into Codex threads via app-server

1 participant