fix: native Windows auto-update, PATH cap, and Ctrl+C terminal restore - #3804
Closed
KooshaPari wants to merge 1 commit into
Closed
fix: native Windows auto-update, PATH cap, and Ctrl+C terminal restore#3804KooshaPari wants to merge 1 commit into
KooshaPari wants to merge 1 commit into
Conversation
|
|
KooshaPari
force-pushed
the
fix/windows-updater-zsh-ctrl-c
branch
from
August 2, 2026 20:24
f37fc75 to
b9c0f3b
Compare
Author
|
Closing: not pursuing upstream merge (no CLA). Fixes moved to KooshaPari/forgecode where they are CI-verified and merged on the fork main. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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 nosh, andcmd.exesilently stops resolving any command oncePATHexceeds its ~2047-char batch limit — a very common state because the userPATHfrequently mirrors the entire systemPATH(a 9,772-char effective PATH reproduced the exact'curl' is not recognizederror). PowerShell resolves the same PATH fine, which is why it "worked elsewhere."Ctrl+C in zsh corrupts the session.
:promptruns 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_resetruns, 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 (absolutepowershell.exepath, immune to a polluted PATH) that downloadsforge-{arch}-pc-windows-msvc.exefrom the GitHub release and stages an atomic swap via a detached.cmdhelper (waits forforge.exeto exit, swapsforge.exe.newover it, cleans up, relaunches). Non-Windows keeps the officialcurl … | shone-liner.crates/forge_infra/src/executor.rs— Windows child processes get a sanitized PATH: critical dirs (System32,Wbem, PowerShellv1.0) first, deduplicated entries, capped at 1900 chars so spawnedcmd.execan always resolve tools.crates/forge_select/src/preview.rs(+signal-hookdep) — 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 existingtokio::signal::ctrl_c()handling in the main UI.shell-plugin/lib/helpers.zsh—_forge_exec_interactivenow enables job control locally (setopt LOCAL_OPTIONS MONITOR), launches forge in its own process group, andfgs 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.zsh—forge-accept-lineinstalls 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
forge.exein place (the running process locks it), so the new binary is downloaded toforge.exe.newand swapped by a detached helper that outlives forge. The helper uses full paths totasklist/find/timeoutso it works even when the inherited PATH is broken.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
forgeusers on native Windows with a long/duplicatedPATHcan actually update (previously: silent failure or'curl' is not recognized).:promptin zsh can press Ctrl+C without losing their terminal state or corrupting subsequent input.Testing
Links
curlnot recognized); Ctrl+C in zsh leaves broken/corrupted input