Skip to content

feat: to #2767, support verbose and compact mode swither with ctrl-o#2770

Open
chiga0 wants to merge 1 commit intoQwenLM:mainfrom
chiga0:feat/add-verbose-mode-switcher
Open

feat: to #2767, support verbose and compact mode swither with ctrl-o#2770
chiga0 wants to merge 1 commit intoQwenLM:mainfrom
chiga0:feat/add-verbose-mode-switcher

Conversation

@chiga0
Copy link
Copy Markdown

@chiga0 chiga0 commented Mar 31, 2026

TLDR

Adds a compact/verbose mode toggle (Ctrl+O) to Qwen Code. In compact mode (default), tool result output and model thinking-chain are hidden, keeping the
terminal clean during long agentic runs. Pressing Ctrl+O switches to verbose mode, revealing full tool output and thoughts. The setting persists across
sessions via ~/.qwen/settings.json, and a verbose label appears in the footer when active.

Screenshots / Video Demo

demo gif

Compact mode (default) — tool calls show name + status only, no output noise:
✓ ReadFile src/index.ts
✓ Edit src/index.ts
✓ Bash npm run build

Verbose mode (Ctrl+O) — full tool output visible, verbose indicator in footer:
✓ ReadFile src/index.ts
1 import React from 'react';
...

✓ Bash npm run build
▎ build
▎ tsc --project tsconfig.json
▎ Done in 2.3s

Dive Deeper

Architecture: Rendering-layer filtering via React Context. No changes to the data model or streaming pipeline — VerboseModeContext distributes
verboseMode and frozenSnapshot state from AppContainer to:

  • HistoryItemDisplay — gates gemini_thought / gemini_thought_content renders behind verboseMode
  • ToolMessage — computes effectiveDisplayRenderer: passes through in verbose mode, returns { type: 'none' } in compact mode (interactive shell
    prompt is unaffected)
  • MainContent — uses frozenSnapshot to freeze the pending items viewport while streaming, preventing layout jitter when toggling mid-stream;
    auto-unfreezes when streaming completes
  • Footer — shows verbose label (localised) when verbose mode is active

Key design decisions:

  • Compact is the default (verboseMode: false) — matches the target UX of a clean terminal by default
  • pendingHistoryItems useMemo was moved earlier in AppContainer (before handleGlobalKeypress) to avoid stale closure / TDZ issues when referenced in
    the Ctrl+O handler
  • refreshStatic() is called on toggle to remount Ink's <Static> component, applying the mode change retroactively to already-rendered history
  • IdentityFile approach for SSH key (non-breaking, no changes to auth)

Localization: verbose key added to en, zh, de, ja, ru, pt locale files.

Reviewer Test Plan

  1. Build: npm run build — should pass with zero TypeScript errors
  2. Tests: npm test — all 238 test files should pass
  3. Default compact mode: Launch the CLI, run a tool-heavy prompt (e.g. list all files in src). Tool result output should be hidden; only tool name +
    status icon shown.
  4. Toggle to verbose: Press Ctrl+O. The verbose label should appear in the footer. Re-run a prompt — full tool output should now be visible.
  5. Toggle back: Press Ctrl+O again. verbose label disappears, tool output hidden.
  6. Persistence: Toggle verbose on, exit the CLI, relaunch — should still be in verbose mode. Check ~/.qwen/settings.json for "ui": { "verboseMode": true }.
  7. Mid-stream toggle: Start a long-running prompt, press Ctrl+O while streaming. Viewport should freeze until the stream completes, then
    auto-unfreeze.
  8. Thinking chain: Use a model with reasoning/thinking enabled. In compact mode, <think> blocks should be hidden. In verbose mode, they should
    appear.
  9. Shell tool: Verify that interactive shell (Ctrl+F focus) still works normally in compact mode — the shell input prompt must not be gated by
    verbose mode.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Validated on macOS (Apple Silicon) via npm run.

Linked issues / bugs

Closes #2767

Copy link
Copy Markdown
Collaborator

@tanzhenxin tanzhenxin left a comment

Choose a reason for hiding this comment

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

Code Review

Hey @chiga0 — thanks for the effort on this, the compact/verbose toggle is an interesting idea!

However, we have some concerns that need to be addressed before this can move forward.

Default behavior change is too disruptive

The biggest issue: this PR changes the default display behavior. Currently, thinking blocks (gemini_thought, gemini_thought_content) are always visible. After this PR, they're hidden by default (verboseMode: false). This is a significant UX regression for existing users who rely on seeing the model's reasoning. We can't accept a change that silently alters the default experience like this.

If you'd like to continue with this feature, the default should be verboseMode: true (preserving current behavior), with compact mode as an opt-in.

Critical issues

  1. useCallback dependency regressionAppContainer.tsx

    • The dependency settings.merged.general?.debugKeystrokeLogging was replaced with settings (the full object). Since settings creates a new reference on every render, this defeats useCallback memoization entirely and causes handleGlobalKeypress to be recreated every render. Please keep the original granular dependency and access setValue separately.
  2. Compact mode hides actively-executing shell outputToolMessage.tsx

    • In compact mode, effectiveDisplayRenderer is unconditionally set to { type: 'none' }, which hides the live ansi output of running shell commands. Users would be typing into a shell blind — they can see the input prompt but not the command output. At minimum, ansi-type displays should be exempted when a tool is actively executing.

Suggestions

  1. Asymmetric frozen snapshot behavior — Frozen snapshot is only created when toggling TO verbose mode during streaming, not when toggling to compact. Switching to compact mid-stream causes tool outputs to disappear abruptly.

  2. Copyright header — New file VerboseModeContext.tsx says "Copyright 2025 Google LLC". New files should reflect the Qwen Code project.

  3. Missing translations — Non-English locales (except Chinese) use the untranslated English string "verbose".

Please address the default behavior change and the critical issues. Happy to re-review once updated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add verbose/compact mode toggle (Ctrl+O) to reduce tool output noise

2 participants