Skip to content

fix: native Windows auto-update, PATH cap, and Ctrl+C terminal restore - #3804

Closed
KooshaPari wants to merge 1 commit into
tailcallhq:mainfrom
KooshaPari:fix/windows-updater-zsh-ctrl-c
Closed

fix: native Windows auto-update, PATH cap, and Ctrl+C terminal restore#3804
KooshaPari wants to merge 1 commit into
tailcallhq:mainfrom
KooshaPari:fix/windows-updater-zsh-ctrl-c

Conversation

@KooshaPari

Copy link
Copy Markdown

Summary

Fix the Windows auto-updater (which breaks on native Windows with 'curl' is not recognized), and stop Ctrl+C from corrupting interactive forge sessions launched from the zsh plugin.

Context

Two independent problems were found and traced to root cause:

  1. Windows auto-update fails on native Windows. The updater ran cmd.exe /C curl -fsSL https://forgecode.dev/cli | sh. On native Windows there is no sh, and cmd.exe silently stops resolving any command once PATH exceeds its ~2047-char batch limit — a very common state because the user PATH frequently mirrors the entire system PATH (a 9,772-char effective PATH reproduced the exact 'curl' is not recognized error). PowerShell resolves the same PATH fine, which is why it "worked elsewhere."

  2. Ctrl+C in zsh corrupts the session. :prompt runs forge's interactive TUI as a child of a ZLE widget in zsh's own foreground process group (job control is off during widgets). Ctrl+C therefore SIGINTs both zsh and forge. zsh's widget aborts before _forge_reset runs, and forge has no signal handler anywhere, so its raw-mode terminal restoration (TerminalGuard::drop) never executes on SIGINT — leaving raw mode enabled, which produces broken half-echoed input, mis-timed key bursts, and ghost prompts that come and go.

Changes

  • crates/forge_main/src/update.rs — platform-branched updater. Windows now uses a native PowerShell command (absolute powershell.exe path, immune to a polluted PATH) that downloads forge-{arch}-pc-windows-msvc.exe from the GitHub release and stages an atomic swap via a detached .cmd helper (waits for forge.exe to exit, swaps forge.exe.new over it, cleans up, relaunches). Non-Windows keeps the official curl … | sh one-liner.
  • crates/forge_infra/src/executor.rs — Windows child processes get a sanitized PATH: critical dirs (System32, Wbem, PowerShell v1.0) first, deduplicated entries, capped at 1900 chars so spawned cmd.exe can always resolve tools.
  • crates/forge_select/src/preview.rs (+ signal-hook dep) — a process-wide SIGINT safety-net flag is registered once; the picker loop checks it and restores the viewport/terminal before returning cleanly instead of dying in raw mode. Coexists with the existing tokio::signal::ctrl_c() handling in the main UI.
  • shell-plugin/lib/helpers.zsh_forge_exec_interactive now enables job control locally (setopt LOCAL_OPTIONS MONITOR), launches forge in its own process group, and fgs it, so Ctrl+C targets forge only — the same isolation vim/fzf get. Falls back to plain foreground execution when job control is unavailable.
  • shell-plugin/lib/dispatcher.zshforge-accept-line installs a function-scoped INT trap (setopt LOCAL_OPTIONS LOCAL_TRAPS) that restores ZLE state as belt-and-suspenders; it is automatically cleared on every exit path, including the editor/commit-preview/suggest early returns.

Key Implementation Details

  • The Windows updater cannot replace forge.exe in place (the running process locks it), so the new binary is downloaded to forge.exe.new and swapped by a detached helper that outlives forge. The helper uses full paths to tasklist/find/timeout so it works even when the inherited PATH is broken.
  • The SIGINT flag is a OnceLock<Arc<AtomicBool>> registered once per process; the picker's 250 ms poll notices the flag and restores the terminal. Ctrl+C inside the picker is still handled as a raw-mode key event; the flag only covers real signals arriving outside the key reader (e.g. when forge runs in its own process group).

Use Cases

  • forge users on native Windows with a long/duplicated PATH can actually update (previously: silent failure or 'curl' is not recognized).
  • macOS/Unix users who run :prompt in zsh can press Ctrl+C without losing their terminal state or corrupting subsequent input.

Testing

# Rust side
cargo check -p forge_select -p forge_infra -p forge_main
cargo test -p forge_main --lib update::

# zsh plugin (from shell-plugin/)
zsh -n lib/helpers.zsh
zsh -n lib/dispatcher.zsh

# Manual: Windows updater path
#   set PATH to >2047 chars (or a PATH that duplicates system entries), run
#   `forge update` and confirm PowerShell download + swap helper run.
# Manual: zsh Ctrl+C
#   in an interactive zsh with the plugin loaded, run `:prompt`, press Ctrl+C,
#   and confirm the prompt/input remain intact with no stray characters.

Links

  • Original report: native Windows auto-update fails (curl not recognized); Ctrl+C in zsh leaves broken/corrupted input

Copilot AI review requested due to automatic review settings August 2, 2026 05:22
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added os: windows Windows-specific issue or feature. type: fix Iterations on existing features or infrastructure. labels Aug 2, 2026
@KooshaPari
KooshaPari force-pushed the fix/windows-updater-zsh-ctrl-c branch from f37fc75 to b9c0f3b Compare August 2, 2026 20:24
@KooshaPari

Copy link
Copy Markdown
Author

Closing: not pursuing upstream merge (no CLA). Fixes moved to KooshaPari/forgecode where they are CI-verified and merged on the fork main.

@KooshaPari KooshaPari closed this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

os: windows Windows-specific issue or feature. type: fix Iterations on existing features or infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants