Skip to content

feat(cli): prototype clean UI toggle and minimal-mode bleed-through#18683

Merged
LyalinDotCom merged 39 commits intomainfrom
explore-cleanui
Feb 12, 2026
Merged

feat(cli): prototype clean UI toggle and minimal-mode bleed-through#18683
LyalinDotCom merged 39 commits intomainfrom
explore-cleanui

Conversation

@LyalinDotCom
Copy link
Collaborator

@LyalinDotCom LyalinDotCom commented Feb 9, 2026

Summary

Prototype a new Focus UI mode for Gemini CLI that is opt-in, keeps existing behavior as default, and can be toggled quickly without losing core controls.

Details

  • Added a double-Tab (Tab + Tab) toggle that switches between:
    • Full UI (current/default experience)
    • Minimal UI (reduced chrome)
  • Restored single Tab to its original uses (focus/suggestions/navigation behavior).
  • Persisted Focus UI choice in persistent state (focusUiEnabled) so once a user opts into minimal mode, that preference is remembered across sessions.

Minimal UI behavior implemented:

  • Input bar always remains visible.
  • Hint near the input area shows: press tab twice for more.
  • ? shortcuts panel remains available from minimal mode and full mode.
  • Mode bleed-through badges render in minimal mode for:
    • YOLO
    • plan
    • auto edit
  • Busy/action-required states suppress non-essential minimal hints and badges.
  • Streaming in minimal mode uses inline loading on the minimal meta row.
  • Escape rewind/status toasts continue to show in minimal mode.
  • Context percentage can bleed through in minimal mode when usage is high (>60%) and context percentage is enabled.
  • When slash suggestions are shown above input (alternate buffer), minimal hint/mode badges are hidden to avoid overlap.

Header/layout behavior:

  • Keep Gemini logo visible.
  • Alternate buffer supports reduced header details in minimal mode.
  • Regular buffer keeps stable static header rendering to avoid redraw/flicker regressions around /clear and resize.

Also updated shortcuts/help presentation:

  • Shortcuts panel ordering now keeps first column stable as:
    • !
    • @
    • Esc Esc
    • Tab Tab
  • Updated shortcut text labels to match final behavior (Esc Esc clear & rewind, Tab Tab focus UI).

Related Issues

  • N/A

How to Validate

  1. Build and typecheck:
    • npm run build
    • npm run typecheck
  2. Run focused CLI UI tests:
    • npm run test --workspace @google/gemini-cli -- src/ui/AppContainer.test.tsx src/ui/components/Composer.test.tsx src/ui/components/InputPrompt.test.tsx src/ui/components/MainContent.test.tsx src/ui/components/ShortcutsHelp.test.tsx
  3. Manual behavior checks in terminal:
    • Start CLI and confirm default is full UI.
    • Press Tab once and verify normal tab behavior still works.
    • Press Tab twice quickly and verify UI toggles to minimal mode.
    • Press Tab twice again and verify it returns to full UI.
    • In minimal mode, verify ? opens shortcuts panel and closes with expected keys.
    • In minimal mode, verify mode badges (YOLO, plan, auto edit) appear appropriately.
    • While streaming/action-required, verify non-essential minimal hints are hidden.
    • In alternate buffer with slash suggestions above input, verify hint/mode badges hide.
    • Run /clear and resize terminal to verify header/layout stability.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@gemini-cli
Copy link
Contributor

gemini-cli bot commented Feb 9, 2026

Hi @LyalinDotCom, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: Improving Our Contribution Process & Introducing New Guidelines.

Key Update: Starting January 26, 2026, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

Thank you for your understanding and for being a part of our community!

@gemini-cli
Copy link
Contributor

gemini-cli bot commented Feb 9, 2026

Hi there! Thank you for your contribution to Gemini CLI.

To improve our contribution process and better track changes, we now require all pull requests to be associated with an existing issue, as announced in our recent discussion and as detailed in our CONTRIBUTING.md.

This pull request is being closed because it is not currently linked to an issue. Once you have updated the description of this PR to link an issue (e.g., by adding Fixes #123 or Related to #123), it will be automatically reopened.

How to link an issue:
Add a keyword followed by the issue number (e.g., Fixes #123) in the description of your pull request. For more details on supported keywords and how linking works, please refer to the GitHub Documentation on linking pull requests to issues.

Thank you for your understanding and for being a part of our community!

@gemini-cli gemini-cli bot closed this Feb 9, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @LyalinDotCom, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience of the CLI by introducing a 'clean UI' prototype. The primary goal is to minimize visual clutter upon startup, allowing users to focus on core interactions while still providing immediate access to detailed information when needed. This is achieved through a new toggle mechanism and intelligent 'bleed-through' for essential indicators, making the interface more streamlined and user-friendly without sacrificing critical feedback.

Highlights

  • Clean UI Prototype: Introduced a new 'clean UI' mode where the CLI starts in a minimal state, reducing visual noise. Users can toggle detailed UI on demand using the Tab key.
  • Keybinding Changes: The Tab key's primary function has been remapped to toggle between minimal and full UI details when no completion or search interaction is active. Shell focus controls (focus/unfocus) have been moved from Tab/Shift+Tab to F6/Shift+F6 respectively.
  • Minimal UI Bleed-Through: Critical operational feedback, such as approval mode labels (YOLO, plan, auto edit), transient status/warning flashes (e.g., Esc-rewind prompt), and context usage percentage (when exceeding 60%), will now 'bleed through' and remain visible even in minimal UI mode.
  • Header and Shortcuts Behavior: The header/logo behavior has been restored, and detail restoration when toggling UI has been fixed. The shortcuts help menu (?) is now accessible in minimal UI mode.
  • Documentation Updates: Keyboard shortcut documentation has been regenerated to reflect the new F6/Shift+F6 bindings for shell focus and to clarify the Tab key's new role in UI toggling.
Changelog
  • docs/cli/commands.md
    • Added a note clarifying the distinction between the /shortcuts command and the new Tab key clean UI detail toggle.
  • docs/cli/keyboard-shortcuts.md
    • Updated keybindings for shell focus commands, remapping them from Tab and Shift+Tab to F6 and Shift+F6.
    • Added new entries for Tab to toggle minimal/full UI details and Shift+Tab to temporarily reveal details in minimal UI for approval mode changes.
  • packages/cli/src/config/keyBindings.ts
    • Modified keybinding configurations to reflect the change of shell focus commands from Tab to F6 and Shift+F6.
  • packages/cli/src/test-utils/render.tsx
    • Added cleanUiDetailsVisible to the baseMockUiState for testing purposes.
    • Introduced mocks for new UI actions: setCleanUiDetailsVisible, toggleCleanUiDetailsVisible, and revealCleanUiDetailsTemporarily.
  • packages/cli/src/ui/App.test.tsx
    • Set cleanUiDetailsVisible to true in mockUIState for initial testing contexts.
  • packages/cli/src/ui/AppContainer.test.tsx
    • Updated test descriptions and keypress simulations to use F6 and Shift+F6 for shell focus, replacing Tab and Shift+Tab.
  • packages/cli/src/ui/AppContainer.tsx
    • Implemented state management for cleanUiDetailsVisible and associated functions (setCleanUiDetailsVisible, toggleCleanUiDetailsVisible, revealCleanUiDetailsTemporarily).
    • Added logic to temporarily reveal UI details when Shift+Tab is used to cycle approval modes in minimal UI.
    • Ensured timeouts for temporary UI reveals are cleared on component unmount.
  • packages/cli/src/ui/components/AppHeader.tsx
    • Introduced a showDetails prop to AppHeader to conditionally render a compact header in minimal UI mode.
  • packages/cli/src/ui/components/Composer.test.tsx
    • Updated mock UI state and actions to include cleanUiDetailsVisible and related functions.
    • Added new test cases to verify that non-essential UI details are hidden in clean mode, while critical bleed-through indicators (approval mode, Esc rewind, context usage) remain visible.
    • Included tests for shortcuts hint visibility in both minimal and full UI modes.
  • packages/cli/src/ui/components/Composer.tsx
    • Integrated cleanUiDetailsVisible to control the rendering of various UI components, hiding them in minimal mode.
    • Implemented logic for 'bleed-through' indicators, ensuring approval mode badges, status messages, and context usage percentage are visible in minimal UI under specific conditions.
    • Adjusted the visibility of QueuedMessageDisplay, TodoTray, HorizontalLine, DetailedMessagesDisplay, and Footer based on the showUiDetails state.
  • packages/cli/src/ui/components/InputPrompt.test.tsx
    • Updated tests for Tab key behavior to verify it now toggles clean UI details instead of shell focus when no completion/search is active.
    • Added a test to confirm Shift+Tab triggers a temporary reveal of clean UI details.
  • packages/cli/src/ui/components/InputPrompt.tsx
    • Integrated toggleCleanUiDetailsVisible and revealCleanUiDetailsTemporarily actions.
    • Modified Tab key handling to toggle UI details if no completion or search is active.
    • Added logic for Shift+Tab to temporarily reveal UI details when in minimal mode.
  • packages/cli/src/ui/components/MainContent.test.tsx
    • Updated AppHeader mock to distinguish between full and minimal display.
    • Added cleanUiDetailsVisible to the default mock UI state.
    • Included tests to verify correct header rendering in minimal mode and proper restoration of full header details after toggling in both alternate and normal buffer modes.
  • packages/cli/src/ui/components/MainContent.tsx
    • Passed cleanUiDetailsVisible as the showDetails prop to AppHeader.
    • Moved AppHeader out of the Static component in the normal buffer to ensure reliable re-rendering upon UI detail toggles.
  • packages/cli/src/ui/components/ShortcutsHint.tsx
    • Modified to display 'press tab for more' when cleanUiDetailsVisible is false, providing a clear hint for UI toggling.
  • packages/cli/src/ui/components/snapshots/MainContent.test.tsx.snap
    • Updated snapshots to reflect the new AppHeader(full) rendering in tests.
  • packages/cli/src/ui/contexts/UIActionsContext.tsx
    • Added setCleanUiDetailsVisible, toggleCleanUiDetailsVisible, and revealCleanUiDetailsTemporarily to the UIActions interface.
  • packages/cli/src/ui/contexts/UIStateContext.tsx
    • Added cleanUiDetailsVisible to the UIState interface.
  • packages/cli/src/ui/keyMatchers.test.ts
    • Updated the key matcher for FOCUS_SHELL_INPUT to f6, removing tab.
Activity
  • The pull request introduces a new feature for a 'clean UI' in the CLI.
  • It involves significant refactoring of UI state management and component rendering logic.
  • Keybindings for Tab and F6 have been remapped to support the new UI toggle and shell focus functionalities.
  • Extensive unit tests have been added and updated across multiple UI components (App, AppContainer, Composer, InputPrompt, MainContent, keyMatchers) to ensure the new behavior is correct and robust.
  • Documentation for keyboard shortcuts and commands has been updated to reflect these changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot 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

This pull request introduces a significant and well-executed UX improvement with the clean UI toggle and minimal mode. The implementation is robust, handling the new cleanUiDetailsVisible state with thoughtful logic for both permanent toggling and temporary reveals. The remapping of keybindings from Tab to F6 for shell focus is applied consistently across configuration, documentation, and tests. The fix in MainContent.tsx to move the AppHeader out of the Static component to ensure it re-renders correctly is a clever solution to a tricky problem. The added tests provide good coverage for the new functionality. Overall, this is a high-quality prototype that greatly enhances the CLI's usability.

@jacob314 jacob314 reopened this Feb 10, 2026
@github-actions
Copy link

github-actions bot commented Feb 10, 2026

Size Change: +10.8 kB (+0.04%)

Total Size: 24.3 MB

Filename Size Change
./bundle/gemini.js 24.3 MB +10.8 kB (+0.04%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB
./bundle/sandbox-macos-strict-open.sb 4.82 kB
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB

compressed-size-action

@gemini-cli gemini-cli bot added the area/core Issues related to User Interface, OS Support, Core Functionality label Feb 10, 2026
@LyalinDotCom LyalinDotCom marked this pull request as ready for review February 10, 2026 14:55
@LyalinDotCom LyalinDotCom requested review from a team as code owners February 10, 2026 14:55
# Conflicts:
#	packages/cli/src/ui/components/Composer.test.tsx
#	packages/cli/src/ui/components/Composer.tsx
@LyalinDotCom
Copy link
Collaborator Author

@jacob314 this is ready for your review

@jacob314
Copy link
Contributor

Thank you for this PR! The clean UI mode looks like a great addition to reduce visual noise.

I've reviewed the code and have identified a critical React anti-pattern that needs to be addressed before merging.

React Anti-Pattern in toggleCleanUiDetailsVisible

In packages/cli/src/ui/AppContainer.tsx, the toggleCleanUiDetailsVisible function performs side effects directly within the state setter callback:

const toggleCleanUiDetailsVisible = useCallback(() => {
  clearModeRevealTimeout();
  setCleanUiDetailsVisibleState((visible) => {
    const nextVisible = !visible;
    // SIDE EFFECTS BELOW:
    cleanUiDetailsPinnedRef.current = nextVisible;
    persistFocusUiPreference(nextVisible);
    return nextVisible;
  });
}, [clearModeRevealTimeout, persistFocusUiPreference]);

React strictly forbids performing side effects (like updating refs or making external calls like persistFocusUiPreference) inside state updater functions. In React's Strict Mode, these updater functions can be called multiple times for a single render, which would cause these side effects to run multiple times unexpectedly.

Recommendation:

Since you already have cleanUiDetailsPinnedRef which synchronously tracks the pinned state, you can read from the ref to determine the next state without needing the functional updater.

Please update the function to look like this:

const toggleCleanUiDetailsVisible = useCallback(() => {
  clearModeRevealTimeout();
  const nextVisible = !cleanUiDetailsPinnedRef.current;
  cleanUiDetailsPinnedRef.current = nextVisible;
  setCleanUiDetailsVisibleState(nextVisible);
  persistFocusUiPreference(nextVisible);
}, [clearModeRevealTimeout, persistFocusUiPreference]);

This ensures the side effects run exactly once per invocation, and the state is updated safely.

Other than this issue, the React code and test cases look solid. Snapshots correctly reflect the changes to the AppHeader mock.

{
command: Command.FOCUS_SHELL_INPUT,
positive: [createKey('tab')],
negative: [createKey('f', { ctrl: true }), createKey('f')],
Copy link
Contributor

Choose a reason for hiding this comment

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

revert this change. we aren't supporting F6.

@gemini-cli gemini-cli bot added the status/need-issue Pull requests that need to have an associated issue. label Feb 12, 2026

describe('Composer', () => {
beforeEach(() => {
composerTestControls.suggestionsVisible = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

revert this slop

Copy link
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

@LyalinDotCom LyalinDotCom added this pull request to the merge queue Feb 12, 2026
Merged via the queue into main with commit db00c5a Feb 12, 2026
26 of 27 checks passed
@LyalinDotCom LyalinDotCom deleted the explore-cleanui branch February 12, 2026 19:35
@raduc
Copy link

raduc commented Feb 21, 2026

There is a bug in how the hideBanner setting works after this:

  • it hides the banner in full UI
  • it shows the banner again in minimal UI

Which is somewhat against the purpose of those two options (hideBanner and minimal UI)

Does anyone know where this can be fixed?

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

Labels

area/core Issues related to User Interface, OS Support, Core Functionality status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants