DEV Community

Cover image for Queue Work Into a Running Codex Session From Another Shell: codex queue, Step by Step
Gabriel Anhaia
Gabriel Anhaia

Posted on Edited on AI-assisted

Queue Work Into a Running Codex Session From Another Shell: codex queue, Step by Step


Codex is halfway through a refund endpoint in one terminal. You remember two things it should do before it calls the task done: run the lint step it skipped, and add a changelog entry. You could switch terminals, wait for the turn to end and type it in. Or you could send it from the shell you're already in, the same way a script or a git hook would.

That is what codex queue is for. Codex CLI 0.149.0 added it "for sending messages to existing local or remote sessions". The command reference shows the shape:

codex queue --thread <SESSION_ID> \
  --message "Run the remaining checks"
Enter fullscreen mode Exit fullscreen mode

Then 0.166.0, released on October 29, added codex queue --resume "to resume unloaded threads after queueing a message". So a message can now wake a session that isn't running.

Step 1: give the session a name you can target

--thread takes a UUID or an exact session name, and the docs say to use a UUID when two sessions share a name. For work you drive by hand, a unique name is easier to type than a UUID.

Inside the running Codex session, rename it:

/rename orders-refund
Enter fullscreen mode Exit fullscreen mode

The reference describes /rename <name> as giving "a saved session a recognizable name without leaving the TUI", and it leaves the transcript as it was. If you'd rather use the UUID, this community tutorial has you copy it from the /status output. The official page lists /status as showing the active model, approval policy, writable roots and current token usage, so check what your version prints. To browse saved sessions, /resume inside the TUI opens a session picker.

The examples below use the name. Scripts that run unattended are safer with the UUID, because a second session renamed orders-refund makes the name ambiguous.

A hand dropping message cards into a slot that feeds a busy workbench where an agent silhouette is working
codex queue adds a message to a session from outside it. The session picks it up when it gets to it.

Step 2: queue the follow-ups

From any other shell on the same machine:

codex queue --thread orders-refund \
  --message "Run npm run lint and fix what it reports."

codex queue --thread orders-refund \
  --message "Add a CHANGELOG.md entry under Unreleased."
Enter fullscreen mode Exit fullscreen mode

Two rules from the reference apply. Queued messages use the session's model, so you can't switch models per message. And the command "accepts text only", so there are no image attachments. If you want a screenshot in front of Codex, attach it in the session yourself. The community tutorial above shows an --image flag; the official page doesn't list one for codex queue.

If the order matters, don't count on two separate queue items arriving as two turns in sequence. I haven't seen the docs promise that. Put the steps in one message, numbered:

codex queue --thread orders-refund --message "Before you finish:
1. Run npm run lint and fix what it reports.
2. Add a CHANGELOG.md entry under Unreleased."
Enter fullscreen mode Exit fullscreen mode

When the session isn't loaded (you closed the terminal, say), add --resume:

codex queue --resume --thread orders-refund \
  --message "Rerun the tests and report what failed."
Enter fullscreen mode Exit fullscreen mode

The reference adds the conditions. Resuming "requires a running local daemon or a server selected with --remote", and if Codex can't resume the session, "it prints a warning and still exits successfully". The message stays queued either way, so a zero exit code doesn't prove the session woke up. PR #57232, which added the flag, says a thread that is already loaded is left running.

Step 3: fire it from a git hook

Anything that runs shell can send a queue command. Here is a post-merge hook that tells the Codex session when main moves under it. Per the githooks docs, post-merge runs after git merge, which includes a git pull, and it doesn't run when the merge fails on conflicts.

#!/bin/sh
# post-merge: tell the Codex session that main moved
[ "$(git branch --show-current)" = "main" ] || exit 0

sha=$(git rev-parse --short HEAD)
msg="main is now at $sha. Rebase onto main, rerun tests."

codex queue --resume --thread orders-refund \
  --message "$msg" || echo "codex queue failed" >&2
Enter fullscreen mode Exit fullscreen mode

The || branch only catches a failed queue write. A failed resume prints a warning and exits 0, so it won't trigger. Drop --resume if you only want to queue while the session is open.

