diff --git a/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx b/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx
index a5ddf5ac34..4e751ad788 100644
--- a/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx
+++ b/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx
@@ -15,8 +15,20 @@ describe('ApprovalModeIndicator', () => {
,
);
const output = lastFrame();
- expect(output).toContain('accepting edits');
- expect(output).toContain('(shift + tab to cycle)');
+ expect(output).toContain('auto-edit');
+ expect(output).toContain('shift + tab to enter default mode');
+ });
+
+ it('renders correctly for AUTO_EDIT mode with plan enabled', () => {
+ const { lastFrame } = render(
+ ,
+ );
+ const output = lastFrame();
+ expect(output).toContain('auto-edit');
+ expect(output).toContain('shift + tab to enter default mode');
});
it('renders correctly for PLAN mode', () => {
@@ -24,8 +36,8 @@ describe('ApprovalModeIndicator', () => {
,
);
const output = lastFrame();
- expect(output).toContain('plan mode');
- expect(output).toContain('(shift + tab to cycle)');
+ expect(output).toContain('plan');
+ expect(output).toContain('shift + tab to enter auto-edit mode');
});
it('renders correctly for YOLO mode', () => {
@@ -33,16 +45,26 @@ describe('ApprovalModeIndicator', () => {
,
);
const output = lastFrame();
- expect(output).toContain('YOLO mode');
- expect(output).toContain('(ctrl + y to toggle)');
+ expect(output).toContain('YOLO');
+ expect(output).toContain('shift + tab to enter auto-edit mode');
});
- it('renders nothing for DEFAULT mode', () => {
+ it('renders correctly for DEFAULT mode', () => {
const { lastFrame } = render(
,
);
const output = lastFrame();
- expect(output).not.toContain('accepting edits');
- expect(output).not.toContain('YOLO mode');
+ expect(output).toContain('shift + tab to enter auto-edit mode');
+ });
+
+ it('renders correctly for DEFAULT mode with plan enabled', () => {
+ const { lastFrame } = render(
+ ,
+ );
+ const output = lastFrame();
+ expect(output).toContain('shift + tab to enter plan mode');
});
});
diff --git a/packages/cli/src/ui/components/ApprovalModeIndicator.tsx b/packages/cli/src/ui/components/ApprovalModeIndicator.tsx
index 875cb0d84b..83adcd8417 100644
--- a/packages/cli/src/ui/components/ApprovalModeIndicator.tsx
+++ b/packages/cli/src/ui/components/ApprovalModeIndicator.tsx
@@ -11,10 +11,12 @@ import { ApprovalMode } from '@google/gemini-cli-core';
interface ApprovalModeIndicatorProps {
approvalMode: ApprovalMode;
+ isPlanEnabled?: boolean;
}
export const ApprovalModeIndicator: React.FC = ({
approvalMode,
+ isPlanEnabled,
}) => {
let textColor = '';
let textContent = '';
@@ -23,29 +25,39 @@ export const ApprovalModeIndicator: React.FC = ({
switch (approvalMode) {
case ApprovalMode.AUTO_EDIT:
textColor = theme.status.warning;
- textContent = 'accepting edits';
- subText = ' (shift + tab to cycle)';
+ textContent = 'auto-edit';
+ subText = 'shift + tab to enter default mode';
break;
case ApprovalMode.PLAN:
textColor = theme.status.success;
- textContent = 'plan mode';
- subText = ' (shift + tab to cycle)';
+ textContent = 'plan';
+ subText = 'shift + tab to enter auto-edit mode';
break;
case ApprovalMode.YOLO:
textColor = theme.status.error;
- textContent = 'YOLO mode';
- subText = ' (ctrl + y to toggle)';
+ textContent = 'YOLO';
+ subText = 'shift + tab to enter auto-edit mode';
break;
case ApprovalMode.DEFAULT:
default:
+ textColor = theme.text.accent;
+ textContent = '';
+ subText = isPlanEnabled
+ ? 'shift + tab to enter plan mode'
+ : 'shift + tab to enter auto-edit mode';
break;
}
return (
- {textContent}
- {subText && {subText}}
+ {textContent ? textContent : null}
+ {subText ? (
+
+ {textContent ? ' ' : ''}
+ {subText}
+
+ ) : null}
);
diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx
index d9094c6ae5..0f6f310637 100644
--- a/packages/cli/src/ui/components/Composer.test.tsx
+++ b/packages/cli/src/ui/components/Composer.test.tsx
@@ -164,6 +164,7 @@ const createMockConfig = (overrides = {}) => ({
getDebugMode: vi.fn(() => false),
getAccessibility: vi.fn(() => ({})),
getMcpServers: vi.fn(() => ({})),
+ isPlanEnabled: vi.fn(() => false),
getToolRegistry: () => ({
getTool: vi.fn(),
}),
@@ -485,16 +486,24 @@ describe('Composer', () => {
expect(lastFrame()).not.toContain('InputPrompt');
});
- it('shows ApprovalModeIndicator when approval mode is not default and shell mode is inactive', () => {
- const uiState = createMockUIState({
- showApprovalModeIndicator: ApprovalMode.YOLO,
- shellModeActive: false,
- });
+ it.each([
+ [ApprovalMode.DEFAULT],
+ [ApprovalMode.AUTO_EDIT],
+ [ApprovalMode.PLAN],
+ [ApprovalMode.YOLO],
+ ])(
+ 'shows ApprovalModeIndicator when approval mode is %s and shell mode is inactive',
+ (mode) => {
+ const uiState = createMockUIState({
+ showApprovalModeIndicator: mode,
+ shellModeActive: false,
+ });
- const { lastFrame } = renderComposer(uiState);
+ const { lastFrame } = renderComposer(uiState);
- expect(lastFrame()).toMatch(/ApprovalModeIndic[\s\S]*ator/);
- });
+ expect(lastFrame()).toMatch(/ApprovalModeIndic[\s\S]*ator/);
+ },
+ );
it('shows ShellModeIndicator when shell mode is active', () => {
const uiState = createMockUIState({
diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx
index 57afdde943..024b34216f 100644
--- a/packages/cli/src/ui/components/Composer.tsx
+++ b/packages/cli/src/ui/components/Composer.tsx
@@ -27,7 +27,6 @@ import { useVimMode } from '../contexts/VimModeContext.js';
import { useConfig } from '../contexts/ConfigContext.js';
import { useSettings } from '../contexts/SettingsContext.js';
import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js';
-import { ApprovalMode } from '@google/gemini-cli-core';
import { StreamingState, ToolCallStatus } from '../types.js';
import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js';
import { TodoTray } from './messages/Todo.js';
@@ -68,9 +67,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
(!uiState.embeddedShellFocused || uiState.isBackgroundShellVisible) &&
uiState.streamingState === StreamingState.Responding &&
!hasPendingActionRequired;
- const showApprovalIndicator =
- showApprovalModeIndicator !== ApprovalMode.DEFAULT &&
- !uiState.shellModeActive;
+ const showApprovalIndicator = !uiState.shellModeActive;
const showRawMarkdownIndicator = !uiState.renderMarkdown;
const showEscToCancelHint =
showLoadingIndicator &&
@@ -169,6 +166,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
{showApprovalIndicator && (
)}
{uiState.shellModeActive && (
diff --git a/packages/cli/src/ui/hooks/useApprovalModeIndicator.test.ts b/packages/cli/src/ui/hooks/useApprovalModeIndicator.test.ts
index 4fec4edf18..0b61023b18 100644
--- a/packages/cli/src/ui/hooks/useApprovalModeIndicator.test.ts
+++ b/packages/cli/src/ui/hooks/useApprovalModeIndicator.test.ts
@@ -236,7 +236,7 @@ describe('useApprovalModeIndicator', () => {
expect(result.current).toBe(ApprovalMode.AUTO_EDIT);
});
- it('should cycle through DEFAULT -> AUTO_EDIT -> PLAN -> DEFAULT when plan is enabled', () => {
+ it('should cycle through DEFAULT -> PLAN -> AUTO_EDIT -> DEFAULT when plan is enabled', () => {
mockConfigInstance.getApprovalMode.mockReturnValue(ApprovalMode.DEFAULT);
mockConfigInstance.isPlanEnabled.mockReturnValue(true);
renderHook(() =>
@@ -246,15 +246,7 @@ describe('useApprovalModeIndicator', () => {
}),
);
- // DEFAULT -> AUTO_EDIT
- act(() => {
- capturedUseKeypressHandler({ name: 'tab', shift: true } as Key);
- });
- expect(mockConfigInstance.setApprovalMode).toHaveBeenCalledWith(
- ApprovalMode.AUTO_EDIT,
- );
-
- // AUTO_EDIT -> PLAN
+ // DEFAULT -> PLAN
act(() => {
capturedUseKeypressHandler({ name: 'tab', shift: true } as Key);
});
@@ -262,7 +254,15 @@ describe('useApprovalModeIndicator', () => {
ApprovalMode.PLAN,
);
- // PLAN -> DEFAULT
+ // PLAN -> AUTO_EDIT
+ act(() => {
+ capturedUseKeypressHandler({ name: 'tab', shift: true } as Key);
+ });
+ expect(mockConfigInstance.setApprovalMode).toHaveBeenCalledWith(
+ ApprovalMode.AUTO_EDIT,
+ );
+
+ // AUTO_EDIT -> DEFAULT
act(() => {
capturedUseKeypressHandler({ name: 'tab', shift: true } as Key);
});
diff --git a/packages/cli/src/ui/hooks/useApprovalModeIndicator.ts b/packages/cli/src/ui/hooks/useApprovalModeIndicator.ts
index 3208b41603..c9c1d768c8 100644
--- a/packages/cli/src/ui/hooks/useApprovalModeIndicator.ts
+++ b/packages/cli/src/ui/hooks/useApprovalModeIndicator.ts
@@ -72,14 +72,14 @@ export function useApprovalModeIndicator({
const currentMode = config.getApprovalMode();
switch (currentMode) {
case ApprovalMode.DEFAULT:
+ nextApprovalMode = config.isPlanEnabled()
+ ? ApprovalMode.PLAN
+ : ApprovalMode.AUTO_EDIT;
+ break;
+ case ApprovalMode.PLAN:
nextApprovalMode = ApprovalMode.AUTO_EDIT;
break;
case ApprovalMode.AUTO_EDIT:
- nextApprovalMode = config.isPlanEnabled()
- ? ApprovalMode.PLAN
- : ApprovalMode.DEFAULT;
- break;
- case ApprovalMode.PLAN:
nextApprovalMode = ApprovalMode.DEFAULT;
break;
case ApprovalMode.YOLO: