Skip to content

feat(shell): unified approval modes with toolbar badges and temporary toasts#2249

Open
baldasso wants to merge 1 commit into
MoonshotAI:mainfrom
baldasso:feat/session-auto-approve-badges
Open

feat(shell): unified approval modes with toolbar badges and temporary toasts#2249
baldasso wants to merge 1 commit into
MoonshotAI:mainfrom
baldasso:feat/session-auto-approve-badges

Conversation

@baldasso
Copy link
Copy Markdown

@baldasso baldasso commented May 12, 2026

What problem does this solve?

Right now, Kimi has four different ways to control auto-approval:

  • --yolo flag
  • --afk flag
  • /yolo slash command
  • /afk slash command
  • The per-session "Approve for session" button

They all do slightly different things, overlap in confusing ways, and—most importantly—there's no way to see which one is active without remembering what you typed five minutes ago. New users have no mental model for how permission levels work.

This PR fixes that by introducing a single, progressive three-level system that's always visible in the UI.

Closes #2105
Closes #1631


The new model: manual → edits → auto

Mode What it does When to use
manual Ask before every action Default. Safe. You stay in control.
edits Auto-approve file ops only (edit, replace, edit_outside) Let Kimi refactor code without interrupting you
auto Auto-approve everything Full trust mode for well-scoped tasks

Plan mode is included in the cycle as a fourth stop (manual → edits → auto → plan → manual) so you can jump into read-only planning without hunting for the slash command.


What it looks like

Bottom toolbar — always know your mode

  • ◐ edits (green) when file operations are auto-approved
  • ● auto (amber) when everything is auto-approved
  • No badge in manual mode — clean, uncluttered default

Input border — instant visual feedback

  • Manual: ── input ── grey solid
  • Edits: ╌╌ input · edits ════════ green dashed
  • Auto: ╌╌ input · auto ════════ amber dashed
  • Plan: ╌╌ input · plan ════════ blue dashed

Shift+Tab to cycle

Press Shift+Tab to cycle through modes. A descriptive toast appears for 5 seconds:

"edits mode — agent can edit files without asking"

Then it disappears. No permanent clutter.

Demo

Screen.Recording.2026-05-12.at.16.36.13.mov

How we got here

This design directly addresses three long-standing community requests:

The naming (manual / edits / auto) was chosen for literal, impossible-to-misunderstand clarity over clever metaphors. Safety-critical UI should not be cute.


Backward compatibility — your existing sessions still work

  • Existing state.json files with yolo=True or afk=True load seamlessly; they map to approval_mode="auto"
  • The /yolo and /afk slash commands still work (they set auto mode internally)
  • The --yolo and --afk CLI flags still work
  • Legacy fields (yolo, afk, auto_approve_actions) are preserved in ApprovalStateData

The old flags are now "implementation details" — the UI speaks the new language.


Technical details

  • New ApprovalMode = Literal["manual", "edits", "auto"] replaces boolean flag soup in the approval state machine
  • _migrate_legacy_approval_state() promotes old flags on session load
  • "Approve for session" on a file action auto-promotes to edits; anything else promotes to auto
  • Toolbar badge rendering degrades gracefully on narrow terminals

Testing

  • 1517/1517 tests pass (no regressions)
  • New tests cover badge rendering and toast messages

Checklist

  • Single-line commit message, no co-author
  • Consistent naming across types, variables, comments, tests
  • ApprovalMode type alias used everywhere
  • Legacy session state migration handled
  • No references to old internal names left in approval code

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment thread src/kimi_cli/soul/approval.py Outdated
type Response = Literal["approve", "approve_for_session", "reject"]

# Actions that touch files but do not execute arbitrary shell commands.
_FILE_ACTIONS = frozenset({"edit", "edit_outside", "replace"})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 _FILE_ACTIONS contains wrong action strings, making 'files' approval mode completely non-functional

The _FILE_ACTIONS frozenset at src/kimi_cli/soul/approval.py:21 contains {"edit", "edit_outside", "replace"}, but these strings are never used as action names anywhere in the codebase. The actual action strings passed to approval.request() come from the FileActions StrEnum (src/kimi_cli/tools/file/__init__.py:10-13): "edit file" (FileActions.EDIT) and "edit file outside of working directory" (FileActions.EDIT_OUTSIDE). The string "replace" is never used as an action at all.

