Repository navigation
feat(terminal): bundle Microsoft's ConPTY (conpty.dll + OpenConsole.exe) - #188
Merged
Merged
Conversation
Sessions now run on the bundled ConPTY from Microsoft.Windows.Console.ConPTY 1.25.260930003 instead of the inbox conhost. Measured on conhost 10.0.26100: the inbox ConPTY drops OSC sequences written to its input and answers DA1 itself, so terminal replies (OSC 7501, OSC 11, …) never reach programs in time. Claude Code logs programStatus=no on inbox, =yes on the bundled one. - csproj: PackageReference (ExcludeAssets=all) + explicit loose copies of conpty.dll and OpenConsole.exe beside the exe, ExcludeFromSingleFile. - ConPtyApi: binds Create/Resize/ClosePseudoConsole by FULL PATH (bundled conpty.dll from AppContext.BaseDirectory, inbox from System32 kernel32); never a bare DLL name. Each PTY keeps the API that created its HPCON. - Fallback to inbox, logged once: setting UseBundledConPty off, a file missing, load/export failure, or a failing bundled CreatePseudoConsole. - Run commands stay on the inbox ConPTY: headless, and OpenConsole consumes the first DA1 answer for its own startup query (measured). - ANSI strip regexes (OutputIndexer, RunInstance, AlertDetector) now also strip CSI finals c and t (OpenConsole opens with ESC[1t ESC[c). - MSI installs both files; CI fails if the .wxs lacks them, if publish/ lacks them, or if they are not validly Microsoft-signed. Exe signing now targets CodeShellManager.exe by name (no longer re-signs OpenConsole.exe). - CLAUDE.md "Bundled ConPTY" section; README mention; ConPtyApiTests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
…h files, softer demotion - A1: PseudoTerminal.DataReceived is now backed by EarlyOutputBuffer. Sessions start the PTY before the bridge subscribes, so the reader's first chunks had no subscriber and were dropped — on the bundled ConPTY that is ESC[1t ESC[c ESC[?1004h ESC[?9001h, and losing ESC[c makes OpenConsole eat the program's DA1 answer later. Output before the first subscriber is held (capped) and flushed to it under the same lock the reader uses, so nothing is lost or reordered. Verified with a subscriber attached 800ms after Start. - A2: the csproj picks conpty.dll/OpenConsole.exe for the target architecture (RuntimeIdentifier, then PlatformTarget, then the build machine's OS architecture; default x64). The bind test skips the load assertion when the DLL and the test process architectures differ. - A3: a failing bundled CreatePseudoConsole still falls back for that terminal and is logged each time, but only 3 consecutive failures (reset on success) switch the rest of the run to inbox (BundledFailurePolicy). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
Merged
5 tasks
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.
Sessions now run on Microsoft's current ConPTY (
Microsoft.Windows.Console.ConPTY1.25.260930003, stable, Microsoft-signed, MIT) instead of the one built into Windows. Windows Terminal and VS Code do the same.Why
Measured against conhost 10.0.26100:
The bundled ConPTY does neither: raw OSC input arrives intact, and DA1 is forwarded to xterm.js. Claude Code 2.1.319 logs
programStatus=no (probe: no reply to OSC 7501 ; ?)on the built-in ConPTY andprogramStatus=yes (probe: OSC 7501 reply)on the bundled one. This unblocks OSC 7501 status reporting in #187, for any program that checks for support before reporting, not only Claude.What changes
Packaging: both files ship as loose files beside the exe in the build output, the single-file publish, the MSI and the ZIP. They come from a PackageReference, not binaries committed to git, and the architecture is picked per build (x64 by default).
Loading:
conpty.dllis loaded by full path only (AppContext.BaseDirectory, function pointers), never by bare name, which avoids DLL search-order hijacking. kernel32 is loaded from System32 by full path.Fallback to the built-in ConPTY, logged to crash.log, when any of these hold:
UseBundledConPtyis falseResize and close always go to the ConPTY that created the console.
Early output is kept: output that arrives before the first subscriber is buffered and delivered in order. Sessions attach after
Start, and the bundled ConPTY's first bytes include a DA1 query that xterm.js must answer.Run commands stay on the built-in ConPTY. They are headless, and the bundled one leaves a program's own DA1 query unanswered there (measured). Their startup is unchanged: 45 ms vs 44 ms median.
Escape stripping: the three escape-stripping regexes now also strip
ESC[1t/ESC[c, so they stay out of search.CI and signing:
CodeShellManager.exeonly. The old folder filter would have re-signed Microsoft'sOpenConsole.exewith our certificate.Review
A read-only review found one real race: the first PTY output, including the startup DA1 query, could be dropped before the bridge subscribed. It also flagged x64-only package paths and a single failure permanently switching the process to the built-in ConPTY. All three are fixed in the second commit. Loader security, the function-pointer signatures, the WiX layout, the signing input and the regex scope were checked and found sound.
Verified
Not verified
files:signing input and the new guards. The first tagged build will exercise them.🤖 Generated with Claude Code
https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX