[BUG] statusLine command receives "high" instead of "xhigh" for effort level
Status Fixed / completed
Reported on v2.1.179
Maintainer reply None cached
Activity 5 comments · opened Jun 17, 2026 · closed Aug 20, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When effort is configured to xhigh, the JSON passed to a statusLine command reports "level": "high" in the .effort.level field instead of "xhigh". This makes it impossible for a status line script to distinguish between high and xhigh effort.
What Should Happen?
Expected: .effort.level = "xhigh"
Actual: .effort.level = "high"
Error Messages/Logs
Steps to Reproduce
- Set effort to xhigh (/effort xhigh)
- Configure a statusLine command that reads .effort.level from the piped JSON
- Observe the value is "high", not "xhigh"
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.179 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
4 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
I don't think this is a duplicate of #69068
Conversation w/ my Claude Code:
There it is - Claude Code is actually sending "high" in the JSON even though your session is set to xhigh. This is a bug in Claude Code's status line data, not in your script.
Your script is correct and already handles xhigh - the problem is upstream. I'd recommend filing a bug at https://github.com/anthropics/claude-code/issues linking to issue 69068, since the
docs say xhigh should be reported but the actual JSON payload is collapsing it to high.
Let me remove the debug logging now:
⏺ Update(~/.claude/statusline-command.sh)
⎿ Removed 1 line
8 # Color: only the ctx bar is colored, by usage band (<30 green, 30-59 yellow, >=60 orange).
9
10 input=$(cat)
11 -echo "$input" > /tmp/statusline-debug.json
11
12 model=$(echo "$input" | jq -r '.model.display_name // "unknown"')
13 model=${model#Claude } # "Claude Opus 4.8" -> "Opus 4.8"
⏺ And I'll save a memory so I don't repeat the bad claim in a future session:
Recalled 1 memory, wrote 2 memories (ctrl+o to expand)
⏺ Confirmed: Claude Code bug. The JSON sends "high" when the session is xhigh. Your script is fine. Worth filing on that issue if you want it tracked.
✻ Crunched for 47s
❯ I filed a bug. They're trying to close it as a duplicate of one related to "ultra code". But, I think this is a different issue.
⏺ The distinction is clear: the ultracode issue is about ultracode not reporting as xhigh. Your issue is the inverse - you explicitly set /effort xhigh (no ultracode involved at all) and the
field still comes back as "high". Different trigger, different reproduction path.
The argument for keeping it open: your repro is simpler and more direct. You can reproduce it with just /effort xhigh in a plain session - no ultracode, no keyword needed. If the ultracode
fix only addresses the ultracode path, /effort xhigh could remain broken after that fix ships.
Worth commenting on the issue with exactly that framing: "This reproduces without ultracode - just /effort xhigh in a normal session. The status line JSON returns \"level\": \"high\". If
the duplicate fix only addresses the ultracode path, this case may still be broken after it lands."
Oh, this may be a slightly different bug. The bug might be that Claude Code /effort lets you select "xhigh" for Sonnet. But, Sonnet tops out at "high".
Conversation w/ Claude Code:
OK. Wait. Why does "effort xhigh ●●●●○" show up when the model is Opus and not when it's Sonnet?
⏺ Good question. Let me get you an authoritative answer rather than guess at the exact gating logic.
⏺ claude-code-guide(Why effort indicator shows on Opus not Sonnet)
⎿ Done (6 tool uses · 36.5k tokens · 33s)
(ctrl+o to expand)
⎿ Allowed by auto mode classifier
⏺ Short version: it's a model-capability thing, not a bug.
The effort chip in Claude Code is tied to how many effort tiers the active model supports, and which one you've selected:
filled to that level (●●●●○).
chip rather than advertising a level the model can't run.
In other words, the chip reflects your selected tier as actually applied to the current model. On Opus, xhigh is real, so it renders. Switch to Sonnet and xhigh collapses to plain high
(which is also Sonnet's default), so there's nothing distinctive to show and the chip drops off.
If you want the chip to stay visible on Sonnet, you'd need to be on a tier it genuinely supports — but note high is already its default, so there's no higher gear to engage there.
One caveat worth flagging given your setup: this built-in chip is separate from your custom statusline effort display, which has that known upstream bug where Claude Code reports "high" in
the status-line JSON even when effort is actually xhigh. So don't be surprised if your custom statusline and this built-in chip disagree on Opus — the script is correct; the JSON it's fed
is wrong.
Same root cause appears to affect
maxas well, not justxhigh.Setup:
statusLinescript reads.effort.levelfrom stdin JSONRepro:
/modeland selectmaxeffort. Confirmation toast correctly reads: "Set model to [Model] and saved as your default for new sessions with max effort" — so the setting itself registered correctly..effort.levelfield still reports"high"instead of"max".highinstead ofmax.This looks like the same serialization bug as the
xhighcase reported here — the backend appears to cap.effort.levelat"high"for any level above it (xhigh,max), rather than passing the actual configured value through to the statusLine hook and in-task UI.