From 6f1d1a7c0057f833a37229fab105a9f2e7be4b13 Mon Sep 17 00:00:00 2001 From: whatevertogo <149563971+whatevertogo@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:18:35 +0800 Subject: [PATCH 1/3] fix(cli): clarify permission mode approval behavior Distinguish YOLO regular-tool approvals from exceptional prompts and describe Auto as unattended across command help, selectors, notices, and replay. Add regression coverage for the permission order and user-visible copy. Refs #1859, #1866, #1874 --- .changeset/clarify-permission-mode-copy.md | 5 +++ apps/kimi-code/src/cli/commands.ts | 12 +++++-- apps/kimi-code/src/tui/commands/config.ts | 20 +++++++++--- apps/kimi-code/src/tui/commands/registry.ts | 6 ++-- .../components/dialogs/permission-selector.ts | 7 +++-- .../src/tui/controllers/session-replay.ts | 3 +- .../test/tui/commands/registry.test.ts | 9 ++++++ .../components/dialogs/choice-picker.test.ts | 31 ++++++++++++++----- .../test/tui/kimi-tui-message-flow.test.ts | 6 +++- .../kimi-code/test/tui/message-replay.test.ts | 3 ++ 10 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 .changeset/clarify-permission-mode-copy.md diff --git a/.changeset/clarify-permission-mode-copy.md b/.changeset/clarify-permission-mode-copy.md new file mode 100644 index 0000000000..ca6dc08616 --- /dev/null +++ b/.changeset/clarify-permission-mode-copy.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Clarify which actions YOLO and Auto permission modes approve automatically across the CLI and TUI. diff --git a/apps/kimi-code/src/cli/commands.ts b/apps/kimi-code/src/cli/commands.ts index 960c707a6c..f7123f5c32 100644 --- a/apps/kimi-code/src/cli/commands.ts +++ b/apps/kimi-code/src/cli/commands.ts @@ -46,8 +46,16 @@ export function createProgram( ) .option('-c, --continue', 'Continue the previous session for the working directory.', false) .addOption(new Option('-C').hideHelp().default(false)) - .option('-y, --yolo', 'Auto-approve regular tool calls; the agent may still ask questions.', false) - .option('--auto', 'Start in auto permission mode: fully autonomous, the agent will not ask questions.', false) + .option( + '-y, --yolo', + 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', + false, + ) + .option( + '--auto', + 'Run unattended: auto-approve permission prompts and never ask questions.', + false, + ) .addOption( new Option( '-m, --model ', diff --git a/apps/kimi-code/src/tui/commands/config.ts b/apps/kimi-code/src/tui/commands/config.ts index 5cab011ea3..af8b999e7a 100644 --- a/apps/kimi-code/src/tui/commands/config.ts +++ b/apps/kimi-code/src/tui/commands/config.ts @@ -130,7 +130,10 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P } await session.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice('YOLO mode: ON', 'Tool actions auto-approved; the agent may still ask you questions.'); + host.showNotice( + 'YOLO mode: ON', + 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', + ); return; } @@ -153,7 +156,10 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P } else { await session.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice('YOLO mode: ON', 'Tool actions auto-approved; the agent may still ask you questions.'); + host.showNotice( + 'YOLO mode: ON', + 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', + ); } } @@ -174,7 +180,10 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P } await session.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice('Auto mode: ON', 'All actions auto-approved; the agent will not ask you questions.'); + host.showNotice( + 'Auto mode: ON', + 'Permission prompts auto-approved; the agent will not ask you questions.', + ); return; } @@ -197,7 +206,10 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P } else { await session.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice('Auto mode: ON', 'All actions auto-approved; the agent will not ask you questions.'); + host.showNotice( + 'Auto mode: ON', + 'Permission prompts auto-approved; the agent will not ask you questions.', + ); } } diff --git a/apps/kimi-code/src/tui/commands/registry.ts b/apps/kimi-code/src/tui/commands/registry.ts index 34556f7e62..bb024005d6 100644 --- a/apps/kimi-code/src/tui/commands/registry.ts +++ b/apps/kimi-code/src/tui/commands/registry.ts @@ -136,14 +136,16 @@ export const BUILTIN_SLASH_COMMANDS = [ { name: 'yolo', aliases: ['yes'], - description: 'Toggle YOLO mode: auto-approve tool actions, but the agent may still ask questions.', + description: + 'Toggle YOLO mode: auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', priority: 101, availability: 'always', }, { name: 'auto', aliases: [], - description: 'Toggle Auto mode: fully autonomous, agent decides everything without asking.', + description: + 'Toggle Auto mode: run unattended, auto-approve permission prompts, and never ask questions.', priority: 99, availability: 'always', }, diff --git a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts index c130987835..6fbc59dfa9 100644 --- a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts +++ b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts @@ -6,17 +6,18 @@ const PERMISSION_OPTIONS: readonly ChoiceOption[] = [ { value: 'manual', label: 'Manual', - description: 'Approve every action yourself.', + description: 'Review actions that require approval.', }, { value: 'yolo', label: 'YOLO', - description: 'Auto-approve tool actions, but the agent may still ask questions.', + description: + 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', }, { value: 'auto', label: 'Auto', - description: 'Fully autonomous — agent decides everything without asking.', + description: 'Run unattended — auto-approve permission prompts and never ask questions.', }, ]; diff --git a/apps/kimi-code/src/tui/controllers/session-replay.ts b/apps/kimi-code/src/tui/controllers/session-replay.ts index ad6e82358b..154d4b5679 100644 --- a/apps/kimi-code/src/tui/controllers/session-replay.ts +++ b/apps/kimi-code/src/tui/controllers/session-replay.ts @@ -569,7 +569,8 @@ export class SessionReplayRenderer { if (mode === 'yolo') { this.host.appendTranscriptEntry( replayEntry(context, 'status', 'YOLO mode: ON', 'notice', { - detail: 'Tool actions auto-approved; the agent may still ask you questions.', + detail: + 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', }), ); return; diff --git a/apps/kimi-code/test/tui/commands/registry.test.ts b/apps/kimi-code/test/tui/commands/registry.test.ts index bc4c5894fc..53d7a9a6ef 100644 --- a/apps/kimi-code/test/tui/commands/registry.test.ts +++ b/apps/kimi-code/test/tui/commands/registry.test.ts @@ -49,6 +49,15 @@ describe('built-in slash command registry', () => { expect(resolveSlashCommandAvailability(plan!, 'clear')).toBe('idle-only'); }); + it('describes YOLO and Auto according to their approval behavior', () => { + expect(findBuiltInSlashCommand('yolo')?.description).toBe( + 'Toggle YOLO mode: auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', + ); + expect(findBuiltInSlashCommand('auto')?.description).toBe( + 'Toggle Auto mode: run unattended, auto-approve permission prompts, and never ask questions.', + ); + }); + it('keeps swarm mode changes and swarm tasks idle-only', () => { const swarm = findBuiltInSlashCommand('swarm'); expect(swarm).toBeDefined(); diff --git a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts index ec590e252c..f6eea65fac 100644 --- a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts @@ -90,13 +90,6 @@ describe('ChoicePickerComponent', () => { }); expect(theme.render(120).map(strip)).toContain(' ❯ Light ← current'); - const permission = new PermissionSelectorComponent({ - currentValue: 'manual', - onSelect, - onCancel, - }); - expect(permission.render(120).map(strip)).toContain(' ❯ Manual ← current'); - const settings = new SettingsSelectorComponent({ onSelect, onCancel, @@ -116,6 +109,30 @@ describe('ChoicePickerComponent', () => { expect(upgradePreferenceOutput).toContain(' Install new versions in the background.'); }); + it('renders permission modes in increasing autonomy order with behavior-specific descriptions', () => { + const permission = new PermissionSelectorComponent({ + currentValue: 'manual', + onSelect: vi.fn(), + onCancel: vi.fn(), + }); + const permissionOutput = permission.render(120).map(strip); + + expect(permissionOutput).toContain(' ❯ Manual ← current'); + expect(permissionOutput).toContain(' Review actions that require approval.'); + expect(permissionOutput).toContain(' YOLO'); + expect(permissionOutput).toContain( + ' Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', + ); + expect(permissionOutput).toContain(' Auto'); + expect(permissionOutput).toContain( + ' Run unattended — auto-approve permission prompts and never ask questions.', + ); + expect(permissionOutput.indexOf(' ❯ Manual ← current')).toBeLessThan( + permissionOutput.indexOf(' YOLO'), + ); + expect(permissionOutput.indexOf(' YOLO')).toBeLessThan(permissionOutput.indexOf(' Auto')); + }); + it('routes Space into the query for searchable lists instead of selecting', () => { const onSelect = vi.fn(); const picker = new ChoicePickerComponent({ diff --git a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts index 567270558c..ca0e00a860 100644 --- a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts +++ b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts @@ -1223,7 +1223,11 @@ command = "vim" driver.handleUserInput('/auto on'); await vi.waitFor(() => { - expect(stripSgr(renderTranscript(driver))).toContain('Auto mode: ON'); + const transcript = stripSgr(renderTranscript(driver)); + expect(transcript).toContain('Auto mode: ON'); + expect(transcript).toContain( + 'Permission prompts auto-approved; the agent will not ask you questions.', + ); }); driver.handleUserInput('/undo 10'); diff --git a/apps/kimi-code/test/tui/message-replay.test.ts b/apps/kimi-code/test/tui/message-replay.test.ts index f3e5faa253..552cb3e232 100644 --- a/apps/kimi-code/test/tui/message-replay.test.ts +++ b/apps/kimi-code/test/tui/message-replay.test.ts @@ -1123,6 +1123,9 @@ describe('KimiTUI resume message replay', () => { expect(transcript).toContain('Plan mode: ON'); expect(transcript).toContain('Permission mode: auto'); expect(transcript).toContain('YOLO mode: ON'); + expect(transcript).toContain( + 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', + ); expect(transcript).toContain('YOLO mode: OFF'); expect(transcript).toContain('Approved for session: run command'); expect(transcript).toContain('Plan mode: OFF'); From 4f183fb2b2dcd95328740842fea6c78be2c821e0 Mon Sep 17 00:00:00 2001 From: whatevertogo <149563971+whatevertogo@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:31:36 +0800 Subject: [PATCH 2/3] style(cli): preserve permission copy layout Keep the updated permission descriptions in the existing one-line call and property layout without applying unrelated whole-file formatting. --- apps/kimi-code/src/cli/commands.ts | 12 ++--------- apps/kimi-code/src/tui/commands/config.ts | 20 ++++--------------- apps/kimi-code/src/tui/commands/registry.ts | 6 ++---- .../components/dialogs/permission-selector.ts | 3 +-- .../src/tui/controllers/session-replay.ts | 3 +-- 5 files changed, 10 insertions(+), 34 deletions(-) diff --git a/apps/kimi-code/src/cli/commands.ts b/apps/kimi-code/src/cli/commands.ts index f7123f5c32..330c601434 100644 --- a/apps/kimi-code/src/cli/commands.ts +++ b/apps/kimi-code/src/cli/commands.ts @@ -46,16 +46,8 @@ export function createProgram( ) .option('-c, --continue', 'Continue the previous session for the working directory.', false) .addOption(new Option('-C').hideHelp().default(false)) - .option( - '-y, --yolo', - 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', - false, - ) - .option( - '--auto', - 'Run unattended: auto-approve permission prompts and never ask questions.', - false, - ) + .option('-y, --yolo', 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', false) + .option('--auto', 'Run unattended: auto-approve permission prompts and never ask questions.', false) .addOption( new Option( '-m, --model ', diff --git a/apps/kimi-code/src/tui/commands/config.ts b/apps/kimi-code/src/tui/commands/config.ts index af8b999e7a..e84e5a13a7 100644 --- a/apps/kimi-code/src/tui/commands/config.ts +++ b/apps/kimi-code/src/tui/commands/config.ts @@ -130,10 +130,7 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P } await session.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice( - 'YOLO mode: ON', - 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', - ); + host.showNotice('YOLO mode: ON', 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.'); return; } @@ -156,10 +153,7 @@ export async function handleYoloCommand(host: SlashCommandHost, args: string): P } else { await session.setPermission('yolo'); host.setAppState({ permissionMode: 'yolo' }); - host.showNotice( - 'YOLO mode: ON', - 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', - ); + host.showNotice('YOLO mode: ON', 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.'); } } @@ -180,10 +174,7 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P } await session.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice( - 'Auto mode: ON', - 'Permission prompts auto-approved; the agent will not ask you questions.', - ); + host.showNotice('Auto mode: ON', 'Permission prompts auto-approved; the agent will not ask you questions.'); return; } @@ -206,10 +197,7 @@ export async function handleAutoCommand(host: SlashCommandHost, args: string): P } else { await session.setPermission('auto'); host.setAppState({ permissionMode: 'auto' }); - host.showNotice( - 'Auto mode: ON', - 'Permission prompts auto-approved; the agent will not ask you questions.', - ); + host.showNotice('Auto mode: ON', 'Permission prompts auto-approved; the agent will not ask you questions.'); } } diff --git a/apps/kimi-code/src/tui/commands/registry.ts b/apps/kimi-code/src/tui/commands/registry.ts index bb024005d6..500a018e01 100644 --- a/apps/kimi-code/src/tui/commands/registry.ts +++ b/apps/kimi-code/src/tui/commands/registry.ts @@ -136,16 +136,14 @@ export const BUILTIN_SLASH_COMMANDS = [ { name: 'yolo', aliases: ['yes'], - description: - 'Toggle YOLO mode: auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', + description: 'Toggle YOLO mode: auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', priority: 101, availability: 'always', }, { name: 'auto', aliases: [], - description: - 'Toggle Auto mode: run unattended, auto-approve permission prompts, and never ask questions.', + description: 'Toggle Auto mode: run unattended, auto-approve permission prompts, and never ask questions.', priority: 99, availability: 'always', }, diff --git a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts index 6fbc59dfa9..1091a3ae8d 100644 --- a/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts +++ b/apps/kimi-code/src/tui/components/dialogs/permission-selector.ts @@ -11,8 +11,7 @@ const PERMISSION_OPTIONS: readonly ChoiceOption[] = [ { value: 'yolo', label: 'YOLO', - description: - 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', + description: 'Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', }, { value: 'auto', diff --git a/apps/kimi-code/src/tui/controllers/session-replay.ts b/apps/kimi-code/src/tui/controllers/session-replay.ts index 154d4b5679..af91b03cfb 100644 --- a/apps/kimi-code/src/tui/controllers/session-replay.ts +++ b/apps/kimi-code/src/tui/controllers/session-replay.ts @@ -569,8 +569,7 @@ export class SessionReplayRenderer { if (mode === 'yolo') { this.host.appendTranscriptEntry( replayEntry(context, 'status', 'YOLO mode: ON', 'notice', { - detail: - 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', + detail: 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', }), ); return; From 0b56643ae7e2a0128a3d9269a2239778a4c96926 Mon Sep 17 00:00:00 2001 From: whatevertogo <149563971+whatevertogo@users.noreply.github.com> Date: Sat, 18 Jul 2026 17:12:09 +0800 Subject: [PATCH 3/3] test(tui): remove redundant permission copy assertions Keep the existing behavior-level coverage without pinning user-facing permission descriptions verbatim in multiple test suites. --- .../test/tui/commands/registry.test.ts | 9 ------ .../components/dialogs/choice-picker.test.ts | 31 +++++-------------- .../test/tui/kimi-tui-message-flow.test.ts | 6 +--- .../kimi-code/test/tui/message-replay.test.ts | 3 -- 4 files changed, 8 insertions(+), 41 deletions(-) diff --git a/apps/kimi-code/test/tui/commands/registry.test.ts b/apps/kimi-code/test/tui/commands/registry.test.ts index 53d7a9a6ef..bc4c5894fc 100644 --- a/apps/kimi-code/test/tui/commands/registry.test.ts +++ b/apps/kimi-code/test/tui/commands/registry.test.ts @@ -49,15 +49,6 @@ describe('built-in slash command registry', () => { expect(resolveSlashCommandAvailability(plan!, 'clear')).toBe('idle-only'); }); - it('describes YOLO and Auto according to their approval behavior', () => { - expect(findBuiltInSlashCommand('yolo')?.description).toBe( - 'Toggle YOLO mode: auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', - ); - expect(findBuiltInSlashCommand('auto')?.description).toBe( - 'Toggle Auto mode: run unattended, auto-approve permission prompts, and never ask questions.', - ); - }); - it('keeps swarm mode changes and swarm tasks idle-only', () => { const swarm = findBuiltInSlashCommand('swarm'); expect(swarm).toBeDefined(); diff --git a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts index f6eea65fac..ec590e252c 100644 --- a/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/choice-picker.test.ts @@ -90,6 +90,13 @@ describe('ChoicePickerComponent', () => { }); expect(theme.render(120).map(strip)).toContain(' ❯ Light ← current'); + const permission = new PermissionSelectorComponent({ + currentValue: 'manual', + onSelect, + onCancel, + }); + expect(permission.render(120).map(strip)).toContain(' ❯ Manual ← current'); + const settings = new SettingsSelectorComponent({ onSelect, onCancel, @@ -109,30 +116,6 @@ describe('ChoicePickerComponent', () => { expect(upgradePreferenceOutput).toContain(' Install new versions in the background.'); }); - it('renders permission modes in increasing autonomy order with behavior-specific descriptions', () => { - const permission = new PermissionSelectorComponent({ - currentValue: 'manual', - onSelect: vi.fn(), - onCancel: vi.fn(), - }); - const permissionOutput = permission.render(120).map(strip); - - expect(permissionOutput).toContain(' ❯ Manual ← current'); - expect(permissionOutput).toContain(' Review actions that require approval.'); - expect(permissionOutput).toContain(' YOLO'); - expect(permissionOutput).toContain( - ' Auto-approve regular tools; sensitive actions may still need approval, and the agent may ask.', - ); - expect(permissionOutput).toContain(' Auto'); - expect(permissionOutput).toContain( - ' Run unattended — auto-approve permission prompts and never ask questions.', - ); - expect(permissionOutput.indexOf(' ❯ Manual ← current')).toBeLessThan( - permissionOutput.indexOf(' YOLO'), - ); - expect(permissionOutput.indexOf(' YOLO')).toBeLessThan(permissionOutput.indexOf(' Auto')); - }); - it('routes Space into the query for searchable lists instead of selecting', () => { const onSelect = vi.fn(); const picker = new ChoicePickerComponent({ diff --git a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts index ca0e00a860..567270558c 100644 --- a/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts +++ b/apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts @@ -1223,11 +1223,7 @@ command = "vim" driver.handleUserInput('/auto on'); await vi.waitFor(() => { - const transcript = stripSgr(renderTranscript(driver)); - expect(transcript).toContain('Auto mode: ON'); - expect(transcript).toContain( - 'Permission prompts auto-approved; the agent will not ask you questions.', - ); + expect(stripSgr(renderTranscript(driver))).toContain('Auto mode: ON'); }); driver.handleUserInput('/undo 10'); diff --git a/apps/kimi-code/test/tui/message-replay.test.ts b/apps/kimi-code/test/tui/message-replay.test.ts index 552cb3e232..f3e5faa253 100644 --- a/apps/kimi-code/test/tui/message-replay.test.ts +++ b/apps/kimi-code/test/tui/message-replay.test.ts @@ -1123,9 +1123,6 @@ describe('KimiTUI resume message replay', () => { expect(transcript).toContain('Plan mode: ON'); expect(transcript).toContain('Permission mode: auto'); expect(transcript).toContain('YOLO mode: ON'); - expect(transcript).toContain( - 'Regular tools auto-approved; sensitive actions may still need approval, and the agent may ask.', - ); expect(transcript).toContain('YOLO mode: OFF'); expect(transcript).toContain('Approved for session: run command'); expect(transcript).toContain('Plan mode: OFF');