Customizable status line

Open 💬 29 comments Opened Apr 14, 2026 by pkondaurov
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Feature Request

Problem

Claude Code has a built-in customizable status line feature that allows users to display useful real-time information at the bottom of the terminal UI — token usage, model name, rate limits, context window, git branch, etc.

This is configured via a simple shell script hook in settings:

{
  "statusLine": {
    "type": "command",
    "command": "/bin/bash ~/.claude/statusline.sh",
    "padding": 0
  }
}

The script receives JSON context on stdin and returns formatted text. This is incredibly useful for power users who want to monitor their session at a glance.

Codex CLI currently has no equivalent mechanism. There's no way to display custom information in the TUI — no status line, no hooks, no plugin system for UI customization.

Proposed Solution

Add a statusLine (or similar) configuration option to ~/.codex/config.toml that allows running an external command and rendering its output in the Codex TUI (e.g., at the bottom of the screen).

Something like:

[status_line]
command = "/bin/bash ~/.codex/statusline.sh"
refresh_interval_secs = 10

The command would receive session context (model, token count, etc.) as JSON on stdin and return a single line of text (with ANSI colors) on stdout.

Use Cases

  • Display current model and token/context usage
  • Show API rate limit status and reset times
  • Display git branch and repo info
  • Show project-specific metadata
  • Integration with external monitoring tools

Why This Matters

For users who switch between Claude Code and Codex, the lack of a status line in Codex is a noticeable gap. The status line is a low-cost, high-value feature that significantly improves the interactive experience.

View original on GitHub ↗

29 Comments

github-actions[bot] contributor · 3 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #16921
  • #16393

Powered by Codex Action

etraut-openai contributor · 3 months ago

Have you tried the /statusline command? It's a little less flexible than an arbitrary script, but it's much easier to configure. Does this meet your needs?

joshka · 3 months ago

I'd like to be able to see my jj-vcs status (change id etc.) in the status line.
It's likely not a small task to invest in making jj a core part of the product, but allowing a hook like this seems like a reasonable compromise https://github.com/openai/codex/issues/16921 seems like they have a good solution to this with a proposed PR ready to review

dlwss · 3 months ago
Have you tried the /statusline command? It's a little less flexible than an arbitrary script, but it's much easier to configure. Does this meet your needs?

The current exposed features have significantly enhanced the functionality, and they can meet the needs of most users in various scenarios. However, I still hope to be able to add an extension point similar to the Statusline of CC CLI. It can store some user-defined data. If it can be made available, I would be very grateful.

jage9 · 3 months ago

Found this while researching this exact idea.
/statusline is actually a decent compromise, though I would still like to have control over the wording and order for conciseness.
For example, I have my Claude one at
5H: 96% | 7D: 100% | context: 89% | Sonnet 4.6
Since I use a screen reader, being able to set the order is important to me.

YitzhakMizrahi · 2 months ago

The built-in /statusline command is useful, but it does not fully cover the use case of a dynamically refreshed status provider. The gap I am running into is less "show one more built-in field" and more "let the user define what the statusline and/or terminal title should say while a session is running."

Useful shape:

  • A configurable command or template that receives current session context, such as model, cwd, repo/branch, approval mode, sandbox mode, turn state, and token/context usage when available.
  • Automatic refresh on a timer and on relevant session events, rather than requiring manual updates.
  • Separate control for the visible statusline/footer and the terminal/window title.
  • User-defined ordering, visibility, and formatting, which helps both compact multiplexer panes and accessibility workflows.
  • Safe failure behavior: if the command times out or exits nonzero, keep the previous value or render nothing, but do not block the TUI.

This would make /statusline a good default for most users while still giving power users a narrow extension point for project-specific or workflow-specific context.

RoggeOhta · 2 months ago

Adding another +1 for command-driven customization specifically, not just selecting built-in /statusline fields.

The current /statusline is useful, but the gap vs Claude Code is the extension point: let users run a command/script, pass Codex session context as JSON on stdin, and render stdout with safe timeout/failure behavior.

Use cases:

  • Show project-specific info that Codex will never know as built-in fields, e.g. jj change id, k8s context, CI/deploy status, ticket id, custom quota/spend.
  • Preserve a compact house style across tmux/zellij panes.
  • Support accessibility by controlling exact wording/order rather than choosing from fixed labels.

A built-in /statusline default and an opt-in command provider could coexist: default remains simple, power users get a narrow, predictable extension hook.

akamalov · 2 months ago

+1

SakaZulu · 2 months ago

Thanks, I noticed #17827 is very closely related.

I am fine with this issue being treated as a duplicate if that helps tracking. The main point I wanted to emphasize is the same as the later comments in #17827: the built-in /statusline picker is useful, but the missing piece is a command-driven extension point.

For my use case, the important part is not just adding more built-in fields. It is allowing a user-provided command to receive Codex session context as JSON on stdin and render stdout back into the TUI, preserving ANSI colors and custom formatting, with timeout/failure safeguards.

That would let the built-in /statusline remain the simple default while enabling advanced users and community tools to build richer status lines.

lapcchan · 2 months ago

/statusline customize is ready. it's just i can't change the color of the statusline...

akamalov · 2 months ago

when will it get merged to main?

kanine · 2 months ago

<img width="437" height="26" alt="Image" src="https://github.com/user-attachments/assets/70173c24-3343-40e7-9e75-d85a2295a6bc" />

I just finished customizing my statusline in another app and stumbled upon this request. This is reminiscent of the old days of internet quotas. I used to track with over/under indicators like I've done here.

Adding a similar scripting ability to Codex is a +1 from me.

CondorCommodore · 2 months ago

Adding another concrete use case for command-backed status-line support:

I need to show local coordination/watch health in the Codex TUI footer, e.g.

watchers:live
watchers:stale
watchers:dead

The status comes from a local script that checks a daemon PID, output freshness, and pending inbox events. Today I can approximate this with UserPromptSubmit hooks that emit systemMessage, but that is not equivalent: it only appears at turn boundaries and only as transient transcript output. The operator still has no persistent footer signal that the watcher is healthy while working.

The current [tui].status_line = [...] built-in picker is useful for Codex-owned state, but this is external workflow state. A command-backed status-line item or banner would solve it cleanly:

[tui]
status_line = [
  { type = "command", command = "~/path/to/statusline-watchers.sh", timeout_ms = 200 },
  "model-with-reasoning",
  "current-dir",
  "context-usage",
  "weekly-limit"
]

Key requirements from this use case:

  • runs on startup and periodically / turn-start
  • bounded timeout
  • command stdout renders as one compact status segment
  • failure should degrade to an omitted or error segment, not break the TUI
  • no need for secrets or model context; cwd/session id are enough

This would let Codex support project-local operational telemetry without expanding the built-in status enum for every workflow-specific field.

stormzhang · 1 month ago

+1. I maintain token-tracker, which renders a rich quota / context / cost statusline on Claude Code via its official StatusLine API — but on Codex I'm stuck with the default style, since there's no custom hook. Same data locally, no way to render it.

!Claude Code statusline

Copying Claude Code's design would close the gap — a command that gets session JSON on stdin and prints a styled string to stdout:

[tui.status_line]
type = "command"
command = "~/.codex/statusline.sh"

Keep the enum items as default, treat command as opt-in. Happy to test a branch.

aqua5230 · 1 month ago

+1 — this is the single biggest gap for me when switching between Claude Code and Codex.

A concrete reference that this is both feasible and high-value: I maintain usage, a macOS menu-bar/TUI tool that pins Claude Code + Codex quota to the screen (all from local files — no API calls).

On the Claude Code side it ships exactly the statusLine command hook proposed here, and renders something like:

usage(main) | 5h ▕███████▏ 99% (9min left) | 7d ▕█▏ 11% (6d13h left)

…with unicode meters, per-threshold colors, and a derived "time-until-reset" — all from a single script that reads local files off stdin.

On the Codex side we're limited to the fixed tui.status_line enum, so the best we can offer users is plain text:

5h 4% left · weekly 33% left · Context 68% left · gpt-5.5 medium

Same underlying data, but we can't draw the meters / colors / countdowns because there's no command-backed hook to render arbitrary output.

The proposed [status_line] command = "..." shape (JSON context on stdin → one ANSI line on stdout) is exactly right — it mirrors Claude Code 1:1, so existing scripts and tools port over with near-zero friction. If this lands, we'd ship Codex support for it the same week. 🙏

vittoriohalfon · 1 month ago

I've prototyped a minimal version of this and would be glad to contribute it if the team is open to an invited PR (I see contributions are invitation-only — happy to follow whatever process you prefer).

