From d4ad4f47bbca159027bd55fb84ea95785bcc7ef8 Mon Sep 17 00:00:00 2001 From: Rob Homewood Date: Wed, 21 Oct 2026 15:34:46 +0100 Subject: [PATCH 1/3] fix(provider-core): Chocolatey Claude installs stay manual-only and compare against choco Claude Code installed with Chocolatey was compared against npm, and Update now ran claude update through the shim. That installs a native copy and leaves the Chocolatey install unchanged. Treat those installs as manual-only, compare them with choco search, and show choco upgrade claude-code without running it. Co-authored-by: Cursor --- docs/internals/providers.md | 5 +- docs/user/install.md | 7 +- .../provider-core/src/server/maintenance.ts | 4 + .../src/server/maintenanceResolver.test.ts | 139 +++++++++++++++++- .../src/server/maintenanceResolver.ts | 81 +++++++++- 5 files changed, 226 insertions(+), 10 deletions(-) diff --git a/docs/internals/providers.md b/docs/internals/providers.md index 4121a349dcbf8..90bd5e31eef7e 100644 --- a/docs/internals/providers.md +++ b/docs/internals/providers.md @@ -93,7 +93,10 @@ manual-only because their version is pinned in mise's config. A Grok cask whose cannot be verified also stays manual-only: `grok update` would install a second copy. npm updates pin `--prefix` because the `npm` on `PATH` can belong to a different Node than the one that owns the provider. Homebrew compares against `brew info` since casks trail npm by hours; native installs share npm's version -train, so the registry stays authoritative for them. +train, so the registry stays authoritative for them. A Chocolatey install of Claude stays +manual-only: its package directory is writable only by administrators, and `claude update` through +the shim installs a native copy elsewhere. The latest version comes from `choco search`, and the +card shows `choco upgrade claude-code` without running it. See the [resolver](../../apps/server/src/provider/providerMaintenance.ts). Ownership is cached per instance and re-read immediately before an update runs. The diff --git a/docs/user/install.md b/docs/user/install.md index 59c8648934ca4..91bbd49256ecc 100644 --- a/docs/user/install.md +++ b/docs/user/install.md @@ -161,9 +161,10 @@ When a provider CLI is behind its latest release, its provider card shows the available version. **Update now** runs the installer that owns the CLI (Homebrew, or a global npm, pnpm, Yarn, Bun, Volta, or Vite+ install), or the CLI's own update command when T3 Code cannot tell. Update a CLI installed with -mise through mise. Cursor and Antigravity update with T3 Code. Homebrew installs -compare against the version Homebrew offers, which can trail the npm release by -a few hours. +mise through mise. Cursor and Antigravity update with T3 Code. Homebrew and +Chocolatey installs compare against the version their package manager offers, +which can trail the npm release; update Claude installed with Chocolatey +through Chocolatey. Add another provider instance for a separate account or configuration. Each instance can have its own environment variables, such as API keys or a custom diff --git a/packages/provider-core/src/server/maintenance.ts b/packages/provider-core/src/server/maintenance.ts index 298fa5a4e4431..7dfe26a1ef8cc 100644 --- a/packages/provider-core/src/server/maintenance.ts +++ b/packages/provider-core/src/server/maintenance.ts @@ -23,6 +23,10 @@ export interface ProviderMaintenanceCapabilities { * install to update. */ readonly installPath?: string; + /** + * A command T3 Code shows but cannot run. + */ + readonly manualCommand?: string; } export interface ProviderMaintenanceCommandAction { diff --git a/packages/provider-core/src/server/maintenanceResolver.test.ts b/packages/provider-core/src/server/maintenanceResolver.test.ts index cbb24818eb550..d446c6d169042 100644 --- a/packages/provider-core/src/server/maintenanceResolver.test.ts +++ b/packages/provider-core/src/server/maintenanceResolver.test.ts @@ -22,10 +22,12 @@ import { homebrewOwnershipFromCommandPath, invalidateLatestProviderVersion, makeCachedProviderMaintenanceResolution, + makeManualOnlyProviderMaintenanceCapabilities, makePackageManagedProviderMaintenanceResolver, makeProviderMaintenanceCapabilities, normalizeCommandPath, npmGlobalPrefixFromCommandPath, + parseChocolateyLatestVersion, parseHomebrewLatestVersion, resolveLatestProviderVersion, resolvePackageManagedProviderMaintenance, @@ -254,6 +256,26 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { }); }); + it("shows the Chocolatey upgrade command without offering to run it", () => { + expect( + createProviderVersionAdvisory({ + driver: driver("claudeAgent"), + currentVersion: "2.1.304", + latestVersion: "2.1.306", + maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ + provider: driver("claudeAgent"), + packageName: "@anthropic-ai/claude-code", + installPath: "C:\\ProgramData\\chocolatey\\bin\\claude.exe", + manualCommand: "choco upgrade claude-code", + }), + }), + ).toMatchObject({ + canUpdate: false, + canInstallVersion: false, + updateCommand: "choco upgrade claude-code", + }); + }); + it.effect("stays manual-only when the binary cannot be located", () => resolveProviderMaintenanceCapabilitiesEffect(packageToolUpdate, { binaryPath: "package-tool", @@ -390,12 +412,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { readonly resolved: string; readonly real: string; readonly platform?: NodeJS.Platform; + readonly env?: NodeJS.ProcessEnv; }) => resolvePackageManagedProviderMaintenance(input.definition, { binaryPath: "claude", resolvedCommandPath: input.resolved, realCommandPath: input.real, - env: {}, + env: input.env ?? {}, platform: input.platform ?? "win32", }).pipe( Effect.provideService(HostProcess.Platform, input.platform ?? "win32"), @@ -428,6 +451,113 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { }), ); + const chocolateyShim = "C:\\ProgramData\\chocolatey\\bin\\claude.exe"; + const chocolateyPackage = "C:\\ProgramData\\chocolatey\\lib\\claude-code\\tools\\claude.exe"; + + it.effect.each([ + { name: "the shimgen shim", resolved: chocolateyShim, real: chocolateyShim }, + { name: "the package binary", resolved: chocolateyPackage, real: chocolateyPackage }, + { + name: "a custom root", + resolved: "D:\\Tools\\Choco\\bin\\claude.exe", + real: "D:\\Tools\\Choco\\bin\\claude.exe", + env: { ChocolateyInstall: "D:\\Tools\\Choco" }, + }, + ] as const)("keeps a Chocolatey Claude install manual-only through $name", (fixture) => + Effect.gen(function* () { + const capabilities = yield* resolveInstall({ definition: claudeUpdate, ...fixture }); + + expect(capabilities.update).toBeNull(); + expect(capabilities.installPath).toBe(fixture.real); + expect(capabilities.latestVersion).toBeNull(); + expect(capabilities.lookupLatestVersion).toBeDefined(); + expect(capabilities.manualCommand).toBe("choco upgrade claude-code"); + }), + ); + + it.effect("keeps a Chocolatey-shaped path off Windows on the native updater", () => + Effect.gen(function* () { + const commandPath = "/home/me/chocolatey/bin/claude.exe"; + const capabilities = yield* resolveInstall({ + definition: claudeUpdate, + resolved: commandPath, + real: commandPath, + platform: "linux", + }); + + expect(capabilities.update).toMatchObject({ lockKey: "claudeAgent-native" }); + }), + ); + + // Chocolatey publishes behind npm, so comparing against the registry would + // report an update `choco upgrade` cannot install yet. + it.effect("compares a Chocolatey Claude install against choco search", () => + Effect.gen(function* () { + const probes: Array = []; + const capabilities = yield* resolvePackageManagedProviderMaintenance(claudeUpdate, { + binaryPath: "claude", + resolvedCommandPath: chocolateyShim, + realCommandPath: chocolateyShim, + env: {}, + platform: "win32", + }).pipe( + Effect.provideService(HostProcess.Platform, "win32"), + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + stdoutSpawner((command) => { + probes.push(command); + return "claude-code|2.1.304\r\n"; + }), + ), + ); + expect(probes).toEqual([]); + + const latest = yield* resolveLatestProviderVersion(capabilities).pipe( + Effect.provide(ProviderLatestVersions.layer), + Effect.provideService( + HttpClient.HttpClient, + HttpClient.make(() => Effect.die("the installer's latest should not come from npm")), + ), + ); + + expect(latest).toBe("2.1.304"); + expect(probes.map((command) => NodePath.basename(command).replace(/\.\w+$/, ""))).toEqual([ + "choco", + ]); + }).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect("stays unknown when choco search fails instead of asking npm", () => + Effect.gen(function* () { + const capabilities = yield* resolvePackageManagedProviderMaintenance(claudeUpdate, { + binaryPath: "claude", + resolvedCommandPath: chocolateyShim, + realCommandPath: chocolateyShim, + env: {}, + platform: "win32", + }).pipe( + Effect.provideService(HostProcess.Platform, "win32"), + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + stdoutSpawner( + () => "", + () => 1, + ), + ), + ); + + const latest = yield* resolveLatestProviderVersion(capabilities).pipe( + Effect.provide(ProviderLatestVersions.layer), + Effect.provideService( + HttpClient.HttpClient, + HttpClient.make(() => Effect.die("a failed choco search should not fall back to npm")), + ), + ); + + expect(latest).toBeNull(); + }).pipe(Effect.provide(NodeServices.layer)), + ); + it.effect.each([ { name: "a native install", @@ -863,6 +993,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { }), ); + it("reads the Chocolatey package version from choco search --limit-output", () => { + expect(parseChocolateyLatestVersion("claude-code|2.1.304\r\n", "claude-code")).toBe("2.1.304"); + expect(parseChocolateyLatestVersion("Claude-Code|2.1.304\r\n", "claude-code")).toBe("2.1.304"); + expect(parseChocolateyLatestVersion("claude-code-other|9.9.9\r\n", "claude-code")).toBeNull(); + expect(parseChocolateyLatestVersion("", "claude-code")).toBeNull(); + }); + it("recognizes Homebrew kegs and casks from the real executable path", () => { expect( homebrewOwnershipFromCommandPath("/opt/homebrew/Cellar/claude-code@latest/2.1.0/bin/claude"), diff --git a/packages/provider-core/src/server/maintenanceResolver.ts b/packages/provider-core/src/server/maintenanceResolver.ts index ed3967ebb4654..baa1c62987c1a 100644 --- a/packages/provider-core/src/server/maintenanceResolver.ts +++ b/packages/provider-core/src/server/maintenanceResolver.ts @@ -194,6 +194,13 @@ export function makeManualOnlyProviderMaintenanceCapabilities(input: { readonly provider: ProviderDriverKind; readonly packageName: string | null; readonly installPath?: string; + /** + * The owning installer's own release, when it publishes behind npm. Without + * it the npm registry is authoritative, and the advisory would keep asking + * for a version the installer cannot provide yet. + */ + readonly lookupLatestVersion?: Effect.Effect; + readonly manualCommand?: string; }): ProviderMaintenanceCapabilities { return { ...makeProviderMaintenanceCapabilities({ @@ -202,8 +209,12 @@ export function makeManualOnlyProviderMaintenanceCapabilities(input: { updateExecutable: null, updateArgs: [], updateLockKey: null, + ...(input.lookupLatestVersion + ? { latestVersion: null, lookupLatestVersion: input.lookupLatestVersion } + : {}), }), ...(input.installPath ? { installPath: input.installPath } : {}), + ...(input.manualCommand ? { manualCommand: input.manualCommand } : {}), }; } @@ -248,6 +259,34 @@ function isWinGetClaudeCommandPath(commandPath: string): boolean { return winGetClaudeCommandPath.test(normalizeCommandPath(commandPath)); } +const CHOCOLATEY_CLAUDE_PACKAGE_ID = "claude-code"; + +/** + * Chocolatey's Claude Code package: the shimgen shim in `\bin` + * (default `chocolatey\bin`) or the binary it launches from `lib\claude-code\tools`. + * The shim is a real executable rather than a link, so following symlinks never + * reaches the package directory. A custom root is not in that path shape, so it is + * also compared with `ChocolateyInstall`. + */ +const chocolateyClaudeCommandPath = /\/(?:chocolatey\/bin|lib\/claude-code\/tools)\/claude\.exe$/; + +function isChocolateyClaudeCommandPath(commandPath: string, env: NodeJS.ProcessEnv): boolean { + if (chocolateyClaudeCommandPath.test(normalizeCommandPath(commandPath))) return true; + const root = nonEmptyString(env.ChocolateyInstall); + if (!root) return false; + const shim = normalizeCommandPath(`${root.replace(/[\\/]+$/, "")}/bin/claude.exe`); + return normalizeCommandPath(commandPath) === shim; +} + +/** `choco search --exact --limit-output` prints `|` for a match and nothing otherwise. */ +export function parseChocolateyLatestVersion(output: string, packageId: string): string | null { + for (const line of output.split(/\r?\n/)) { + const [id, version] = line.trim().split("|", 2); + if (id?.toLowerCase() === packageId.toLowerCase()) return nonEmptyString(version); + } + return null; +} + function isPnpmGlobalCommandPath(commandPath: string): boolean { const normalized = normalizeCommandPath(commandPath); return ( @@ -450,6 +489,32 @@ export const resolvePackageManagedProviderMaintenance = Effect.fn( ) { return manual; } + // Chocolatey's package directory is writable only by administrators, so an + // unelevated server cannot run `choco upgrade`; `claude update` through the + // shim installs a native copy elsewhere and leaves the shim's version alone. + if ( + definition.provider === "claudeAgent" && + context.platform === "win32" && + commandPaths.some((commandPath) => isChocolateyClaudeCommandPath(commandPath, context.env)) + ) { + const services = yield* Effect.context(); + return makeManualOnlyProviderMaintenanceCapabilities({ + provider: definition.provider, + packageName, + installPath: context.realCommandPath, + manualCommand: "choco upgrade claude-code", + lookupLatestVersion: runProbe( + "choco", + ["search", CHOCOLATEY_CLAUDE_PACKAGE_ID, "--exact", "--limit-output"], + context.env, + ).pipe( + Effect.map((output) => + output ? parseChocolateyLatestVersion(output, CHOCOLATEY_CLAUDE_PACKAGE_ID) : null, + ), + Effect.provideContext(services), + ), + }); + } const nativeUpdate = definition.nativeUpdate; const native = nativeUpdate @@ -839,7 +904,10 @@ export function createProviderVersionAdvisory(input: { status: advisory.status, currentVersion: input.currentVersion, latestVersion, - updateCommand: resolveLatestProviderUpdateAction(capabilities, latestVersion)?.command ?? null, + updateCommand: + resolveLatestProviderUpdateAction(capabilities, latestVersion)?.command ?? + capabilities.manualCommand ?? + null, canUpdate: capabilities.update !== null, canInstallVersion: makeTargetedProviderUpdateAction(capabilities, "0.0.0") !== null, checkedAt: input.checkedAt ?? null, @@ -870,12 +938,15 @@ const fetchNpmLatestVersion = Effect.fn("fetchNpmLatestVersion")(function* (pack return payload ? nonEmptyString(payload.version) : null; }); -/** The installer's own answer is cached apart from the npm registry entry. */ +/** + * The installer's own answer is cached apart from the npm registry entry. A + * manual-only install has no command to key on, so its executable stands in. + */ function installerLatestVersionKey(capabilities: ProviderMaintenanceCapabilities) { + if (!capabilities.lookupLatestVersion) return null; const update = capabilities.update; - return capabilities.lookupLatestVersion && update - ? [update.lockKey, update.executable, ...update.args].join("\0") - : null; + if (update) return [update.lockKey, update.executable, ...update.args].join("\0"); + return capabilities.installPath ? ["manual", capabilities.installPath].join("\0") : null; } export function latestProviderVersionCacheKeys( From 88f139448691f60b0bd8a1223a8446d172cbe911 Mon Sep 17 00:00:00 2001 From: Rob Homewood Date: Wed, 21 Oct 2026 17:16:56 +0100 Subject: [PATCH 2/3] fix(provider-core): only treat Claude as Chocolatey-owned under a Chocolatey root A path ending in lib\claude-code\tools\claude.exe was enough to hide the native updater and show choco upgrade. Require the default chocolatey directory or ChocolateyInstall. Co-authored-by: Cursor --- .../src/server/maintenanceResolver.test.ts | 12 ++++++++++ .../src/server/maintenanceResolver.ts | 22 +++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/provider-core/src/server/maintenanceResolver.test.ts b/packages/provider-core/src/server/maintenanceResolver.test.ts index d446c6d169042..f357c796ebbc3 100644 --- a/packages/provider-core/src/server/maintenanceResolver.test.ts +++ b/packages/provider-core/src/server/maintenanceResolver.test.ts @@ -463,6 +463,12 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { real: "D:\\Tools\\Choco\\bin\\claude.exe", env: { ChocolateyInstall: "D:\\Tools\\Choco" }, }, + { + name: "a custom root package", + resolved: "D:\\Tools\\Choco\\lib\\claude-code\\tools\\claude.exe", + real: "D:\\Tools\\Choco\\lib\\claude-code\\tools\\claude.exe", + env: { ChocolateyInstall: "D:\\Tools\\Choco" }, + }, ] as const)("keeps a Chocolatey Claude install manual-only through $name", (fixture) => Effect.gen(function* () { const capabilities = yield* resolveInstall({ definition: claudeUpdate, ...fixture }); @@ -590,6 +596,12 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { resolved: userWinGetLink, real: userWinGetPackage, }, + { + name: "a claude-code tools path outside Chocolatey", + definition: claudeUpdate, + resolved: "C:\\Work\\lib\\claude-code\\tools\\claude.exe", + real: "C:\\Work\\lib\\claude-code\\tools\\claude.exe", + }, { name: "another WinGet package", definition: claudeUpdate, diff --git a/packages/provider-core/src/server/maintenanceResolver.ts b/packages/provider-core/src/server/maintenanceResolver.ts index baa1c62987c1a..9e93115706691 100644 --- a/packages/provider-core/src/server/maintenanceResolver.ts +++ b/packages/provider-core/src/server/maintenanceResolver.ts @@ -262,20 +262,24 @@ function isWinGetClaudeCommandPath(commandPath: string): boolean { const CHOCOLATEY_CLAUDE_PACKAGE_ID = "claude-code"; /** - * Chocolatey's Claude Code package: the shimgen shim in `\bin` - * (default `chocolatey\bin`) or the binary it launches from `lib\claude-code\tools`. - * The shim is a real executable rather than a link, so following symlinks never - * reaches the package directory. A custom root is not in that path shape, so it is - * also compared with `ChocolateyInstall`. + * Chocolatey's Claude Code package: the shimgen shim in `\bin` or the + * binary it launches from `\lib\claude-code\tools`. The default root's + * directory is named `chocolatey`. A custom root is not, so those paths are + * compared with `ChocolateyInstall`. The shim is a real executable rather than + * a link, so following symlinks never reaches the package directory. */ -const chocolateyClaudeCommandPath = /\/(?:chocolatey\/bin|lib\/claude-code\/tools)\/claude\.exe$/; +const chocolateyClaudeCommandPath = /\/chocolatey\/(?:bin|lib\/claude-code\/tools)\/claude\.exe$/; function isChocolateyClaudeCommandPath(commandPath: string, env: NodeJS.ProcessEnv): boolean { - if (chocolateyClaudeCommandPath.test(normalizeCommandPath(commandPath))) return true; + const normalized = normalizeCommandPath(commandPath); + if (chocolateyClaudeCommandPath.test(normalized)) return true; const root = nonEmptyString(env.ChocolateyInstall); if (!root) return false; - const shim = normalizeCommandPath(`${root.replace(/[\\/]+$/, "")}/bin/claude.exe`); - return normalizeCommandPath(commandPath) === shim; + const prefix = normalizeCommandPath(root.replace(/[\\/]+$/, "")); + return ( + normalized === `${prefix}/bin/claude.exe` || + normalized === `${prefix}/lib/claude-code/tools/claude.exe` + ); } /** `choco search --exact --limit-output` prints `|` for a match and nothing otherwise. */ From 89f433b5931e2c59397f7be1d4d305055d3fadac Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Mon, 26 Oct 2026 11:41:02 +0000 Subject: [PATCH 3/3] test(provider-core): verify Chocolatey Claude update boundaries --- .../provider-core/src/server/maintenance.ts | 4 +-- .../src/server/maintenanceResolver.test.ts | 28 +++++++++++++++---- .../src/server/maintenanceResolver.ts | 13 +-------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/provider-core/src/server/maintenance.ts b/packages/provider-core/src/server/maintenance.ts index 1a68708bc7f7a..86341e74ac534 100644 --- a/packages/provider-core/src/server/maintenance.ts +++ b/packages/provider-core/src/server/maintenance.ts @@ -15,9 +15,7 @@ export interface ProviderMaintenanceCapabilities { readonly compareVersions?: (current: string, latest: string) => number; /** Resolved executable path for advisories when no update command is proven. */ readonly installPath?: string; - /** - * A command T3 Code shows but cannot run. - */ + /** Displayed for manual updates; never executed by T3 Code. */ readonly manualCommand?: string; } diff --git a/packages/provider-core/src/server/maintenanceResolver.test.ts b/packages/provider-core/src/server/maintenanceResolver.test.ts index 829cd97eb0443..0473c8456bfd7 100644 --- a/packages/provider-core/src/server/maintenanceResolver.test.ts +++ b/packages/provider-core/src/server/maintenanceResolver.test.ts @@ -498,6 +498,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { real: "D:\\Tools\\Choco\\lib\\claude-code\\tools\\claude.exe", env: { ChocolateyInstall: "D:\\Tools\\Choco" }, }, + { + name: "a mixed-case custom root with a trailing separator", + resolved: "D:\\Tools\\Choco\\bin\\Claude.EXE", + real: "D:\\Tools\\Choco\\bin\\Claude.EXE", + env: { ChocolateyInstall: "d:/tools/choco/" }, + }, + { name: "a native-looking alias", resolved: nativeClaude, real: chocolateyPackage }, ] as const)("keeps a Chocolatey Claude install manual-only through $name", (fixture) => Effect.gen(function* () { const capabilities = yield* resolveInstall({ definition: claudeUpdate, ...fixture }); @@ -528,7 +535,7 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { // report an update `choco upgrade` cannot install yet. it.effect("compares a Chocolatey Claude install against choco search", () => Effect.gen(function* () { - const probes: Array = []; + const probes: Array<{ command: string; args: ReadonlyArray }> = []; const capabilities = yield* resolvePackageManagedProviderMaintenance(claudeUpdate, { binaryPath: "claude", resolvedCommandPath: chocolateyShim, @@ -539,8 +546,8 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { Effect.provideService(HostProcess.Platform, "win32"), Effect.provideService( ChildProcessSpawner.ChildProcessSpawner, - stdoutSpawner((command) => { - probes.push(command); + stdoutSpawner((command, args) => { + probes.push({ command, args }); return "claude-code|2.1.304\r\n"; }), ), @@ -556,9 +563,18 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { ); expect(latest).toBe("2.1.304"); - expect(probes.map((command) => NodePath.basename(command).replace(/\.\w+$/, ""))).toEqual([ - "choco", - ]); + expect(probes.map(({ command }) => NodePath.basename(command).replace(/\.\w+$/, ""))).toEqual( + ["choco"], + ); + expect(probes[0]?.args).toEqual(["search", "claude-code", "--exact", "--limit-output"]); + expect( + createProviderVersionAdvisory({ + driver: driver("claudeAgent"), + currentVersion: "2.1.304", + latestVersion: latest, + maintenanceCapabilities: capabilities, + }), + ).toMatchObject({ status: "current", canUpdate: false, canInstallVersion: false }); }).pipe(Effect.provide(NodeServices.layer)), ); diff --git a/packages/provider-core/src/server/maintenanceResolver.ts b/packages/provider-core/src/server/maintenanceResolver.ts index dd418adf61a83..17b64ee1dffa1 100644 --- a/packages/provider-core/src/server/maintenanceResolver.ts +++ b/packages/provider-core/src/server/maintenanceResolver.ts @@ -196,11 +196,6 @@ export function makeManualOnlyProviderMaintenanceCapabilities(input: { readonly provider: ProviderDriverKind; readonly packageName: string | null; readonly installPath?: string; - /** - * The owning installer's own release, when it publishes behind npm. Without - * it the npm registry is authoritative, and the advisory would keep asking - * for a version the installer cannot provide yet. - */ readonly lookupLatestVersion?: Effect.Effect; readonly manualCommand?: string; }): ProviderMaintenanceCapabilities { @@ -258,13 +253,7 @@ function isWinGetClaudeCommandPath(commandPath: string): boolean { const CHOCOLATEY_CLAUDE_PACKAGE_ID = "claude-code"; -/** - * Chocolatey's Claude Code package: the shimgen shim in `\bin` or the - * binary it launches from `\lib\claude-code\tools`. The default root's - * directory is named `chocolatey`. A custom root is not, so those paths are - * compared with `ChocolateyInstall`. The shim is a real executable rather than - * a link, so following symlinks never reaches the package directory. - */ +// Chocolatey's executable shim is not a symlink, so realpath cannot prove its owner. const chocolateyClaudeCommandPath = /\/chocolatey\/(?:bin|lib\/claude-code\/tools)\/claude\.exe$/; function isChocolateyClaudeCommandPath(commandPath: string, env: NodeJS.ProcessEnv): boolean {