Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clauodex

Drive Codex threads from your terminal — or from Claude Code, as a skill.

List and read your threads, start new tasks, and steer, queue, interrupt, or re-model a turn that is running inside the Codex desktop app.

$ clauodex active
ID        STATUS   OWNER      AGE  SOURCE  TITLE                       CWD
--------  -------  ---------  ---  ------  --------------------------  -----------------------
019f7191  running  codex-app  22m  vscode  Reach #3 in ICML challenge  ~/Documents/Codex/…

$ clauodex steer 019f7191 "stop rewriting the parser, just fix the off-by-one"
steered 019f7191 (turn 019fac00)

Zero dependencies. One Python file. Python 3.8+.

Why it exists

Codex has no supported API for "what is my desktop app doing, and can you tell it something?" There are two protocols involved, and using only the first one gets you a read-only tool:

  1. The app-server protocol — the JSON-RPC interface codex app-server speaks. Great for listing, reading, and running threads. But "loaded" and "running" are per-process memory, and the desktop app's app-server is a stdio child of the Electron process with no listening socket. Nothing you start yourself can steer a turn the app is running.

  2. The desktop app's IPC router — an undocumented message bus the Electron process listens on, which exists so a second Codex client can drive a thread the app owns. This is the part that makes steering work.

Clauodex speaks both and routes each command to whichever process actually owns the thread. Full protocol notes, including everything needed to reimplement the IPC side, are in reference/protocol.md.

Install

git clone https://github.com/SSHdotCodes/clauodex.git ~/.claude/skills/clauodex
ln -s ~/.claude/skills/clauodex/scripts/clauodex.py /usr/local/bin/clauodex

Cloning to ~/.claude/skills/clauodex registers it as a Claude Code skill — ask Claude "what are my Codex threads doing?" and it will use it. The symlink is only needed if you also want it on your $PATH; skip it to use the skill alone.

Then check your setup:

clauodex doctor

Commands

active threads with a turn running right now, and who owns each
threads browse threads — --search, --cwd, --live, --archived
read <thread> print the conversation — --last N, -v for reasoning and full output
new "<prompt>" start a task — --cwd, --model, --effort, --sandbox, --wait
send <thread> "<msg>" send a message; queues automatically if a turn is running
steer <thread> "<msg>" inject into the running turn
queue <thread> "<msg>" run after the current turn finishes
interrupt <thread> stop the running turn
model <thread> <id> change model / --effort
goal Codex goals (/goal) — list, show, set, edit, pause, resume, clear
--from <thread> on new/send/steer/queue: send as another Codex thread, producing the app's "Sent by Codex from another chat" badge
pin <thread> pin/unpin in the app sidebar
wait <thread> block until the turn ends, print the reply
tail <thread> -f live event stream
approvals / approve <id> answer a blocked approval request
open <thread> open it in the Codex desktop app
release <thread> drop clauodex's hold so the app can own it
doctor / status environment report / daemon state

Plus models, name, fork, compact, archive, delete, and raw for calling any app-server method directly. --json works on everything.

Threads accept a full id, any unique id prefix, or last.

Goals

A goal is an objective attached to a thread that Codex's server keeps working toward, turn after turn, on its own. This is the same mechanism /goal uses in the app — continuation lives in the Codex core, not in a loop clauodex runs.

clauodex new "start here" --goal "Get the test suite green" --goal-budget 2000000
clauodex goal list --active
clauodex goal edit <thread> "new objective"
clauodex goal pause <thread>     # stops autonomous continuation
clauodex goal clear <thread>

Codex sets the status itself as it works (active, paused, blocked, usageLimited, budgetLimited, complete), so a goal going complete is the agent reporting, not an error.

A goal-driven thread runs in the Codex app, with its goal pill and progress visible there, exactly like one started with /goal. A goal and a live app view are not a trade-off.

An active goal spends quota with nobody watching — --goal-budget is worth setting. interrupt only ends the current turn; the goal will start another, so use goal pause to actually stop an autonomous thread.