Design — one self-contained [tui] key, with no change to the existing status_line item list:

[tui]
status_line_command = { command = ["my-script"], timeout_sec = 5, interval_sec = 10, position = "end" }

The command is fed session context as JSON on stdin (model, reasoning_effort, cwd, git_branch, session_id, approval_mode, sandbox_mode, context_used_pct/context_remaining_pct, context_window, codex_version) and its first stdout line is rendered as a status-line segment — mirroring Claude Code's statusLine.command. Execution is async / non-blocking: it reuses the existing hooks command-runner pattern (configurable timeout, kill_on_drop), re-runs on an interval, and the output is sanitized to a single escape-free line so it can't corrupt the TUI.

It's implemented against main, kept intentionally small (no /statusline picker changes), with config-deserialize + TUI render tests passing and cargo fmt / clippy clean.

A couple of things I'd want the team's steer on before any PR:

  • Cross-surface consistency — should the same key eventually be honored by the IDE / web surfaces, or is this CLI-only for now?
  • Execution model — argv-direct (what I have) vs a shell string, to match whatever convention you'd prefer.

Happy to share the branch or adjust the design to fit your roadmap. Thanks!

Necmttn · 29 days ago

Command-backed status lines work if the contract is small and bounded. Send JSON with session id, model, cwd, git branch, approval/sandbox mode, context usage, quota snapshot, and version. Enforce timeout, refresh interval, max output width, and stale-output behavior. That lets local quota/watch tools render state without giving the command transcript access or blocking the TUI.

---

_Generated with ax._

AlanineX · 26 days ago

For anyone who mainly wants local host telemetry in the meantime, I published a small tmux-based workaround: https://github.com/AlanineX/codex-host-status

It does not replace the native feature request here. It wraps interactive codex sessions, leaves subcommands like codex exec / codex doctor untouched, and renders a compact status bar like:

🐍 base ⚙ CPU 4% 41C 🎮 GPU 2% 43C 0.6G 💾 RAM 10.1/47G 🕒 14:29

This covers my local CPU/GPU/RAM visibility use case while waiting for a real command-backed tui.status_line hook in Codex.

stormzhang · 26 days ago

+1 on this. I shipped a workaround for the same use case as an open-source CLI (token-tracker) and want to share what users actually need vs. what the built-in /statusline can express today.

What we ended up doing: since Codex has no command-backed statusline hook, we inject a two-line "faux statusline" via the Stop hook, returning systemMessage after every turn. It renders with 24-bit truecolor, shows project + branch + diff + session tokens + cost + 5h/7d quota + context %, and follows the active theme. (Verified: does not enter the model context.)

!Codex faux statusline screenshot

Why /statusline wasn't enough:

  • Fixed enum items don't compose into the multi-line layout users want (progress bars + diff stats + cost + reset countdowns).
  • No way to call external scripts that already track project context / usage.
  • No per-item theming/coloring control.

What would unblock the whole class of tools: exactly what Claude Code does — accept a command/script-based statusline (stdin JSON in, formatted text out). Today we're stuck with a hidden Stop-hook workaround that renders in the response area (not the bottom bar), depends on Stop-hook + systemMessage being stable, and is hard for new users to discover.

Happy to share implementation details if useful. Thanks for considering.

string-theorist · 21 days ago

+1. I run a workflow/governance tool that's meant to work across different agents, but it leans heavily on Claude Code's statusLine. We keep a little state file (active task, pipeline stage, drift, context left) that the hooks update, and the statusline just renders it. Codex already has the hooks now, there's just nowhere to show it natively. Would love to port it over: an opt-in { type = "command", command, timeout_ms } that gets the session JSON on stdin and renders stdout, with a timeout.

Thanks for the great work on this!

pzarzycki · 13 days ago

Related to this, here's a small tool. It is not a live status line, but it helps inspect local Codex/Claude session data so token usage and session details are less opaque, without API keys or sending logs anywhere.

Open source:
https://github.com/pzarzycki/token-companion

If you like it - leave a star; submit an issue or request, or even a PR!

lindestad · 12 days ago

Just want to add in that this would be extremely useful for improving the way the current statusline renders items when displaying multiple items. Codex cli is easiest to read when not set to the entire screen width, but then items overflow:

gpt-5.5 xhigh · ~/dev/project · Context 46% used · 5h 80% left · weekly … Vim: Normal

Being able to style these, and/or have some of them only appear at desired thresholds (like weekly/5h only appearing below a certain remaining level) enhances the statusline massively, it could instead render as

5.5 xhigh · ~/dev/project · Ctx 46% · 5h 80% · week 72% · Vim: Normal

This is the same statusline information, but it now renders all the information (weekly is cut off originally).

Allowing the user to do this would be fantastic.

ducky-duke · 11 days ago

+1

mark-undoio · 11 days ago

We ship a tool that integrates with coding agents and the lack of a flexible status line is quite painful to our customers - it means they've got no way to display progress information from within our stack when the agent is driving our tool. It makes the workflow more opaque for them as they can't tell what the agent is doing or why.

Ideally we'd be able to supply a default script for status line behaviour that less advanced users can just configure, with more advanced users being able to script whatever they want from our feedback and other sources.

Edit to add: Alternatively, the ability to supply a JSON blob for formatting / filtering within the agent's status line config would also work well.

jleme · 9 days ago

The current status line configuration is limited to built-in fields and does not support customer-specific workflow needs, such as command-backed content, semantic colors, or conditional indicators. Please consider supporting an extensible status line API.

Nutcasey · 6 days ago

I'd like to see this too.

shenxingy · 6 days ago

Adding a concrete, shipping use case for a command-backed status line (distinct from picking more built-in fields).

We ship $codex-usage as a Codex-native workflow. It reads rate-limit snapshots through the authenticated codex app-server protocol (it never opens auth.json) and renders a compact pace indicator against a 95%-utilization target. Its default output is already exactly one status line:

Clade(main) 🐣 -12% (6d)

i.e. <project>(<branch>) <pace-glyph> <±pace-vs-target>% (<resets-in>), and it also emits a machine-readable payload a hook could consume directly:

$ codex-usage --json
[
  {
    "limit_id": "codex", "name": "Codex", "window": "week",
    "used_percent": 2, "remaining_percent": 98,
    "resets_in": "6d", "pace_delta": -12.5, "projected_percent": 13.1
  }
]

The one thing we can't do is surface this persistently in the TUI. [tui].status_line is a fixed enum of built-in item ids, so today the pace line only lives in an on-demand invocation or a transient session-start message — it can't stay pinned in the footer the way Claude Code's statusLine.command keeps a custom renderer live.

The missing piece is exactly the extension point in this issue: Codex pipes session/rate-limit JSON to a user command on stdin and renders its stdout (first line, ANSI-aware) in the footer, with a timeout + fail-open so a slow or failing command never blocks the TUI. Additive to the existing field picker, roughly:

[tui]
status_line = ["current-dir", "git-branch"]   # built-in fields still work

[tui.status_line_command]                      # new: command-backed segment
command = ["codex-usage"]                       # already prints one status line
refresh_interval_secs = 30
timeout_ms = 800                               # on timeout / non-zero exit: keep last good line

PR #10170 already demonstrated a working implementation; the status surface has since been refactored into tui/src/bottom_pane/, so it would need a fresh pass on the current architecture rather than a straight rebase. Happy to help build and test it against a real renderer ($codex-usage) if there's maintainer appetite.

shenxingy · 6 days ago

I put together a working implementation on today's bottom_pane architecture: compare diff.

It adds a custom status-line item backed by [tui].status_line_command (argv) — Codex runs it on a timer, pipes a small JSON session snapshot ({cwd, git_branch, model}) on stdin, and renders the first stdout line, with a 1.5s timeout + kill-on-drop and fail-open (keeps the last good value), mirroring the async workspace-headline item. A snapshot diff re-runs it immediately on a branch/dir switch so the footer isn't stuck on stale data. Rebases cleanly on main; clippy/fmt clean; the command-runner unit tests plus the full status_line tui suite pass.

This repo limits opening PRs to collaborators, so I can't open one directly — happy to if a maintainer enables it, or the branch is here to cherry-pick: shenxingy:feat/status-line-command.

pavelbe · 4 days ago

+1. Use case: side-by-side multi-terminal agent workflows (Claude Code + Codex CLI in split panes). We render cross-session mailbox/peer badges in Claude Code via its statusLine command hook, but Codex's [tui].status_line only accepts built-in item identifiers — so the Codex pane can't show a symmetric indicator. A custom command item (or a single script-fed text item) would cover this.