Skip to content

feat(rprompt): display reasoning effort next to model in zsh rprompt#3087

Open
EmojiPati wants to merge 4 commits intotailcallhq:mainfrom
EmojiPati:feat/rprompt-reasoning-effort
Open

feat(rprompt): display reasoning effort next to model in zsh rprompt#3087
EmojiPati wants to merge 4 commits intotailcallhq:mainfrom
EmojiPati:feat/rprompt-reasoning-effort

Conversation

@EmojiPati
Copy link
Copy Markdown
Contributor

Summary

Show the currently configured reasoning effort (e.g. HIGH, MEDIUM) next to the model in the ZSH right prompt so users can see at a glance what effort level their agent is running with.

Context

The ZSH right prompt already surfaces the active agent, token count, cost, and model — but not the reasoning effort. Because effort level noticeably changes latency, cost, and output quality, users often forget what level they had configured during a session. The shell plugin already sets FORGE_REASONING__EFFORT as part of every forge invocation (shell-plugin/forge.theme.zsh:20), and the config layer (crates/forge_services/src/app_config.rs:51-66) resolves it into Option<Effort>, so exposing it in the prompt is the missing piece.

Changes

  • ZshRPrompt: added an Option<Effort> field rendered to the right of the model when set.
  • Display impl: renders the effort in uppercase (e.g. HIGH, XHIGH, NONE) preceded by a nerd-font lightbulb glyph (\u{eb41}) when nerd fonts are enabled. Uses YELLOW when the conversation is active (tokens > 0) and DIMMED otherwise, matching the existing pattern for the other segments.
  • ZshColor::YELLOW: new 256-palette color constant (3).
  • handle_zsh_rprompt_command: extended the tokio::join! to fetch reasoning effort in parallel with the existing model/conversation lookups and pipe it into the builder.

Key Implementation Details

  • No new service/DTO was introduced; the feature reuses ForgeAPI::get_reasoning_effort, which already honors FORGE_REASONING__EFFORT through ForgeConfig's env-var source (crates/forge_config/src/reader.rs:103-108). This means the per-session override set by the shell plugin (shell-plugin/forge.theme.zsh:20) is picked up automatically.
  • Effort::None is deliberately rendered as NONE so the user can tell that reasoning is explicitly disabled (vs. unset, which shows nothing).
  • Respects use_nerd_font: when nerd fonts are disabled the glyph is omitted and only the uppercase label is rendered.

Use Cases

  • At-a-glance confirmation of current effort before issuing a costly prompt: FORGE claude-opus-4-7 HIGH.
  • Noticing that a session accidentally dropped effort to MEDIUM after a provider switch.
  • Debugging whether FORGE_REASONING__EFFORT is actually propagating from the shell plugin.

Rendered Examples

  • Active (tokens > 0), nerd fonts on: 󱙺 FORGE 1.5k gpt-4 HIGH
  • Init state (no tokens): same segments but all DIMMED
  • Nerd fonts off: FORGE 1.5k gpt-4 LOW
  • No reasoning effort set: existing behavior — nothing is appended

Testing

# Unit tests (12 total in this module, 6 new for reasoning effort)
cargo test -p forge_main --lib zsh::rprompt

# Full crate (312 tests)
cargo test -p forge_main --lib

# CI lint commands (same ones enforced by .github workflows)
cargo +nightly fmt --all --check
cargo +nightly clippy --all-features --workspace --all-targets -- -D warnings
cargo +nightly clippy --all-features --workspace -- \
  -D clippy::string_slice -D clippy::indexing_slicing

New tests cover: active state rendering, init/dimmed state, XHighXHIGH uppercase, explicit Effort::None variant, nerd-font-off path, and a regression guard ensuring that None (unset) produces no output.

Links

  • Related file: crates/forge_main/src/zsh/rprompt.rs
  • Shell plugin integration: shell-plugin/forge.theme.zsh:20

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 20, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label Apr 20, 2026
Adds the currently configured reasoning effort (e.g. HIGH, MEDIUM) to
the right of the model in the ZSH right prompt. Follows the existing
active/inactive (bright/dimmed) color pattern, renders a nerd-font
lightbulb glyph when nerd fonts are enabled, and picks up session
overrides set via the FORGE_REASONING__EFFORT env var.
@EmojiPati EmojiPati force-pushed the feat/rprompt-reasoning-effort branch from 8b7b851 to 5c3a65e Compare April 20, 2026 03:45
Comment thread crates/forge_main/src/zsh/rprompt.rs Outdated

// Add reasoning effort (rendered to the right of the model)
if let Some(ref effort) = self.reasoning_effort {
let effort_label = effort.to_string().to_uppercase();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets select just the first 3 letters:

low
med
hig
xhi
max

Hide it if its none

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review.

Hiding none makes sense — I'll include that in the next push.

The one thing I'd like to run by you is the abbreviation. On wider terminals the short forms feel a bit cryptic, while the full labels still fit comfortably. Would you be open to making this width-aware — using the short form when the terminal is narrow, and the full label when there's room? That way we keep things tidy on smaller screens without giving up readability on full-screen setups.

Happy to go either way, just wanted to raise it before implementing.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed the width-aware version. Narrow terminals show the three-letter form (MED, HIG, etc.), and it expands to the full label (MEDIUM, HIGH) on wider setups. none stays hidden.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image I tested it, and it’s still showing the full word instead of just three characters. Also, can we remove the icon before it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @amitksingh1490 , thanks for testing!

On the full label showing instead of the 3-letter form — that's actually the intended behavior we agreed on with @tusharmath above (#3087 (comment)). The label is width-aware: it collapses to the three-letter form (MED, HIG, XHI, MIN, MAX) only when the terminal is narrower than 100 columns, and expands to the full uppercase label (MEDIUM, HIGH, XHIGH, MINIMAL) at 100 columns or wider, so we don't sacrifice readability on full-screen setups.

From your screenshot it looks like your terminal is ≥100 columns, which is why you're seeing the full form. You can verify the switch quickly with:

COLUMNS=80 forge zsh rprompt # -> MED / HIG / XHI
COLUMNS=120 forge zsh rprompt # -> MEDIUM / HIGH / XHIGH
COLUMNS=100 forge zsh rprompt # -> full (threshold is inclusive)

Or just resize your terminal below 100 columns and the RPROMPT will update on the next refresh. The threshold lives in crates/forge_main/src/zsh/rprompt.rs as WIDE_TERMINAL_THRESHOLD = 100. Happy to tune it if you feel 100 is too generous — just let me know what width you'd prefer.

On the icon — I intentionally kept a glyph there for visual symmetry with the model segment right before it. The model already renders with a nerd-font icon (\u{ec19}) as a prefix, so the reasoning effort follows the same pattern with a matching lightbulb glyph (\u{eb41}) — together they read as two icon-prefixed labels belonging to the same group. Dropping the icon would make the reasoning segment visually inconsistent with the model/agent/token segments, all of which are glyph-prefixed.

If you still prefer it gone after that rationale, I'm happy to drop it — just wanted to surface the symmetry reasoning first in case we want to keep it.

Copy link
Copy Markdown
Contributor

@amitksingh1490 amitksingh1490 Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok can we drop the icon, as we show model name and reasoning effort is property of model doesn't need its own icon? I checked on smaller width its working properly

EmojiPati and others added 3 commits April 20, 2026 07:41
Per review feedback, the \`Effort::None\` variant carries no useful
information for the user (it means 'no reasoning' — same effective
state as having reasoning unset), so the rprompt now suppresses it
entirely instead of rendering the literal text 'NONE'.

The corresponding test was updated to assert the new hidden behavior.
Render the reasoning effort as a three-letter abbreviation (MIN, LOW,
MED, HIG, XHI, MAX) when the terminal is narrower than 100 columns,
and as the full uppercase label (MINIMAL, LOW, MEDIUM, HIGH, XHIGH,
MAX) when wider. This keeps the prompt compact on small screens while
preserving readability on full-screen setups.

Width is sourced from the $COLUMNS env var propagated by the zsh
shell plugin. Callers that do not supply a width default to the
full-length label.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature Brand new functionality, features, pages, workflows, endpoints, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants