Summary
ccs update always runs npm install -g @kaitranntt/ccs@latest on my machine even though CCS is installed globally via pnpm. It fails because I don't use/want npm for global installs.
Root cause
In dist/utils/package-manager-detector.js, inferInstallFromPath() detects a pnpm-managed flat global install with this regex:
const pnpmFlatMatch = normalizedPath.match(/\/global\/([^/]+)\/node_modules\/@kaitranntt\/ccs/);
This assumes exactly one path segment between global/ and node_modules/. But pnpm's global store layout on recent pnpm versions (11.x here) nests an extra version segment, e.g.:
~/Library/pnpm/global/v11/139e7-1a00df73ffb-064d180929716eff/node_modules/@kaitranntt/ccs/dist/ccs.js
That's two segments (v11 and a hash) between global/ and node_modules/, so the regex never matches. None of the other branches in inferInstallFromPath match either, so detectCurrentInstall() falls through to the hardcoded default:
return {
manager: 'npm',
...
detectionSource: 'default',
};
ccs update then runs npm install -g @kaitranntt/ccs@latest, which is the wrong package manager for a pnpm-managed global install.
Reproduction
- Install CCS globally via pnpm on a pnpm version that uses the
global/vNN/<hash>/node_modules layout (pnpm 11.x): pnpm add -g @kaitranntt/ccs
- Run
ccs update
- Observe it invokes npm instead of pnpm (visible via
ccs --version showing Installation: Location: .../pnpm/global/v11/<hash>/node_modules/@kaitranntt/ccs/dist/ccs.js but the update command still uses npm install -g).
Workaround: update manually with pnpm add -g @kaitranntt/ccs@latest.
Suggested fix
Loosen the pnpm-flat-global regex to allow one or more path segments between global/ and node_modules/@kaitranntt/ccs, e.g.:
const pnpmFlatMatch = normalizedPath.match(/\/global\/(?:[^/]+\/)+node_modules\/@kaitranntt\/ccs/);
(with a guard against matching a literal lib/ segment, as the existing code already does for the single-segment case)
Environment
- CCS version: 8.9.0 (also reproduced on 8.8.1)
- pnpm version: 11.17.0
- OS: macOS (darwin)
- Install command:
pnpm add -g @kaitranntt/ccs
Summary
ccs updatealways runsnpm install -g @kaitranntt/ccs@lateston my machine even though CCS is installed globally via pnpm. It fails because I don't use/want npm for global installs.Root cause
In
dist/utils/package-manager-detector.js,inferInstallFromPath()detects a pnpm-managed flat global install with this regex:This assumes exactly one path segment between
global/andnode_modules/. But pnpm's global store layout on recent pnpm versions (11.x here) nests an extra version segment, e.g.:That's two segments (
v11and a hash) betweenglobal/andnode_modules/, so the regex never matches. None of the other branches ininferInstallFromPathmatch either, sodetectCurrentInstall()falls through to the hardcoded default:ccs updatethen runsnpm install -g @kaitranntt/ccs@latest, which is the wrong package manager for a pnpm-managed global install.Reproduction
global/vNN/<hash>/node_moduleslayout (pnpm 11.x):pnpm add -g @kaitranntt/ccsccs updateccs --versionshowingInstallation: Location: .../pnpm/global/v11/<hash>/node_modules/@kaitranntt/ccs/dist/ccs.jsbut the update command still usesnpm install -g).Workaround: update manually with
pnpm add -g @kaitranntt/ccs@latest.Suggested fix
Loosen the pnpm-flat-global regex to allow one or more path segments between
global/andnode_modules/@kaitranntt/ccs, e.g.:(with a guard against matching a literal
lib/segment, as the existing code already does for the single-segment case)Environment
pnpm add -g @kaitranntt/ccs