feat(cli): add hostname to footer with smart visibility

- Add hostname to footer ALL_ITEMS and DEFAULT_ORDER
- Implement smart visibility for hostname (only show when remote/container)
- Shorten hostname to first segment to save space
- Fix vimEnabled destructuring in Footer.tsx

Fixes https://github.com/google-gemini/gemini-cli/issues/25661
This commit is contained in:
Taylor Mullen 2026-04-20 20:35:43 -07:00
parent a38e2f0048
commit f578c375d0
3 changed files with 73 additions and 2 deletions

View file

@ -22,6 +22,11 @@ export const ALL_ITEMS = [
header: 'sandbox',
description: 'Sandbox type and trust indicator',
},
{
id: 'hostname',
header: 'host',
description: 'System hostname (only shown when remote or in a container)',
},
{
id: 'model-name',
header: '/model',
@ -70,6 +75,7 @@ export const DEFAULT_ORDER = [
'workspace',
'git-branch',
'sandbox',
'hostname',
'model-name',
'context-used',
'quota',
@ -87,6 +93,7 @@ export function deriveItemsFromLegacySettings(
'workspace',
'git-branch',
'sandbox',
'hostname',
'model-name',
'quota',
];

View file

@ -861,6 +861,47 @@ describe('<Footer />', () => {
expect(output).toContain('/model');
unmount();
});
it('renders hostname item when enabled and remote', async () => {
vi.stubEnv('SSH_TTY', '/dev/pts/1');
const { lastFrame, unmount } = await renderWithProviders(<Footer />, {
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
ui: {
footer: {
items: ['hostname'],
},
},
}),
});
expect(lastFrame()).toContain('host');
unmount();
});
it('does NOT render hostname item when enabled but NOT remote', async () => {
// Ensure no remote env vars are set
vi.stubEnv('SSH_TTY', '');
vi.stubEnv('CLOUD_SHELL', '');
const { lastFrame, unmount } = await renderWithProviders(<Footer />, {
config: mockConfig,
width: 120,
uiState: { sessionStats: mockSessionStats },
settings: createMockSettings({
ui: {
footer: {
items: ['hostname'],
},
},
}),
});
expect(lastFrame({ allowEmpty: true })).not.toContain('host');
unmount();
});
});
describe('fallback mode display', () => {

View file

@ -18,6 +18,8 @@ import {
} from '@google/gemini-cli-core';
import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js';
import process from 'node:process';
import { hostname } from 'node:os';
import * as fs from 'node:fs';
import { MemoryUsageDisplay } from './MemoryUsageDisplay.js';
import { ContextUsageDisplay } from './ContextUsageDisplay.js';
import { QuotaDisplay } from './QuotaDisplay.js';
@ -35,6 +37,8 @@ import {
} from '../../config/footerItems.js';
import { isDevelopment } from '../../utils/installationInfo.js';
const SYSTEM_HOSTNAME = hostname().split('.')[0];
interface CwdIndicatorProps {
targetDir: string;
maxWidth: number;
@ -172,14 +176,22 @@ interface FooterColumn {
width: number;
isHighPriority: boolean;
}
export const Footer: React.FC = () => {
const uiState = useUIState();
const quotaState = useQuotaState();
const { copyModeEnabled } = useInputState();
const config = useConfig();
const settings = useSettings();
const { vimEnabled, vimMode } = useVimMode();
const { vimMode, vimEnabled } = useVimMode();
const isRemote =
process.env['SSH_TTY'] ||
process.env['SSH_CONNECTION'] ||
process.env['SSH_CLIENT'] ||
process.env['CLOUD_SHELL'] === 'true' ||
process.env['EDITOR_IN_CLOUD_SHELL'] === 'true' ||
process.env['KUBERNETES_SERVICE_HOST'] ||
(process.platform === 'linux' && fs.existsSync('/.dockerenv'));
const authType = config.getContentGeneratorConfig()?.authType;
const [email, setEmail] = useState<string | undefined>();
@ -319,6 +331,17 @@ export const Footer: React.FC = () => {
);
break;
}
case 'hostname': {
if (isRemote && SYSTEM_HOSTNAME) {
addCol(
id,
header,
() => <Text color={itemColor}>{SYSTEM_HOSTNAME}</Text>,
SYSTEM_HOSTNAME.length,
);
}
break;
}
case 'model-name': {
const str = getDisplayString(model);
addCol(