Background by default

Clauodex runs threads in the background and never opens or focuses the Codex app on its own. Making the app take over a thread requires a codex:// deeplink, which pulls the app to the front and switches the thread you are looking at, so that is opt-in: new --open, or clauodex open <thread>.

Work still goes to the app whenever the app already holds the thread — that costs nothing and keeps its UI live. Otherwise clauodex runs it. The app-server enforces a per-thread writer lock, so opening a thread clauodex is running contends safely rather than corrupting it. Idle threads are released automatically, so opening one afterwards loads cleanly.

clauodex active labels every thread with where it actually runs:

OWNER Meaning What works
codex-app running in the app, because it already had the thread open everything, and the app shows it live
clauodex running under clauodex — the default for anything the app isn't already showing everything, but not visible live until you open it
app/cli running in another Codex client, e.g. a codex CLI session read only
- idle anything; it gets handed to the app

--local forces the local path. clauodex release <thread> drops the hold manually; idle local threads release themselves when they finish. A thread with an active goal is handed to the app rather than merely dropped, so the goal keeps running there — goal continuation happens in whichever app-server holds the thread.

app/cli is genuinely read-only: a plain CLI session has no IPC router to route through.

Delegation

Codex Desktop's "one task manages other tasks" capability is a set of host-injected codex_app__* tools — an external program cannot load them. What it reproduces is their wire behaviour: the prompt is wrapped in a codex_delegation envelope carrying the calling task's id and sent as ordinary turn/start / turn/steer input.

clauodex send <target> "take over the migration" --from <source-thread>

The app renders only the prompt, tags it "Sent by Codex from another chat", and links back to the source task. clauodex builds the envelope byte-compatibly with the app's own builder and decodes it on read.

How it works

A background daemon (started on first use) holds a codex app-server child process and a client registration on the app's IPC router, so threads stay loaded between CLI invocations and running turns can be steered. State lives in ~/.clauodex; threads themselves live in CODEX_HOME and are shared with every other Codex client, which is why threads you create here show up in the app.

Environment

Variable Effect
CODEX_HOME Codex data directory (default ~/.codex) — honoured like the Codex tools do
CLAUODEX_HOME clauodex state directory (default ~/.clauodex)
CLAUODEX_CODEX_BIN use a specific codex binary
CLAUODEX_FORCE_TCP use the loopback-TCP daemon transport instead of a unix socket

The codex binary is auto-detected, preferring the desktop app's bundled build (usually a newer alpha, and always the build whose protocol version matches the threads the app writes) and falling back to the standalone install layout and then $PATH.

Platforms. macOS and Linux are supported. Everything works without the desktop app installed — you just lose the codex-app routing, so app-owned threads become read-only. On Windows the app-server features fall back to a loopback-TCP daemon transport; driving the desktop app needs its unix-socket IPC router and is not available there.

Notes

  • Every turn spends your Codex quota. There is no dry-run.
  • After a steer, the in-flight turn is recorded as interrupted and a fresh turn continues with your message injected. That is Codex's own steer semantics, not a failure.
  • On codex-app threads, wait and queue detect "turn finished" by watching the thread's rollout file go quiet (~8s lag), because the app does not expose its in-memory turn state.
  • Approvals for codex-app threads appear in the app's UI and are answered there; clauodex approvals covers clauodex's own threads.

Compatibility

Built against Codex 0.146.0-alpha.3.1 (desktop app) and verified against 0.145.0 (Homebrew CLI). Both protocols are internal to Codex and unversioned in any public sense — a Codex update can change them. clauodex doctor is the first thing to run if something stops working, and reference/protocol.md documents how to regenerate the app-server types and re-extract the IPC method table from a new build.

License

MIT

About

Drive Codex threads from your terminal or Claude Code - list, read, start, and steer/queue/interrupt turns running inside the Codex desktop app

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages