MoonshotAI / MoonshotAI/kimi-code
UserPromptSubmit denial displays the hook result but leaves the TUI pending until Ctrl-S
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
What version of Kimi Code is running?
0.42.0
Which open platform/subscription were you using?
Kimi Platform (API key · platform.kimi.ai)
Which model were you using?
kimi-k3
What platform is your computer?
Darwin 25.6.0 arm64 arm
What issue are you seeing?
A UserPromptSubmit hook that denies submission (to display a result and skip the model call) shows the result, but the TUI never finishes the pending interaction on its own. A following prompt stays queued until I press Ctrl-S ("steer immediately"). Both exit-0 structured denial and exit-2 denial reproduce it; changing the hook output form does not resolve the stall.
Source-level findings (verified against 0.42.0 commit 6954d2c8bf94a5c7fc29cc6ae35b15d042cc4dcb and current main d3dc5945548d3353a5e6cfc457a3a8cf84d7da71):
- The engine does emit
prompt.completedwithreason: "blocked", but the SDK filters it out before it reaches the TUI:prompt.completedis inDROPPED_DOMAIN_EVENT_TYPES(packages/node-sdk/src/v2/event-mapper.ts, entry at L38 on main, filter at L68). - The blocked path publishes completion and returns before
loop.submit, so no engine turn starts or ends (packages/agent-core-v2/src/agent/prompt/promptService.tsL547–552). - The TUI finalizes an interaction on
turn.ended(apps/kimi-code/src/tui/controllers/session-event-handler.tsL369–391); thehook.resulthandler (L594–617) renders the result without finalizing.
Net: on the hook-denial path the TUI gets the display event but neither a forwarded prompt.completed nor a turn.ended, so it never returns to idle.
What steps can reproduce the bug?
- Add this rule to
~/.kimi-code/config.toml, then start a new interactivekimisession:
[[hooks]]
event = "UserPromptSubmit"
matcher = "^hook-stall$"
command = "printf '%s\\n' 'Hook handled this prompt; model submission skipped.' >&2; exit 2"
- Submit
hook-stall. The hook result is displayed and model submission is denied. - Submit a nonmatching prompt, such as
Reply with OK. It stays pending instead of being processed. - Press Ctrl-S (“steer immediately”); the following prompt can then proceed.
For the exit-0 variant, replace only command with:
command = '''
printf '%s\n' '{"message":"Hook handled this prompt; model submission skipped.","hookSpecificOutput":{"permissionDecision":"deny","permissionDecisionReason":"Handled by hook"}}'
exit 0
'''
Use one variant at a time. The explicit message avoids conflating this with raw JSON display when that field is absent.
What is the expected behavior?
After displaying the hook result and denying submission, the TUI should finish the interaction cleanly, return to idle, and process the next prompt normally without ctrl-s.
Additional information
Related: #3464 (client stalls / invisible completed work, but for compaction/rendering and queueing, not this hook-denial path), #3568 (raw hook JSON when no message field — here the result displays fine; completion stalls with either output form), #3536 (proposed model-visible/terminal-hidden context), PR #929 (suppress allowed hook output while keeping blocking output visible — this is about finishing after that visible blocking result).
Contribution
- I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)
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.
Research direction
Start with packages/agent-core-v2/src/agent/prompt/promptService.ts and trace the blocked path, then inspect packages/node-sdk/src/v2/event-mapper.ts and apps/kimi-code/src/tui/controllers/session-event-handler.ts. Reproduce the denial with the provided hook configuration and follow the prompt completion events. Done means the displayed denial returns the TUI to idle and a subsequent prompt is processed without Ctrl-S.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100