What version of Kimi Code is running?
0.29.1 (kimi --version)
Which open platform/subscription were you using?
N/A — bug is in the local CLI input handling, independent of model/platform.
Which model were you using?
kimi-code/kimi-for-coding (K2.7 Coding), but the bug is model-independent.
What platform is your computer?
Remote Linux host (Ubuntu 22.04.5 LTS, x86_64) accessed via SSH from macOS.
What issue are you seeing?
When a child process (e.g. yazi --version) crashes due to a dynamic-link error, the terminal sends control sequences (CSI/OSC) to synchronize state. Kimi Code's stdin reader captures these sequences and treats them as user input, which triggers an immediate cancelAll() abort of the currently executing turn. The CLI then displays "Interrupted by user" even though the user never pressed Ctrl+C or sent any input.
Concrete symptom
• Used Shell (which yazi && yazi --version && ya --version)
Interrupted by user
The user did not interrupt. The interruption was caused by terminal escape sequences leaking into the user-input stream.
What steps can reproduce the bug?
- SSH into a Linux host from a terminal that supports Kitty keyboard protocol (e.g. Ghostty, Kitty, WezTerm).
- Run
kimi on the remote host.
- Ask kimi to install a TUI binary whose
.deb is compiled against a newer glibc than the host has (e.g. yazi v26.5.6 .deb on Ubuntu 22.04 with glibc 2.35).
- kimi downloads and installs the
.deb via dpkg, then runs yazi --version to verify.
yazi crashes with:
yazi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.39' not found (required by yazi)
- The child process exits with code 1. The terminal emulator detects the TTY state change and automatically sends sync/query sequences.
- Bug: These sequences appear in kimi's stdin and are interpreted as a new user message, causing the active turn to be cancelled.
Evidence from logs
Terminal control sequences captured as user input
In ~/.kimi/logs/kimi.log, a prior session shows the exact bytes that were captured:
2026-07-25 15:25:59 | INFO | ...run_soul_command:827 |
Running soul with user input: [TextPart(type='text', text='a\[6;18;8t]11;rgb:1515/1919/1e1e[?1;2;4c[6;18;8t]11;rgb:1515/1919/1e1e什么情况,我是指安装https://github.com/sxyazi/yaziGi=31;OK')]
The prefix contains literal CSI sequences:
ESC[6;18;8t — terminal window size report/query
11;rgb:1515/1919/1e1e — OSC color response
ESC[?1;2;4c — DA (device attributes) response
These were not typed by the user — they were injected by the SSH client/terminal emulator after the child process crashed.
The "cancel" log line
2026-07-25 15:28:36 | INFO | ...run_soul_command:1016 | - Cancelled by user
This happened at the exact moment after yazi --version crashed, with no human input in between.
Wire log confirms no ToolResult for the verification command
In wire.jsonl for session 23ed76c0-bb1f-4327-84be-7a92cdcbb1ee:
{"type": "ToolCall", ... "function": {"name": "Shell", "arguments": "{\"command\": \"which yazi && yazi --version && ya --version\", \"timeout\": 30}"}}
{"type": "TurnEnd", "payload": {}}
There is no ToolResult event after the ToolCall. The turn was aborted before the shell command could complete and return its output.
Root cause analysis
- Child process crash changes TTY state:
yazi is a TUI application. Even --version may initialize terminal modes (or the dynamic-linker crash path leaves the TTY in an inconsistent state).
- Terminal emulator sends sync sequences: When it detects the child has exited, the terminal sends CSI/OSC sequences to query/restore state.
- kimi's stdin reader captures raw bytes: The sequences arrive on stdin alongside or immediately after the shell command's output stream closes.
- Input parser treats them as user text: The sequences are not filtered out; they become a
TextPart user message.
- New user message triggers
cancelAll(): kimi sees "new user input" while a turn is in progress, aborts the active turn, and marks it as "Cancelled by user".
What is the expected behavior?
- Terminal control sequences (CSI
ESC[, OSC ESC], ST ESC\) should never be interpreted as user input.
- When a child process exits abnormally, kimi should wait for the
ToolResult (with the error output and non-zero exit code) and display it normally.
- The turn should continue until the LLM has processed the result, not be prematurely cancelled.
Suggested fix
Filter terminal escape sequences from the stdin input stream before passing them to the user-input parser:
# Pseudocode for the input sanitization layer
CSI_PATTERN = re.compile(r'\x1b\[[0-?]*[ -/]*[@-~]') # ESC [ ... letter
OSC_PATTERN = re.compile(r'\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?') # ESC ] ... ST
APC_PATTERN = re.compile(r'\x1b_[^\x1b]*(?:\x1b\\)?') # ESC _ ... ST
Or, more robustly: the input reader should only accept printable characters and explicit user actions (Enter, Ctrl+C, etc.) and drop any byte sequence that starts with ESC (0x1b) unless it is a known keybinding (e.g. arrow keys, which should be translated to their semantic meaning, not passed through as raw bytes).
Additional information
- kimi-code version: 0.29.1 (binary release,
~/.kimi-code/bin/kimi)
- Host OS: Ubuntu 22.04.5 LTS, glibc 2.35
- Terminal: Ghostty on macOS (client), SSH to remote Linux host
- SSH config:
ServerAliveInterval 240, TCPKeepAlive yes
- Workaround: Fix the underlying cause that makes the child crash (e.g. install a musl-linked binary instead of glibc-linked) so the TTY state change never happens.
Related but distinct issues
What version of Kimi Code is running?
0.29.1(kimi --version)Which open platform/subscription were you using?
N/A — bug is in the local CLI input handling, independent of model/platform.
Which model were you using?
kimi-code/kimi-for-coding(K2.7 Coding), but the bug is model-independent.What platform is your computer?
Remote Linux host (Ubuntu 22.04.5 LTS, x86_64) accessed via SSH from macOS.
What issue are you seeing?
When a child process (e.g.
yazi --version) crashes due to a dynamic-link error, the terminal sends control sequences (CSI/OSC) to synchronize state. Kimi Code's stdin reader captures these sequences and treats them as user input, which triggers an immediatecancelAll()abort of the currently executing turn. The CLI then displays "Interrupted by user" even though the user never pressed Ctrl+C or sent any input.Concrete symptom
The user did not interrupt. The interruption was caused by terminal escape sequences leaking into the user-input stream.
What steps can reproduce the bug?
kimion the remote host..debis compiled against a newer glibc than the host has (e.g. yazi v26.5.6 .deb on Ubuntu 22.04 with glibc 2.35)..debviadpkg, then runsyazi --versionto verify.yazicrashes with:Evidence from logs
Terminal control sequences captured as user input
In
~/.kimi/logs/kimi.log, a prior session shows the exact bytes that were captured:The prefix contains literal CSI sequences:
ESC[6;18;8t— terminal window size report/query11;rgb:1515/1919/1e1e— OSC color responseESC[?1;2;4c— DA (device attributes) responseThese were not typed by the user — they were injected by the SSH client/terminal emulator after the child process crashed.
The "cancel" log line
This happened at the exact moment after
yazi --versioncrashed, with no human input in between.Wire log confirms no ToolResult for the verification command
In
wire.jsonlfor session23ed76c0-bb1f-4327-84be-7a92cdcbb1ee:{"type": "ToolCall", ... "function": {"name": "Shell", "arguments": "{\"command\": \"which yazi && yazi --version && ya --version\", \"timeout\": 30}"}} {"type": "TurnEnd", "payload": {}}There is no
ToolResultevent after theToolCall. The turn was aborted before the shell command could complete and return its output.Root cause analysis
yaziis a TUI application. Even--versionmay initialize terminal modes (or the dynamic-linker crash path leaves the TTY in an inconsistent state).TextPartuser message.cancelAll(): kimi sees "new user input" while a turn is in progress, aborts the active turn, and marks it as "Cancelled by user".What is the expected behavior?
ESC[, OSCESC], STESC\) should never be interpreted as user input.ToolResult(with the error output and non-zero exit code) and display it normally.Suggested fix
Filter terminal escape sequences from the stdin input stream before passing them to the user-input parser:
Or, more robustly: the input reader should only accept printable characters and explicit user actions (Enter, Ctrl+C, etc.) and drop any byte sequence that starts with
ESC(0x1b) unless it is a known keybinding (e.g. arrow keys, which should be translated to their semantic meaning, not passed through as raw bytes).Additional information
~/.kimi-code/bin/kimi)ServerAliveInterval 240,TCPKeepAlive yesRelated but distinct issues
13;129u#1984 — Terminal left in Kitty keyboard protocol after abnormal exit (SSH disconnect). That issue is about teardown (not restoring terminal modes on exit). This issue is about input ingestion (terminal sequences leaking into the user-input stream while a turn is active).