diff --git a/packages/cli/src/ui/components/Footer.test.tsx b/packages/cli/src/ui/components/Footer.test.tsx
index 9c253fec925..7fecd246261 100644
--- a/packages/cli/src/ui/components/Footer.test.tsx
+++ b/packages/cli/src/ui/components/Footer.test.tsx
@@ -381,6 +381,61 @@ describe('', () => {
unmount();
});
+ it('shows the context percentage even when hideModelInfo is true', async () => {
+ const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
+ ,
+ {
+ width: 120,
+ uiState: { sessionStats: mockSessionStats },
+ settings: createMockSettings({
+ ui: {
+ footer: {
+ hideModelInfo: true,
+ hideContextPercentage: false,
+ },
+ },
+ }),
+ },
+ );
+ await waitUntilReady();
+
+ expect(lastFrame()).not.toContain(defaultProps.model);
+ expect(lastFrame()).toMatch(/\d+% context left/);
+ unmount();
+ });
+
+ it('shows quota stats even when hideModelInfo is true', async () => {
+ const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
+ ,
+ {
+ width: 120,
+ uiState: {
+ sessionStats: mockSessionStats,
+ quota: {
+ userTier: undefined,
+ stats: { remaining: 15, limit: 100, resetTime: undefined },
+ proQuotaRequest: null,
+ validationRequest: null,
+ overageMenuRequest: null,
+ emptyWalletRequest: null,
+ },
+ },
+ settings: createMockSettings({
+ ui: {
+ footer: {
+ hideModelInfo: true,
+ },
+ },
+ }),
+ },
+ );
+ await waitUntilReady();
+
+ expect(lastFrame()).not.toContain(defaultProps.model);
+ expect(lastFrame()).toContain('15%');
+ unmount();
+ });
+
it('renders footer with all optional sections hidden (minimal footer)', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
,
diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx
index 9babae6ce3e..f4632e9cc14 100644
--- a/packages/cli/src/ui/components/Footer.tsx
+++ b/packages/cli/src/ui/components/Footer.tsx
@@ -71,11 +71,22 @@ export const Footer: React.FC = () => {
const pathLength = Math.max(20, Math.floor(terminalWidth * 0.25));
const displayPath = shortenPath(tildeifyPath(targetDir), pathLength);
- const justifyContent = hideCWD && hideModelInfo ? 'center' : 'space-between';
const displayVimMode = vimEnabled ? vimMode : undefined;
-
const showDebugProfiler = debugMode || isDevelopment;
+ // Determine if anything is visible on the left or right to set layout
+ const showLeftSection = showDebugProfiler || !!displayVimMode || !hideCWD;
+ const showRightSection =
+ !hideModelInfo ||
+ !hideContextPercentage ||
+ !!quotaStats ||
+ showMemoryUsage ||
+ corgiMode ||
+ showErrorSummary;
+
+ const justifyContent =
+ !showLeftSection && !showRightSection ? 'center' : 'space-between';
+
return (
{
)}
{/* Right Section: Gemini Label and Console Summary */}
- {!hideModelInfo && (
+ {(!hideModelInfo ||
+ !hideContextPercentage ||
+ !!quotaStats ||
+ showMemoryUsage ||
+ corgiMode ||
+ showErrorSummary) && (
- /model
- {getDisplayString(model)}
+ {!hideModelInfo && (
+ <>
+ /model
+ {getDisplayString(model)}
+ >
+ )}
{!hideContextPercentage && (
<>
- {' '}
+ {/* Adds a space between Model Info and Context if BOTH are shown */}
+ {!hideModelInfo && ' '}
{
)}
{quotaStats && (
<>
- {' '}
+ {/* Adds a space if either of the previous items are shown */}
+ {(!hideModelInfo || !hideContextPercentage) && ' '}