Skip to content

perf(windows): reduce first-start editor discovery time - #6124

Open
simon-curtis wants to merge 2 commits into
pingdotgg:mainfrom
simon-curtis:perf/windows-startup
Open

perf(windows): reduce first-start editor discovery time#6124
simon-curtis wants to merge 2 commits into
pingdotgg:mainfrom
simon-curtis:perf/windows-startup

Conversation

@simon-curtis

@simon-curtis simon-curtis commented Aug 11, 2026

Copy link
Copy Markdown

What Changed

On Windows, command discovery now lists each PATH directory once, matches PATHEXT candidates case-insensitively, and performs the existing executable-file check only for matching entries.

PATH order and resolveCommandCandidates remain unchanged. If a directory cannot be listed, lookup falls back to upstream's direct candidate probes.

Why

The first client configuration probes up to 22 editor commands. Upstream performs a filesystem probe for every PATH × PATHEXT candidate, so editor discovery can consume seconds on a long Windows PATH and approaches its five-second timeout.

This narrows the PR to reducing first-start/editor-discovery time without changing desktop PATH hydration or packaging behavior.

Measured Impact

Targeted Windows command-discovery benchmark on 71 PATH entries and 12 PATHEXT extensions; medians from five alternating runs:

Workload Upstream This PR Saved
5 provider commands 199 ms 49 ms 150 ms
22 editor commands 1,964 ms 425 ms 1,539 ms

This is a resolver benchmark rather than an end-to-end launch measurement. The exact gain depends on PATH and PATHEXT size.

Scope

No PowerShell environment probing, provider lifecycle, installer, packaging, or WSL behavior changes are included.

Verification

  • vp fmt --check packages/shared/src/shell.ts packages/shared/src/shell.test.ts
  • vp lint packages/shared/src/shell.ts packages/shared/src/shell.test.ts --report-unused-disable-directives
  • vp run --filter @t3tools/shared typecheck
  • vp test run packages/shared/src/shell.test.ts — 30 tests passed

model: gpt-5.6-sol
harness: Codex in T3 Code

Note

Reduce first-start editor discovery time on Windows with case-insensitive PATH resolution

  • On Windows, resolveCommandPathForPlatform in shell.ts now lists each PATH directory and builds a case-insensitive filename map to match command candidates, avoiding failed probes caused by case mismatches.
  • Falls back to the existing direct-probe behavior when a PATH directory cannot be listed.
  • Adds a test in shell.test.ts that creates a mixed-case executable in a temp directory and verifies case-insensitive resolution on win32 with PATHEXT set.

Macroscope summarized e1ea751.


Note

Medium Risk
Touches shared spawn/command resolution used broadly on Windows; listing failures are handled with fallback, but resolution semantics could differ in edge cases (permissions, odd PATH layouts).

Overview
Windows resolveCommandPath no longer stat-probes every PATH × PATHEXT candidate. For each PATH directory it reads the directory once, maps filenames case-insensitively to PATHEXT candidates, and only runs the executable check on matches—fixing missed tools when on-disk casing differs from the probe (e.g. provider-tool.eXe).

If a directory cannot be listed, behavior falls back to the previous direct candidate probes. PATH order and candidate generation are unchanged.

A vitest covers mixed-case resolution on win32.

Reviewed by Cursor Bugbot for commit e1ea751. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 29b8ba25-3a43-402f-863d-92b83471eb11

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 11, 2026
Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts Outdated
const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
const snapshot = yield* makeManagedServerProvider<ProviderSnapshotSettings<ClaudeSettings>>({
maintenanceCapabilities,
maintenanceCapabilities: maintenanceCapabilities.get,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟠 High Drivers/ClaudeDriver.ts:180

maintenanceCapabilities.get() returns the npm updater immediately after ClaudeDriver.create(), even when claude on PATH actually resolves to a native or Homebrew install. Before the deferred maintenanceCapabilities.refresh completes, ProviderRegistry.getProviderMaintenanceCapabilitiesForInstance can therefore return the wrong update action, so an update requested during startup runs npm instead of claude update/Homebrew. makeProviderMaintenanceCapabilitiesSource initializes its current value via resolver.resolve(options) before command-path/realpath discovery, and that synchronous resolve falls back to the npm updater for a bare claude command. Consider initializing current with a non-actionable value (or gating maintenance access) until the deferred resolution completes.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Drivers/ClaudeDriver.ts around line 180:

`maintenanceCapabilities.get()` returns the npm updater immediately after `ClaudeDriver.create()`, even when `claude` on PATH actually resolves to a native or Homebrew install. Before the deferred `maintenanceCapabilities.refresh` completes, `ProviderRegistry.getProviderMaintenanceCapabilitiesForInstance` can therefore return the wrong update action, so an update requested during startup runs `npm` instead of `claude update`/Homebrew. `makeProviderMaintenanceCapabilitiesSource` initializes its `current` value via `resolver.resolve(options)` before command-path/realpath discovery, and that synchronous resolve falls back to the npm updater for a bare `claude` command. Consider initializing `current` with a non-actionable value (or gating maintenance access) until the deferred resolution completes.

Comment thread scripts/build-desktop-artifact.ts
Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts Outdated
Comment thread packages/shared/src/shell.ts Outdated
@simon-curtis simon-curtis changed the title perf(windows): reduce startup work and clarify long phases perf(windows): reduce startup work and clarify installer phases Aug 11, 2026
Comment thread apps/server/src/provider/providerMaintenance.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found.

You can customize Macroscope's approvability policy. Learn more.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fef06d7. Configure here.

Comment thread apps/server/src/provider/providerMaintenance.ts Outdated
@simon-curtis
simon-curtis marked this pull request as draft August 13, 2026 11:14

@CDVolvik CDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Read the Windows shell half against today's main. CONFLICTING.

Desktop: drops the -NoProfile PATH probe entirely and keeps only the profile probe, merging process PATH + profile PATH + knownWindowsCliDirs. That is the ~2s startup win (each PowerShell spawn was ~2s). It also deletes the no-profile source #6356 is trying to make read Machine+User, so a CLI installed after launch still will not show up until the next process start unless the profile sees it.

Shared: directory listing + case-insensitive name map instead of probing every PATHEXT candidate, with a fallback when readDirectory fails (ACL / unreadable share). That is the right Windows lookup. Returning [command] when the input already has a PATHEXT suffix is also right — the old code generated three casings of the same extension.

Do not land this and #6356/#4896/#6301 independently; they all rewrite installWindowsEnvironment.

@simon-curtis simon-curtis changed the title perf(windows): reduce startup work and clarify installer phases perf(windows): speed up shell command discovery Aug 17, 2026
@simon-curtis simon-curtis changed the title perf(windows): speed up shell command discovery perf(windows): reduce first-start editor discovery time Aug 17, 2026
@simon-curtis

Copy link
Copy Markdown
Author

Scope update: I have reframed this PR around reducing first-start/editor-discovery time on Windows.

After comparing the original branch with current main and the overlapping Windows environment work, the earlier ~2-second startup result was attributable to removing a PowerShell PATH probe. That change affects PATH refresh semantics and conflicts with the other installWindowsEnvironment work, so it no longer belongs in this PR. The installer, packaging, provider-lifecycle, desktop environment, and WSL changes have also been removed.

What remains is the independently useful shared lookup optimization: list each Windows PATH directory once, match PATHEXT candidates case-insensitively, preserve PATH order, and fall back to the existing direct probes when listing fails. I also restored resolveCommandCandidates exactly to main, so this PR no longer changes candidate casing behavior.

A targeted five-run benchmark on this machine's 71-entry PATH and 12 PATHEXT values measured provider discovery at 199 ms → 49 ms and first editor discovery at 1,964 ms → 425 ms. This is a resolver benchmark, not an end-to-end startup claim.

@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 17, 2026
Comment thread packages/shared/src/shell.ts
Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
@simon-curtis
simon-curtis marked this pull request as ready for review August 17, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants