Repository navigation
feat(open-with): configurable editors/IDEs instead of a hard-wired "Open in VS Code" - #186
Merged
Merged
Conversation
…pen in VS Code" (#178) Replace the single VS Code action with a user-owned "Open with" list: label, program, and an argument template per session kind (local {folder}; WSL {distro} {linuxPath} {folder}; SSH {user} {host} {userAtHost} {port} {remoteFolder}), one default. - Toolbar { } becomes the run-button pattern: { } opens the default for the session's kind, the chevron lists every applicable entry plus Edit...; sidebar right-click gains "Open with >". Works for WSL and SSH sessions (VS Code family via --remote wsl+ / ssh-remote+). - Seeded once by OpenWithDetector (off the UI thread): VS Code stable and Insiders, Cursor, Windsurf, VSCodium (PATH shim -> exe, App Paths, standard install dirs, Scoop), Visual Studio via vswhere, JetBrains IDEs (standalone + Toolbox), Zed, Sublime Text, Notepad++. PATH code.cmd is still found first, so the zero-config default is unchanged. - OpenWithService (WPF-free): templates are tokenised before substitution, so each placeholder is one argv element; launch is UseShellExecute=false + ArgumentList. Programs must be absolute local .exe paths and never a shell; .cmd/.bat shims are resolved to the real exe, and a batch target refuses any argument with cmd metacharacters (BatBadBut). Option-shaped and control-character values are refused; a local folder must exist. - state.json and imports are sanitised; imports reject batch files outright. The editor (Settings -> Open with, or Edit...) previews the full resolved command for each kind. - 110 new unit tests (hostile folder names round-tripped through CommandLineToArgvW, BatBadBut refusal, import trust, detector layouts). Closes #178 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
…m checks (#178 review) - Import never silently replaces the Open-with list: every imported entry's program and templates are listed and confirmed, default No. - Programs: refuse anything under %SystemRoot%; on-disk check resolves the real path (8.3, links, subst), refuses network drives, and checks PE OriginalFilename so renamed shells are caught. Run at import, launch and (debounced, off-thread) in the editor. - Templates must contain a placeholder; menu headers show the program file and tooltips the fully resolved command. - No placeholder may start an argument with '-' or '/' (verified: Code.exe 1.143.1 honours /js-flags=... as a Chromium switch). Seeded VS Code remote forms are now --folder-uri vscode-remote://... with {name:uri} percent-encoding. - PrepareAsync validates before probing WSL $HOME; ResolveShim needs a single unambiguous candidate; detection finding nothing stays unseeded; toolbar state follows session edits and is released on teardown. - Dialog disk I/O moved off the UI thread. - Tests: real ArgumentList encoding round-tripped via a spawned child, 8.3 / renamed-copy / SystemRoot / network-drive refusals, probe ordering, URI encoding (921 total). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
mortenaslo
added a commit
that referenced
this pull request
Nov 6, 2026
Conflict in MainWindow.OnLoaded: kept EnsureOpenWithSeeded(); the old RestoreWindowState call stays removed (bounds are applied before show). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
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.
Closes #178
Summary
Replaces the single hard-wired Open in VS Code with a configurable Open with… list. Each entry has a label, a program, and an argument template for each session kind (local, WSL, SSH); one entry is the default.
{ }▼, the same pattern as the ▶/▼ run button:{ }opens the default editor for this session's kind.--folder-uri vscode-remote://wsl+…orssh-remote+…, passed as one argument with percent-encoded{name:uri}placeholders. Before, a WSL folder was opened over the\wsl$share.Auto-detect
Detection seeds the list once; after that it is the user's.
.exe, App Paths, standard install folders, and Scoop.vswhere.*64.exeonly.Detection runs on the thread pool.
code.cmdon PATH is still found first, so with no configuration it behaves as before. If nothing is found, detection runs again on the next launch.Security
UseShellExecute = falseandArgumentList.ArgumentListand splits its raw command line withCommandLineToArgvW.-or/. Checked on this machine: Code.exe 1.143.1 does treat/js-flags=…as a Chromium switch..cmdshims are resolved to the real.exe, but only when the script names exactly one program. If a batch file is used anyway, any argument containing a cmd metacharacter is refused, never escaped..exe.%SystemRoot%, and no known shells or script hosts.Review
A read-only review of the first commit found eight issues, all fixed in the second commit. The most serious was an imported backup being able to put an arbitrary command behind a harmless label. The others were an 8.3-name bypass of the shell list,
/-prefixed values reaching Code.exe as switches, and file checks running on the UI thread.Tests
OpenWithServiceTests,OpenWithHardeningTests,OpenWithDetectorTests).Manual testing still needed (desktop was locked)
{ }▼ layout and tooltips, the sidebar submenu, and Settings → Open withcode.cmd, previews and warnings, Detectssh-remote+user%40host; VS Code decoding%40is the main assumption)🤖 Generated with Claude Code
https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX