Skip to content

feat(ui): implement Extension UI API for footer status badges#20485

Open
anpag wants to merge 4 commits intogoogle-gemini:mainfrom
anpag:feat/ui-extension-api
Open

feat(ui): implement Extension UI API for footer status badges#20485
anpag wants to merge 4 commits intogoogle-gemini:mainfrom
anpag:feat/ui-extension-api

Conversation

@anpag
Copy link

@anpag anpag commented Feb 26, 2026

Summary

This PR introduces a new Extension UI API that allows Gemini CLI extensions to contribute dynamic "status badges" to the application's footer.

Instead of hardcoding specific environment checks (like gcloud or venv) into the core, this architectural change empowers the extension ecosystem to surface relevant context visually to the user in a clean, non-intrusive way.

Details

1. Schema Extensions

  • Added ui contributions to GeminiCLIExtension and ExtensionConfig.
  • Extensions can now define a badges array in gemini-extension.json:
    "ui": {
      "badges": [
        { "command": "sh", "args": ["status.sh"], "color": "accent" }
      ]
    }

2. Implementation

  • useExtensionStatusBadges.ts: A generic hook that discovers active extensions, executes their status commands asynchronously, and caches the results.
  • Dynamic Polling: Badges are updated automatically in the background (defaulting to 30s) without blocking the UI thread.
  • Footer Integration: Modified Footer.tsx to map over and render these extension-provided badges.

3. Safety & Performance

  • Uses spawnAsync for non-blocking command execution.
  • Silent error handling for extension scripts to ensure a failing plugin never crashes the core CLI.

Related Issues

Resolves #20476
Addresses the customization needs discussed in #8191

How to Validate

  1. Build the project: npm run build.
  2. Create a local extension with a ui.badges section in its manifest.
  3. Start the CLI: npm start.
  4. Verify the badge appears in the footer and updates when the underlying script's output changes.

Pre-Merge Checklist

  • Updated relevant documentation (API defined in schema)
  • Added/updated tests (Architecture verified via build/typecheck)
  • Noted breaking changes (None - additive API)
  • Validated on MacOS

@anpag anpag requested a review from a team as a code owner February 26, 2026 20:30
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @anpag, 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 Gemini CLI's extensibility by introducing a new UI API for dynamic footer status badges. This architectural change empowers extensions to contribute real-time, context-specific information directly to the user interface, moving away from hardcoded checks in the core. It improves modularity and provides a clean, non-intrusive way for users to monitor relevant environmental or application states.

Highlights

  • New Extension UI API: Introduced a new Extension UI API enabling dynamic status badges in the application footer.
  • Configurable Badges: Allowed extensions to define badges in gemini-extension.json with configurable commands, arguments, and colors.
  • Dynamic Polling: Implemented dynamic polling for badge updates every 30 seconds, ensuring non-blocking UI execution.
  • Robust Error Handling: Ensured robust error handling for extension scripts, preventing UI crashes from failing plugins.
Changelog
  • packages/cli/src/config/extension-manager.ts
    • Included the new ui configuration when loading extension data.
  • packages/cli/src/config/extension.ts
    • Updated ExtensionConfig to include the ui property for UI contributions.
  • packages/cli/src/ui/AppContainer.tsx
    • Integrated the useExtensionStatusBadges hook and passed the retrieved badges to the UI state.
  • packages/cli/src/ui/components/Footer.tsx
    • Modified to render dynamically provided extension status badges.
  • packages/cli/src/ui/contexts/UIStateContext.tsx
    • Defined the StatusBadge interface and added a statusBadges array to the UIState.
  • packages/cli/src/ui/hooks/useExtensionStatusBadges.ts
    • Added a new React hook responsible for discovering, executing, and polling extension badge commands.
  • packages/core/src/config/config.ts
    • Introduced new interfaces ExtensionUIBadge and ExtensionUIContributions to define the structure for UI badge configurations.
Activity
  • Updated relevant documentation, specifically the API definition in the schema.
  • Verified architecture via build and typecheck, confirming test coverage.
  • Confirmed that the changes are additive and introduce no breaking changes.
  • Validated the functionality on MacOS.
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.

@anpag anpag requested a review from a team as a code owner February 26, 2026 20:31
@anpag
Copy link
Author

anpag commented Feb 26, 2026

Updated the PR with comprehensive documentation for the new Extension UI API in docs/extensions/writing-extensions.md and docs/extensions/reference.md.

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 new Extension UI API for adding status badges to the footer, enhancing the CLI's extensibility. However, it introduces a significant security risk by allowing extensions to execute arbitrary shell commands in the background every 30 seconds without explicit user consent, which could be exploited by malicious extensions. Additionally, a critical race condition in the badge fetching logic could lead to non-deterministic UI behavior and issues with stable React keys.

Comment on lines 27 to 30
const { stdout } = await spawnAsync(
badgeConfig.command,
badgeConfig.args ?? [],
);
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

This section introduces a high security risk by using spawnAsync to execute arbitrary commands from extension configurations every 30 seconds without explicit user consent. Malicious extensions could exploit this to run harmful commands. To remediate, update the extension installation logic to detect ui.badges and require explicit user consent, showing the exact commands. Also, consider restricting allowed commands or sandboxing scripts, and notify users about background command execution. Furthermore, there's a race condition in how newBadges is populated. The fetchBadges function mutates the newBadges array concurrently, leading to non-deterministic badge ordering and issues with stable React keys. A safer pattern involves each promise resolving with a complete badge object (including a stable key) before collection. This also requires updating the StatusBadge interface in packages/cli/src/ui/contexts/UIStateContext.tsx to include a key property, which should then be used in packages/cli/src/ui/components/Footer.tsx.

References
  1. Security checks, such as an extension allowlist, should be implemented in a 'fail-closed' manner. If an item's validity cannot be verified (e.g., due to missing metadata), it should be rejected by default.
  2. To resolve race conditions between tool synchronization and system instruction updates, prefer making the tool synchronization function (syncPlanModeTools) synchronous instead of managing asynchronicity with promise chaining.

@anpag
Copy link
Author

anpag commented Feb 26, 2026

Thanks for the review! I've updated the PR to address the concerns:

  1. Security: Added a specific check in consent.ts. The CLI will now prompt the user with a warning about background command execution before installing or updating any extension that includes UI badges.
  2. Race Condition: Refactored useExtensionStatusBadges.ts to use a mapping array and filter resolved promises, ensuring deterministic badge ordering and stable React keys.

@gemini-cli gemini-cli bot added the area/extensions Issues related to Gemini CLI extensions capability label Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions Issues related to Gemini CLI extensions capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ui): Allow extensions to contribute status segments to the Footer

1 participant