1jehuang / 1jehuang/jcode

[Windows] Session picker "current-terminal" resume leaves the terminal unresponsive (keys and Ctrl+C ignored)

Open
#980 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug priority: high regression triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Environment

  • OS: Windows 10/11 (ConPTY console)
  • Terminal: Windows Terminal (also reproducible in other ConPTY hosts)
  • jcode: v0.77.0
  • Config: keybindings.session_picker_enter = "current-terminal"

Steps to reproduce

  1. Run jcode --resume (no argument) to open the session picker.
  2. Select any session in the left pane and press Enter.
  3. TUI appears but is unresponsive. Typing produces no visible effect and Ctrl+C does not interrupt anything. The window must be force-closed or the stuck jcode --resume <id> process killed manually.

jcode --resume "<session-name>" works correctly.

Root cause

crates/jcode-base/src/platform.rs::replace_process implements "exec" on Windows as:

  1. Command::spawn() of the replacement jcode --resume <id>, then
  2. immediate std::process::exit(0) in the picker process.

Windows has no exec, and the spawn+exit sequence breaks the process substitution semantics that the flow relies on:

  • The shell (cmd.exe) waits only for the picker process. When the picker exits, cmd.exe regains the prompt and begins reading console input again.
  • The replacement child keeps running attached to the same console, and both cmd.exe and the child now block on the shared console input buffer.
    Keystrokes are consumed by an arbitrary one of the two readers.
  • The child's TUI enables raw mode (no ENABLE_PROCESSED_INPUT, no echo) for the console; these modes are console-global, so there is no echo and Ctrl+C no longer generates a break signal.
  • Result: the terminal appears frozen and ignores all input, including Ctrl+C.

Evidence from a live repro: the replacement child processes boot fully (TUI_TERMINAL_MODES initialized, first frame rendered, session history restored, MCP servers connected) and then log zero activity for the rest of their lifetime, i.e. input never reaches them.

Suggested fix

Preserve the wait chain on Windows so the invoking shell does not regain the console while the replacement client runs:

  • Simplest: in the picker's current-terminal path, after spawning the child, the parent should child.wait() for the child to exit instead of exiting immediately (possibly also re-attaching console control handlers). This keeps cmd.exe blocked and the console input single-reader.
  • Alternatively, use the existing terminal-mode handoff machinery (TUI_TERMINAL_MODES handoff flags) together with the wait, so the child can skip re-entering raw/alt-screen state it already owns.
  • Or route "current-terminal" to the "new-terminal" behavior on Windows.

Workaround for users

  • Use jcode --resume "<session-name>" directly, or
  • Set keybindings.session_picker_enter = "new-terminal" in config.toml.

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 crates/jcode-base/src/platform.rs at replace_process and trace the current-terminal session-picker path on Windows. Reproduce with jcode --resume and the current-terminal binding, then verify the replacement client keeps the shell blocked and accepts keyboard input and Ctrl+C without leaving the terminal unresponsive.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.