This causes two failures:

  1. _should_auto_approve() in "files" mode never auto-approves (line 198-199): action in _FILE_ACTIONS is always False, so the "files" mode behaves identically to "ask" — the user is still prompted for every file edit.
  2. approve_for_session never promotes to "files" mode (line 301): The condition action in _FILE_ACTIONS is always False, so approving a file action "for session" always falls through to the elif at line 303 and escalates directly to "all" mode, skipping the intended intermediate "files" mode entirely.
Suggested change
_FILE_ACTIONS = frozenset({"edit", "edit_outside", "replace"})
_FILE_ACTIONS = frozenset({"edit file", "edit file outside of working directory"})
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. _FILE_ACTIONS now uses the actual action strings from FileActions enum: "edit file" and "edit file outside of working directory".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

from kimi_cli.utils.logging import logger

P2 Badge Match file approval action values

In edits mode, file tools still prompt because the actions passed by WriteFile/StrReplaceFile are the FileActions values ("edit file" and "edit file outside of working directory"), not "edit" or "edit_outside". With approval_mode == "files", _should_auto_approve() therefore returns false for normal file writes/edits and falls through to the manual approval request, so the new edits mode does not actually auto-approve its primary workflow.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 292 to 295
approval_state = ApprovalState(
yolo=effective_yolo,
approval_mode=effective_mode,
yolo=session.state.approval.yolo,
afk=session.state.approval.afk,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the --yolo flag in approval state

When an interactive session is started with --yolo, effective_mode becomes "all" but the shared state keeps yolo from the persisted session instead of the invocation flag. In that scenario /yolo checks is_yolo_flag(), sees false, and turns yolo on rather than disabling auto-approval on the first toggle, which is a regression from the previous effective_yolo = yolo or session.state.approval.yolo behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. ApprovalState now receives yolo or session.state.approval.yolo, so invocation-time --yolo correctly sets the internal yolo flag and /yolo toggle works as expected on first use.

@baldasso baldasso force-pushed the feat/session-auto-approve-badges branch from 2e8d9de to e9fbf13 Compare May 12, 2026 19:44
@baldasso
Copy link
Copy Markdown
Author

Fixed both issues flagged by the AI reviews:

  1. _FILE_ACTIONS mismatch (approval.py:21): Updated to use the actual action strings passed by file tools — "edit file" and "edit file outside of working directory" — instead of the stale "edit" / "edit_outside" / "replace" placeholders.

  2. --yolo flag not preserved (agent.py:295): Now passes yolo or session.state.approval.yolo to ApprovalState so invocation-time --yolo correctly sets the internal yolo flag, making /yolo toggle behave as expected on first use.

Amended and force-pushed.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9fbf13ef8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/kimi_cli/session_state.py Outdated
Comment on lines +111 to +112
elif approval.auto_approve_actions:
approval.approval_mode = "edits"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid promoting arbitrary legacy approvals to edits

When resuming a legacy session where "Approve for session" was used for a non-file action such as ShellTool's "run command", this migration sets approval_mode to "edits" just because auto_approve_actions is non-empty. The old action set is still preserved and checked later, so shell commands remain auto-approved while the toolbar only says edits, and the new edits mode also starts auto-approving all file edits; that both misrepresents and broadens the resumed session's approval scope.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Removed the promotion of auto_approve_actions to edits mode. The legacy set continues to work under manual mode (checked in Approval.request), so promoting it would have both broadened the approval scope and misrepresented the state in the toolbar.

@baldasso baldasso force-pushed the feat/session-auto-approve-badges branch from e9fbf13 to d6df535 Compare May 12, 2026 21:39
@baldasso
Copy link
Copy Markdown
Author

All three AI-review issues are now fixed in the amended commit:

  1. ** strings** (approval.py:21) — Updated to match actual tool action strings: and .

  2. ** invocation flag** (agent.py:295) — Now passes to so invocation-time is reflected in the internal flag.

  3. ** migration** (session_state.py:112) — Removed the promotion to . Legacy continues to work under mode (checked in ), so promoting it would have broadened the approval scope and misrepresented the state in the toolbar.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6df53555c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +77 to +78
elif approval_mode == "manual" and auto_approve_actions:
approval_mode = "edits"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid promoting legacy action approvals to edits

Fresh evidence: load_session_state() now intentionally leaves legacy auto_approve_actions in manual mode, but Runtime.create() still passes that set into this constructor, and this branch promotes any non-empty set to edits. Resuming a session that previously approved only a non-file action such as run command therefore shows edits mode and starts auto-approving all file edits while the old shell action remains auto-approved via the preserved set, broadening the session's approval scope.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Unified Auto Mode as a first-class feature Feature Request: Granular Auto-Approval Rules (like Claude Code)

1 participant