diff --git a/packages/cli/src/ui/components/AppHeader.test.tsx b/packages/cli/src/ui/components/AppHeader.test.tsx
index 2fab08c8e6..f7d3ce70c3 100644
--- a/packages/cli/src/ui/components/AppHeader.test.tsx
+++ b/packages/cli/src/ui/components/AppHeader.test.tsx
@@ -11,7 +11,7 @@ import {
import type { LoadedSettings } from '../../config/settings.js';
import { AppHeader } from './AppHeader.js';
import { describe, it, expect, vi, beforeEach } from 'vitest';
-import { makeFakeConfig } from '@google/gemini-cli-core';
+import { makeFakeConfig, type ContentGeneratorConfig } from '@google/gemini-cli-core';
import crypto from 'node:crypto';
import { _clearSessionBannersForTest } from '../hooks/useBanner.js';
@@ -252,7 +252,7 @@ describe('', () => {
const mockConfig = makeFakeConfig();
vi.spyOn(mockConfig, 'getContentGeneratorConfig').mockReturnValue({
authType: undefined,
- } as any); // eslint-disable-line @typescript-eslint/no-explicit-any
+ } as ContentGeneratorConfig);
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
,
@@ -289,4 +289,39 @@ describe('', () => {
expect(lastFrame()).not.toContain('Tips');
unmount();
});
+
+ it('should render compact version tags for nightly builds', async () => {
+ const { lastFrame, unmount } = await renderWithProviders(
+ ,
+ {},
+ );
+
+ expect(lastFrame()).toContain('v0.42.0');
+ expect(lastFrame()).toContain('[nightly]');
+ expect(lastFrame()).not.toContain('20260428');
+ unmount();
+ });
+
+ it('should render compact version tags for alpha builds', async () => {
+ const { lastFrame, unmount } = await renderWithProviders(
+ ,
+ {},
+ );
+
+ expect(lastFrame()).toContain('v1.0.0');
+ expect(lastFrame()).toContain('[alpha]');
+ unmount();
+ });
+
+ it('should render normal versions without tags', async () => {
+ const { lastFrame, unmount } = await renderWithProviders(
+ ,
+ {},
+ );
+
+ expect(lastFrame()).toContain('v1.2.3');
+ expect(lastFrame()).not.toContain('[');
+ expect(lastFrame()).not.toContain(']');
+ unmount();
+ });
});
diff --git a/packages/cli/src/ui/components/AppHeader.tsx b/packages/cli/src/ui/components/AppHeader.tsx
index 1b3d9b2cfa..ec134ce930 100644
--- a/packages/cli/src/ui/components/AppHeader.tsx
+++ b/packages/cli/src/ui/components/AppHeader.tsx
@@ -90,6 +90,13 @@ export const AppHeader = ({ version, showDetails = true }: AppHeaderProps) => {
}
}
+ // Parse version string (e.g., 0.42.0-nightly.20260428.g59b2dea0e)
+ // to extract the base version and the tag.
+ const versionParts = version.split('-');
+ const baseVersion = versionParts[0];
+ const tagPart = versionParts.slice(1).join('-');
+ const tag = tagPart ? tagPart.split('.')[0] : '';
+
// If the terminal is too narrow to fit the icon and metadata (especially long nightly versions)
// side-by-side, we switch to column mode to prevent wrapping.
const isNarrow = terminalWidth < NARROW_TERMINAL_BREAKPOINT;
@@ -114,7 +121,13 @@ export const AppHeader = ({ version, showDetails = true }: AppHeaderProps) => {
Gemini CLI
- v{version}
+ v{baseVersion}
+ {tag && (
+
+ {' '}
+ [{tag}]
+
+ )}
{updateInfo?.isUpdating && (