MoonshotAI / MoonshotAI/kimi-cli

Shell tool interactive commands cause terminal input corruption and hangs (missing PTY allocation)

Open
#2,037 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
11.4k
Forks
1.3k
Avg merge
9h 47m
Merged PRs (30d)
2

Description

Shell tool interactive commands cause terminal input corruption and hangs (missing PTY allocation)

Summary

The Shell tool explicitly closes stdin and does not allocate a pseudo-terminal (PTY). This breaks interactive commands (ssh-add, sudo, npm init, etc.) in a way that is worse than a clean failure — it creates a terminal input race condition where both the subprocess and Kimi CLI's prompt_toolkit fight over /dev/tty, causing characters to appear slowly or not at all.

Other CLI agents (Claude Code, Gemini CLI, Codex CLI) handle this correctly by either allocating a PTY for subprocesses or suspending their own input loop to yield the terminal to interactive commands.

Root Cause

In tools/shell/__init__.py:

process = await kaos.exec(*self._shell_args(command), env=get_noninteractive_env())
process.stdin.close()  # <-- EOF immediately; no interactive input possible

The stdin.close() prevents clean interactive input. However, tools like ssh-add bypass stdin entirely and open /dev/tty directly via getpass(). This creates the following conflict:

Layer Reads from Behavior
ssh-add /dev/tty Puts terminal into no-echo mode, waits for passphrase
Kimi CLI (prompt_toolkit) stdin (same terminal fd) Also reading keystrokes for chat input
Result Both race for the same bytes Characters appear erratically or with extreme delay

Reproduction

  1. Ensure ssh-agent has no loaded keys: ssh-add -D
  2. In Kimi CLI, run: Shell (ssh-add ~/.ssh/id_ed25519 && git push origin main)
  3. Observe that ssh-add prints Enter passphrase for /Users/.../.ssh/id_ed25519:
  4. Attempt to type the passphrase
  5. Expected: Clean interactive prompt where typing works normally
    Actual: Each character takes 1–3+ seconds to appear; backspace is equally broken; the experience is unusable

Comparison with other CLI agents

Tool PTY allocation Interactive subprocess behavior
Claude Code ✅ Yes (pty.openpty or equivalent) Interactive commands work natively; agent yields terminal control
Gemini CLI ✅ Yes Same — interactive subprocesses receive clean TTY access
Codex CLI ✅ Yes Same
Kimi CLI ❌ No (stdin.close()) Terminal input corruption; race between subprocess and prompt_toolkit

Why this matters beyond "nice to have"

This is not just a missing feature — it is a reliability bug. The current behavior:

  • Leaves zombie ssh-add processes hanging on /dev/tty
  • Corrupts the terminal state (no-echo mode from getpass() may not be restored if the subprocess is killed by timeout)
  • Makes Kimi CLI unusable for any workflow involving SSH passphrases, sudo, or interactive CLI tools
  • Forces users to drop out of Kimi CLI into a native terminal for basic Git operations

Suggested fixes

Option A: Allocate a PTY for shell subprocesses (best)

Use pty.openpty() or equivalent when spawning shell commands. This gives the subprocess its own terminal device, eliminating the race with prompt_toolkit.

Option B: Suspend prompt_toolkit input during interactive commands

When a subprocess is detected reading from /dev/tty, temporarily suspend Kimi CLI's own input handling and yield terminal control. Resume when the subprocess exits. This is what git does during git commit with an editor.

Option C: Detect interactive commands and warn/block

If PTY allocation is architecturally difficult in the short term, detect when a subprocess opens /dev/tty (via tcgetpgrp or lsof monitoring) and immediately fail with a clear error:
"This command requires interactive input, which the Shell tool does not support. Please run it in a native terminal."

This prevents the current broken state where the command hangs for 60–120s and corrupts terminal input.

Related issues

  • #1117 — Shell tool interactive input support (feature request covering the same surface area)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in tools/shell/init.py at the shell process creation and the immediate process.stdin.close() call. Reproduce the ssh-add scenario described in the issue, then trace how shell commands interact with prompt_toolkit and terminal input. Done means interactive commands no longer corrupt or hang terminal input, with behavior verified for the reported ssh-add workflow.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.