fix(server): open stable Zed when a prerelease Zed is first on PATH#9501

closed1
main
GitHub fork: fix/windows-zed-stable
openedSep 3, 2026byEEzraBuild
View on GitHubTwo-way sync enabledPR last imported 21d ago

What Changed

Zed's stable, preview, and nightly channels each install their own zed CLI. Editor resolution took the first zed found on PATH, so on a machine where a prerelease channel sits earlier on PATH, choosing "Zed" opened Zed Nightly or Zed Preview.

  • packages/shared/src/shell.ts gains resolveCommandPaths, which lists every PATH match for a command in order. It reuses the existing PATHEXT handling, quote stripping, and the PATH directory listing cache from #13669, never fails, and is not cached.
  • packages/shared/src/editor.ts (where editor command resolution now lives after #12439) uses it only for Zed: it prefers the first install whose own folder name does not mark a prerelease channel (Zed Preview, Zed Nightly.app, zed-nightly.app) and, when that install is not the first on PATH, resolves it by absolute path. A single install, an already correct PATH order, or a "preview" or "nightly" folder elsewhere in the path keeps the bare command, so nothing changes for those users. The install-folder fallback for machines without zed on PATH is untouched.
  • No environment or PATH rewriting, which is what the earlier attempt in #2066 was flagged for.
  • Tests: a launcher test puts a nightly zed.EXE ahead of a stable one on PATH and asserts stable launches by absolute path, then removes stable and asserts the bare command is kept. editor.test.ts covers the prerelease classifier. A shared test covers resolveCommandPaths ordering, explicit paths, and an empty PATH.

Why

Fixes #1978. The bug reproduces on Windows with Zed 1.18.0 stable and Zed Preview 1.19.0 installed side by side, both at %LOCALAPPDATA%\Programs\<channel>\bin\zed.exe, with the Preview bin first on PATH. Verified by launching through the real ExternalLauncher and checking which Zed process received the workspace:

PATH orderBeforeAfter
Preview bin before stable binZed Preview opened the projectZed stable opened the project

UI Changes

None.

Validation

  • vp test run apps/server/src/process/externalLauncher.test.ts packages/shared/src/editor.test.ts packages/shared/src/shell.test.ts
  • vp lint and vp fmt --check on the five changed files
  • vp run --filter @t3tools/shared --filter t3 typecheck

Model: Claude Fable 5.1. Harness: Claude Code.

Checks

15 successful · 7 skipped
All checks passed
5a539f4
MmacroscopeappBoton outdated lineSep 3, 2026

🟡 Medium process/externalLauncher.ts:188

resolveZedCommand still launches the nightly executable when stable Zed is installed under a path such as C:\Users\preview-user\..., so selecting Zed opens the wrong channel. isPrereleaseZedPath matches substrings anywhere in the full path; restrict the check to complete path components such as nightly or preview.

✅ Resolved in a36c424ada4c95d9a3ee40ec2673f87982af1db8

Synced from GitHub

Approvability

Verdict: Approved at 0c4d469

Macroscope's review found this PR approvable — This is a narrowly scoped fix to select stable Zed when a prerelease CLI appears first on PATH, while leaving other editors and existing configuration unchanged. The shared PATH helper is small, used only by the Zed launch path, and covered by targeted tests.

You can add or adjust custom eligibility rules. Learn more.

Added 1 commit

  • fix(server): open stable Zed when a prerelease Zed is first on PATH5a539f4
Synced from GitHub

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 18b1799e-87ba-4e94-808c-2c62529b6072

📥 Commits

Reviewing files that changed from the base of the PR and between c18e5ea6ed741443a8ec4a5d22d4b6939b0ecd21 and 5a539f4e359d83709128c55223179aaa9e687695.

📒 Files selected for processing (5)
  • apps/server/src/process/externalLauncher.test.ts
  • packages/shared/src/editor.test.ts
  • packages/shared/src/editor.ts
  • packages/shared/src/shell.test.ts
  • packages/shared/src/shell.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Zed command resolution now checks all matching executable paths and prefers a stable installation over prerelease installations. Tests cover path detection, command lookup, and Windows launch selection.

Changes

Zed Command Resolution

Layer / File(s)Summary
Resolve all command paths
packages/shared/src/shell.ts, packages/shared/src/shell.test.ts
Added resolveCommandPaths to return executable matches in PATH order or a single match for an explicit path. Tests cover ordered matches, explicit paths, and empty results.
Select a stable Zed installation
packages/shared/src/editor.ts, packages/shared/src/editor.test.ts, apps/server/src/process/externalLauncher.test.ts
Added prerelease path detection and Zed-specific selection that prefers a non-prerelease install. Tests cover install path recognition and Windows launch behavior, including fallback to zed when the stable executable is removed.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 5a539

The change prefers stable Zed installations without changing other editors or launch arguments. No concrete merge-blocking risk is established; merge after normal checks pass.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 5a539

Stable-channel preference can select a program from a later PATH directory. This matters if that directory is less trusted than the first. Existing launch checks remain, and no remotely exploitable path or privilege escalation was established.

Retained concerns

  • Low · security · inferred: If an attacker can write a later PATH directory while the first Zed match is classified as prerelease, a stable-looking executable in that directory can now be selected instead of the earlier executable. This is a conditional local authority expansion, not a demonstrated deployment vulnerability; exploitability depends on PATH directory ownership and trust.
Security review details

Security Blast Radius

  • inferred — The supported exposure is local executable selection in the server launcher context. A malicious selected executable could execute with that process-launch authority. Remote reachability, elevated privileges, and cross-tenant or cross-service propagation were not established.

Security Findings and Attack Paths

  • inferred — The conditional attack requires control of a later PATH directory, an earlier match classified as prerelease, and a subsequent Zed launch. A stable-looking malicious match can then displace the earlier executable. If all candidate directories have equivalent trust, this selection change does not demonstrate a security-boundary bypass.

Trust Boundaries and Controls

  • observed — The launcher retains editor-definition validation, a pre-spawn availability check, and existing platform-specific shell controls. These controls reject missing commands and constrain argument handling, but do not authenticate a later PATH candidate.

Resilience and Maintainability Implications

  • observed — The regression test removes the stable executable and verifies that a repeated launch returns to the bare-command fallback. Production launch also rechecks availability, so discovery does not alone authorize spawning a deleted executable. This does not establish immutable executable identity between checking and spawning.

Hardening Proposals

  • proposed — If deployments permit lower-trust writable PATH directories, constrain stable candidates to trusted installation roots or provide an explicitly configured executable path. Treat channel-name classification as preference logic, not a trust decision.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Out of Scope Changes check⚠️ WarningThe issue targets Windows only. resolveEditorCommand applies the new prerelease-aware Zed resolution for every platform, not only win32. The added classification tests also cover macOS and Linux-s…Limit the new prerelease-aware Zed command selection to the Windows path, or provide a directly linked issue that requires the same behavior on macOS and Linux. Preserve the existing Zed resolution behavior on other platforms.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedIssue #1978 requires the Windows Zed action to select the stable install when stable and Nightly commands are both on PATH. resolveCommandPaths collects matches in PATH order. `resolveZedPathCommand…
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 5 files.
Title check✅ PassedThe title clearly and concisely describes the primary change: selecting stable Zed when a prerelease installation appears first on PATH.
Description check✅ PassedThe description clearly explains what changed, why it changed, UI impact, scope, tests, and validation. The template checklist is omitted, but the listed content covers the relevant checklist items an…
Full details: Out of Scope Changes check

Explanation

The issue targets Windows only. resolveEditorCommand applies the new prerelease-aware Zed resolution for every platform, not only win32. The added classification tests also cover macOS and Linux-style paths. No linked issue establishes a requirement to change Zed resolution on those platforms. The generic resolver and Zed-only use support the Windows fix, but the cross-platform runtime behavior exceeds the linked scope.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

Note

This comment is posted by Julius' dot

Closing for missing product-direction approval. Julius’s triage on #1978 leaves the generic Zed channel-selection decision open. The native Windows evidence addresses reproduction, but preferring stable over PATH still needs that decision. Please obtain and link explicit approval of the selection rule for reconsideration.