The branch check matters if Codex works in a worktree. A linked worktree shares "everything except per-worktree files such as HEAD, index, etc." with the main checkout, according to the git-worktree docs, and that includes the hooks. Without the check, a merge inside Codex's own worktree would queue a message to Codex about itself.

Install it where git looks for hooks:

hooks=$(git rev-parse --git-path hooks)
cp post-merge "$hooks/post-merge"
chmod +x "$hooks/post-merge"
Enter fullscreen mode Exit fullscreen mode

Git ignores hooks without the executable bit. If your repo sets core.hooksPath (husky and similar tools do), put the file there instead. And if you pull with --rebase, post-merge won't run, because no merge happens.

Step 4: send it from CI

A CI job can do the same with --remote and --remote-auth-token-env, which reads a bearer token from the environment variable you name. That only works if the runner can reach a Codex server, so in practice it means a self-hosted runner on the same network, not a public endpoint you opened for this. A small script the job calls when tests fail:

#!/bin/sh
# ci-notify.sh: queue a CI failure into the session
set -eu
run="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY"
run="$run/actions/runs/$GITHUB_RUN_ID"

codex queue --remote "$CODEX_REMOTE_URL" \
  --remote-auth-token-env CODEX_REMOTE_TOKEN \
  --thread orders-refund \
  --message "CI failed on $GITHUB_SHA. Logs: $run"
Enter fullscreen mode Exit fullscreen mode

The GITHUB_* variables are ones GitHub Actions sets for every job; on another CI, swap in its equivalents. I haven't run this against a remote server, so check the flag placement against codex queue --help in your version.

Step 5: run it in Hermes with a second pane

I build Hermes IDE, so weigh this section with that in mind. Hermes runs each agent's own interface in a real terminal, which means /rename, codex queue and Codex's other commands work there as they do anywhere else.

Press ⌘N (Ctrl+Shift+N on Windows and Linux), pick Codex and type the task. It starts on its own hermes/ branch, in its own worktree, with the task as its first prompt. Split the pane right and open a plain shell next to it. Codex works on the left; you send queue commands from the right, or let the hook send them.

Hermes IDE with two agent sessions in split panes, Codex on the left and Claude Code on the right, each on its own hermes/ worktree branch, with the sessions sidebar
Hermes 2.3.4 split panes: Codex and Claude Code side by side, each in its own hermes/ worktree, with the sidebar showing status, context use, cost and branch.

The part that pairs well with queueing is the attention inbox. Every session shows one status (working, needs approval, asked you, done, error or idle) and says when that status is a guess. The inbox counts the agents blocked on you, and ⌘I (Ctrl+Shift+I) jumps to the one that has waited longest.

Queueing a message doesn't clear an approval prompt: if Codex is stopped at one, it's waiting on you, and the inbox shows that. You answer in Codex's own terminal. Hermes never answers a permission prompt for you and never types into a terminal on its own, so the queue command stays yours to send.

The limits, from the open issues

codex queue returns once the message is stored. Issue #54252, open since October 15, asks for a way to read the reply. There's no CLI command for that yet, and the workaround in the issue goes through the experimental app-server schema.

A mailbox with its flag raised and a letter inside, next to a closed door, leaving it unclear whether anyone has read it
Exit code 0 means the message was stored, nothing more.

Delivery can pause. In issue #56914, reported on 0.164.0 and still open, a session that was interrupted mid-turn and then resumed holds queued messages until a manual turn completes, and codex queue prints the same success message either way. In the desktop app, issue #52705 reports that with an active /goal, queued items can wait until someone presses Steer. Both are open issues, so check them before you rely on this.

So treat codex queue as fire-and-check. Send the message from the hook or the job, then look at the session (or codex agents, which the reference calls the command center) before you assume the work happened.


If this was useful

A queue that says "stored" but can't tell you "consumed" is one of the oldest problems in messaging. The Event-Driven Architecture Pocket Guide is my short book on that territory: sagas, CQRS, the outbox, and the traps nobody warns you about. It's the thinking you need once hooks and CI jobs start sending work to agents. It belongs to Pocket Guides for Developers, 8 short books on agents, RAG, prompts, observability, events, databases and system design.

Hermes IDE is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux: download it or star it on GitHub.

Event-Driven Architecture Pocket Guide: Saga, CQRS, Outbox, and the Traps Nobody Warns You About

Top comments (0)