
Codex Gives Your Terminal Agent Status Signals
Codex’s 0.163.0 prerelease adds Program Status Protocol signals so terminals can distinguish working, done, error, and the kinds of prompts that block an agent—without scraping screens or watching window titles. We explain how the signals latch until you interact, what to expect from terminal integrations, and cover recent changes to managed worktrees, image previews, model catalogs, and WebSocket request limits.
Chapter 1
Codex Speaks OSC 7501
Ethan Park
Morning, everyone. Before anything else, thanks to Jellypod for helping make this daily show a reality. It's Thursday, October 15th, and today's topic is how Codex now tells your terminal exactly what it's doing.
Ethan Park
On October 14th, commit dec5491, pull request 54114 from contributor cconger, landed on main. It makes the Codex TUI speak Mitchell Hashimoto's Program Status Protocol, which he published on October 6th. It's carried over OSC 7501, a terminal escape sequence. It's in the 0.163.0 prerelease builds, including alpha 11. The latest stable is still 0.162.1, so you won't see it there yet.
Maya
Let me set up why this matters, because the before picture is where the pain is. Before this change, the TUI collapsed completed turns and failed turns into the same generic idle state. When it was blocked on a prompt, it didn't say why. And blocking detection depended on whether you had terminal title changes enabled at all.
Maya
If you run several sessions across tmux panes, Zellij tabs, Ghostty windows, or an agent manager, you know the workaround. Tools scrape the screen or watch the window title, and they match patterns like spinner glyphs to guess whether an agent is working. It's fragile, and it breaks when a glyph changes.
Ethan Park
Here's what Codex emits now. The sequence is escape, right bracket, 7501, semicolon, then key value fields separated by colons, then a string terminator. When a live turn finishes successfully, it sends state equals done, colon, app equals codex. When a live turn fails, state equals error. And when it's stuck waiting on you, it sends state equals blocked with an extra field, kind.
Ethan Park
There are three kinds. Permission covers tool execution approvals, filesystem grant prompts, apply_patch confirmations, MCP elicitation approval actions, and app link install or enable requests. Question covers request_user_input, MCP elicitation in form mode, and unanswered asynchronous questions once the agent has stopped. Auth covers user verification overlays and Gov MCP authentication prompts. Per the commit, this classification also catches requests hidden behind another view or delayed while you're typing, and it no longer depends on your title settings.
Maya
The detail I'd focus on is latching. Done and error stay set until you deliberately interact. That means any key press that isn't a key release, a non empty paste, or a mouse click, drag, or scroll. Mouse movement does not count. The commit has a test for exactly this: it completes or fails a turn, hovers the mouse, confirms the status is unchanged, then clicks and confirms it drops to idle.
Maya
Practically, that means a badge on a background tab won't clear because your cursor happened to cross the window. It stays until you actually attend to that pane.
Ethan Park
On how to use it: there's no flag, as far as the change describes. It's on in the TUI on main and in 0.163.0 alpha 11 and later. Terminals that don't recognize OSC 7501 ignore it. Terminals that do, like Ghostty through libghostty, can consume it natively.
Ethan Park
If yours doesn't, you can read it yourself. Match the stream with a pattern that captures the state value after state equals, plus the optional kind field. Then wire it up. When state is blocked and kind is permission, fire a desktop notification with notify send on Linux or osascript on macOS. When state is done, flash the pane border. A blocked permission prompt is the one worth interrupting yourself for, since the agent can't do anything until you answer.
Maya
Existing iTerm2 support is preserved. The OSC 21337 integration still works, with done and error mapping to Idle, shown in green. Blocked maps to Waiting, in blue. Working is orange.
Maya
Now the caveats, because they decide whether your notifications are trustworthy. Replayed turns, from thread history or a resumed session, are classified as idle, so you won't get a false done alert when you resume. Interrupted turns, whether you hit Ctrl+C or Escape, also go to idle rather than error. So error means a real failure, not you cancelling.
Maya
And pending follow up work and active goals keep the state at working. In a multi turn goal, you won't get a done between intermediate steps. Only the final result fires. One more thing: this is prerelease, so I'd treat the exact field set as subject to change until it ships stable.
Chapter 2
Smaller Changes Worth Knowing
Ethan Park
A few smaller items from the last day. The biggest is a cleanup, and it connects to our October 2nd episode. We told you to set features.worktrees equals true in ~/.codex/config.toml to enable managed worktrees. Pull request 54175, merged October 15th, retires that flag.
Ethan Park
Managed worktree creation and repository aware session discovery no longer check any feature flag. They still require a trusted local workspace. features.worktrees is now ignored, and so is features.realtime_conversation. Voice availability in the TUI now follows platform support. Leftover lines in your config won't break anything, but Codex warns if managed requirements reference them, and both flags are hidden from /experimental. You can delete those lines.
Maya
Second, pull request 54216 adds image previews in the fullscreen transcript. Local viewed images and generated image artifacts render as bounded thumbnails using Kitty or Sixel graphics. Viewed images show when their activity is expanded or in detailed presentation. Generated images appear next to their saved path entry. Previews are removed when overlays open, and image rows stay out of search and text selection. On remote workspaces, unsupported terminals, missing files, or oversized images, you just get the text entry.
Ethan Park
Two more fixes. Pull request 54169 reloads the model catalog after you sign in or out, so the model list no longer holds stale provider settings or needs a restart after managed provider requirements change. And pull request 54135 removes the 8 KiB inbound request limit on direct exec server WebSockets. Previously, a larger fs/writeFile request would disconnect the executor. Message and frame limits still apply.
Maya
If you want something to try today, install the 0.163.0 alpha 11 build and run a long task in a background tab. Then see whether your multiplexer or terminal reacts to the blocked and done states. That's the quickest way to find out whether you can drop your screen scraping scripts.