Skip to content

fix: cancel current command/stream on Ctrl+C instead of exiting - #89

Draft
aryansk wants to merge 1 commit into
shauryagangrade:mainfrom
aryansk:codex/issue-51-ctrl-c
Draft

fix: cancel current command/stream on Ctrl+C instead of exiting#89
aryansk wants to merge 1 commit into
shauryagangrade:mainfrom
aryansk:codex/issue-51-ctrl-c

Conversation

@aryansk

@aryansk aryansk commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Problem

Pressing Ctrl+C while the assistant is streaming a reply, or while a bash
command is running, terminates the entire GCode session and prints the
goodbye screen. Any messages since the last save are lost — the turn in
progress is never persisted. Closes #51.

Change

Three interrupt-handling fixes:

  • execute_bash (gcode/tools.py): catches KeyboardInterrupt from
    subprocess.run and returns Command execution cancelled by user.
    instead of letting it kill the REPL. Applies both to the prompt phase
    (already handled) and the running-command phase (new).
  • Streaming (gcode/agent.py _stream): a Ctrl+C during streaming
    stops the stream, keeps whatever was accumulated so far as the turn's
    assistant message (with no half-formed tool calls), and persists it —
    the session stays alive and history is saved.
  • Tool calls (gcode/agent.py _run_tool): a Ctrl+C during any tool
    call returns Command execution cancelled by user. to the model instead
    of propagating.

A Ctrl+C (or Ctrl+D) at the prompt still exits with the goodbye screen,
unchanged.

Why this approach

Minimal, targeted changes: the interrupt is caught at the two async
boundaries where it can arrive mid-work (streaming and subprocess), and the
tool-call boundary is hardened so a cancelled tool result is recorded in
history like any other tool result. No changes to the prompt loop or exit
paths.

Testing

uv run pytest:  111 passed (4 new: 3 agent streaming/tool-cancel tests,
                1 subprocess-interrupt test)
uv run ruff check .:  All checks passed
uv run ruff format --check .:  31 files already formatted
uv run mypy gcode:  Success: no issues found in 12 source files
uv run bandit -q -r gcode/ -c pyproject.toml:  clean
uv run python -m compileall -q gcode demo:  clean

New tests cover: partial reply retained on mid-stream interrupt, empty
reply when interrupted before any chunk, and a tool that raises
KeyboardInterrupt returning the cancelled result.

Documentation and release impact

  • User-facing documentation updated
  • Changelog/release note needed (user-visible behavior change)
  • Migration or compatibility note needed
  • No documentation impact

Review notes

  • Known limitations: a Ctrl+C during streaming intentionally drops any
    tool calls the model had begun to emit (they are half-formed), but keeps
    the text.
  • Follow-up issue: none.

execute_bash now catches KeyboardInterrupt from subprocess.run and
returns "Command execution cancelled by user."; the streaming loop stops
on interrupt and keeps the partial reply so the session and history
survive; tool calls interrupted mid-run cancel cleanly. A Ctrl+C at the
prompt still exits with the goodbye screen. Closes shauryagangrade#51.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Ctrl+C mid-stream or during a bash command exits the whole session

1 participant