Web UI shows the wrong permission mode — /status permission never synced (yolo/auto displays as manual)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 74/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- frontend
Research direction
Start in apps/kimi-web/src/composables/useKimiWebClient.ts, especially refreshSessionStatus and the rawState.permission initialization. Compare the status mapping in apps/kimi-web/src/client.ts and the permission type in types.ts, then trace the displayed permission computed state. Done means the indicator reflects the attached session's server-reported manual, auto, or yolo permission after loading and refreshing, with the chosen session-scope behavior verified.
Written by the indexing model from the issue text.
Description
What version of Kimi Code is running?
0.22.3 (web SPA / kimi server run surface). The affected code path is unchanged on current main.
Which open platform/subscription were you using?
Not applicable — this is a client-side display bug in the web SPA, independent of the /login plan.
Which model were you using?
Not applicable — provider/model-independent (purely client-side UI state).
What platform is your computer?
Any (browser-based web SPA); reproduced on Linux.
What issue are you seeing?
The web UI's permission-mode indicator does not reflect the session's actual permission. It is seeded from browser localStorage (default manual) and is never updated from the session's real permission, even though the SPA already fetches GET /sessions/{id}/status, whose response includes the authoritative permission field. A session running in yolo (or auto) is displayed as manual, misleading the operator about whether tool actions are being auto-approved.
Root cause — two facts in the web client:
- Displayed permission is driven by
localStorage, not the session. Inapps/kimi-web/src/composables/useKimiWebClient.ts: state is seededpermission: loadPermissionFromStorage()(:363;loadPermissionFromStoragedefaults to'manual'at:130) and displayed viacomputed(() => rawState.permission)(:1732). The only write torawState.permissionis the user's explicit optimisticsetPermission(apps/kimi-web/src/composables/client/useWorkspaceState.ts:1560-1561). Nothing syncs it from the session. - The
/statusfold ignorespermission.refreshSessionStatus(useKimiWebClient.ts:583) folds onlymodel, context tokens,swarmMode, andplanMode.st.permissionis present (client.ts:399maps the wirepermissionfield intoAppSessionRuntimeStatus.permission,types.ts:98) but is never applied torawState.permission. So the fetched status corrects model/context/plan/swarm, but leaves permission at the stalelocalStorage/manualdefault.
Impact: safety-relevant, not cosmetic — the operator sees manual and may assume every tool action will be confirmed, while the agent is actually auto-approving everything (yolo). Also affects auto shown as manual. The daemon side is correct; /status already returns an accurate permission. This is purely a client-side sync gap.
What steps can reproduce the bug?
- Set
default_permission_mode = "yolo"at the root ofconfig.toml. - Start
kimi server run(the web SPA), open the web UI, create/open a session. - Observe the permission indicator shows
manualeven after a full reload. - Confirm the server disagrees:
GET /api/v1/sessions/<id>/status→"permission": "yolo"(both the SPA's own session and a freshPOST /api/v1/sessionsone).
Behavioral confirmation the session is really yolo: the agent read a file via a tool without surfacing a tool-approval prompt (a manual session would prompt first) → tools were auto-approved. Only the label is wrong.
What is the expected behavior?
The permission indicator should reflect the session's server-side permission (yolo/auto/manual), synced from GET /sessions/{id}/status, rather than a stale localStorage default.
Additional information
Suggested fix: fold /status permission into reactive state exactly like swarmMode/planMode. In refreshSessionStatus (useKimiWebClient.ts:583, where rawState is already in scope):
rawState.permission = st.permission;
Permission is currently a single global rawState.permission (unlike the per-session planModeBySession/swarmModeBySession); if the indicator should be per-session, key it by sessionId (permissionBySession[sessionId] = st.permission) and drive the computed getter from the active session. Also worth reconsidering whether seeding from localStorage should win over an attached session's server-side permission at all.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 41m
- Merged PRs (30d)
- 345
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MoonshotAI/kimi-code
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
MoonshotAI/kimi-code#3947 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
MoonshotAI/kimi-code#3836 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
MoonshotAI/kimi-code#3790 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
MoonshotAI/kimi-code#3755 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
MoonshotAI/kimi-code#3627 ·
All issues in MoonshotAI/kimi-code
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100