Status line: no way to distinguish ultracode from xhigh (no `ultracode` field in stdin JSON)

Status Open
Reported on v2.1.169
Maintainer reply None cached
Activity 4 comments · opened Jun 17, 2026

What I'm trying to do

Surface the active ultracode mode in a custom status line.

Problem

The status line stdin JSON exposes reasoning effort via effort.level, but ultracode is deliberately collapsed into xhigh and there is no separate signal. From the docs (https://code.claude.com/docs/en/statusline):

effort.level — Current reasoning effort (low, medium, high, xhigh, or max). [...] Ultracode is not a distinct level and reports as xhigh.

The full status line JSON schema contains no ultracode field (neither top-level nor nested), and per https://code.claude.com/docs/en/model-config ultracode is a session-only setting that is not written to settings.json. Consequently a status line script has no data source from which it could tell whether the current session is in plain xhigh or in ultracode — they are indistinguishable.

Request

Expose an explicit ultracode indicator in the status line stdin JSON, e.g. a top-level boolean "ultracode": true or a nested effort.ultracode: true, so custom status lines can render it (the same way effort.level is already surfaced).

Why it matters

ultracode changes orchestration behaviour (dynamic multi-agent workflows) and token usage substantially, so being able to see at a glance that a session is in ultracode — not just xhigh — is useful for cost/behaviour awareness.

Environment

  • Claude Code version: 2.1.169 (Claude Code)
  • Platform: macOS (darwin)

View original on GitHub ↗

3 Comments

afram123 · 2 months ago

Worth linking this to where the confusion starts. On the input side, the /effort picker presents ultracode as the top option next to the real tiers ("low, medium, high, xhigh, max, ultracode, auto"), so users believe it is a higher effort than max — then the status line can't reflect it because, exactly as you and #63468 note, ultracode isn't a distinct level; it is xhigh + dynamic-workflow orchestration tracked as a separate session flag.

Your ask (a first-class ultracode field in the stdin JSON) is the right fix on the status-line side. The matching fix on the input side is to stop presenting ultracode as a peer effort tier in the selector — or to annotate it as "xhigh + dynamic workflow orchestration" (the CLI already ships that string), so the two sides agree.

Broader labeling/transparency issue: #69653.

laggarcia · 1 month ago

+1 — fresh data point confirming this is still the case on v2.1.215 (Linux/Fedora 44), and that there is currently no reliable path to this information at all.

Use case: a custom multi-line status line that displays effort.level in a session-status segment. Ultracode materially changes session behavior (workflow orchestration and the token spend that comes with it), so "xhigh" versus "ultracode" is exactly the kind of state a status line exists to surface — but the stdin JSON makes them indistinguishable.

What I verified on 2.1.215:

  • /effort ultracode confirms with "Set effort level to ultracode (this session only): xhigh + dynamic workflow orchestration", but the statusline JSON still reports effort.level: "xhigh".
  • This appears to contradict #77812, which reports that the /effort ultracode path (as opposed to the /model picker) emits "ultracode" — I could not reproduce that on Linux/2.1.215. Whatever inconsistency existed there, the field collapses to "xhigh" on this platform and version through both paths.
  • The persistent "ultracode": true settings key is likewise not reflected anywhere in the statusline payload.

Current workaround, for anyone landing here: have the statusline script read "ultracode" from ~/.claude/settings.json with jq and show a marker when it is true and the stdin effort.level is "xhigh". That approximates the configured default but cannot track live state — mid-session /effort changes in either direction are invisible.

Suggested shape: a boolean sibling (effort.ultracode: true) rather than a new effort.level value, since ultracode is documented as a Claude Code setting layered on top of xhigh rather than a distinct model effort level — that would keep effort.level a clean enum for existing scripts while making the toggle observable.

dvainrub · 1 month ago

Adding two things that strengthen this: how cheap the fix looks, and a working (if fragile) workaround.

The state already exists internally, it is just dropped before the statusline metadata. On 2.1.216, selecting ultracode issues apply_flag_settings { effortLevel: "xhigh", ultracode: true }; the ultracode boolean lives in session AppState and get_settings already returns an applied.ultracode. The statusline/hook metadata is built by notifyMetadataChanged({ effort_level }), which emits only effort_level and omits the boolean. So effort.ultracode (or a top-level ultracode), plus $CLAUDE_ULTRACODE for hook parity with $CLAUDE_EFFORT, is an additive change to that one payload.

Version note (2.1.216): the /effort → effort.level:"ultracode" behavior reported in #77812 (2.1.210) is gone here; both the /effort and model-picker paths now report effort.level:"xhigh", so there is currently no field-based signal at all.

Workaround that works today (fragile). Ultracode injects a per-turn ` <system-reminder> whose transitions are persisted into the transcript as attachment records ultra_effort_enter / ultra_effort_exit. A statusline handed transcript_path` can read the last one:

grep -aE '"ultra_effort_(enter|exit)"' "$transcript_path" \
  | jq -rs 'map(select(.type=="attachment" and ((.isSidechain // false)|not) and ((.attachment.type // "")|startswith("ultra_effort_")))) | last | .attachment.type // ""'
# "ultra_effort_enter" => ultracode ON

Caveats an official field would remove: undocumented internal format, and eventually-consistent (the enter/exit marker is only written when the next user prompt builds its attachments, so changing /effort without sending a message shows the stale state until the next turn). Verified on 2.1.216, macOS.

Showing cached comments. Read the full discussion on GitHub ↗