mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-05 08:43:29 +08:00
fix: eliminate child process spawns during session startup (#162)
getAvailablePackageManagers() spawned where.exe/which for each package manager (npm, pnpm, yarn, bun). During SessionStart hooks, these 4+ child processes combined with Bun's own initialization exceeded the spawn limit on Windows, freezing the terminal. Fix: Remove process spawning from the hot path. Steps 1-5 of detection (env var, project config, package.json, lock file, global config) already cover all file-based detection. If none match, default to npm without spawning. Also fix getSelectionPrompt() to list supported PMs without checking availability.
This commit is contained in:
@@ -66,8 +66,8 @@ async function main() {
|
|||||||
const pm = getPackageManager();
|
const pm = getPackageManager();
|
||||||
log(`[SessionStart] Package manager: ${pm.name} (${pm.source})`);
|
log(`[SessionStart] Package manager: ${pm.name} (${pm.source})`);
|
||||||
|
|
||||||
// If package manager was detected via fallback, show selection prompt
|
// If no explicit package manager config was found, show selection prompt
|
||||||
if (pm.source === 'fallback' || pm.source === 'default') {
|
if (pm.source === 'default') {
|
||||||
log('[SessionStart] No package manager preference found.');
|
log('[SessionStart] No package manager preference found.');
|
||||||
log(getSelectionPrompt());
|
log(getSelectionPrompt());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,11 @@ function detectFromPackageJson(projectDir = process.cwd()) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get available package managers (installed on system)
|
* Get available package managers (installed on system)
|
||||||
|
*
|
||||||
|
* WARNING: This spawns child processes (where.exe on Windows, which on Unix)
|
||||||
|
* for each package manager. Do NOT call this during session startup hooks —
|
||||||
|
* it can exceed Bun's spawn limit on Windows and freeze the plugin.
|
||||||
|
* Use detectFromLockFile() or detectFromPackageJson() for hot paths.
|
||||||
*/
|
*/
|
||||||
function getAvailablePackageManagers() {
|
function getAvailablePackageManagers() {
|
||||||
const available = [];
|
const available = [];
|
||||||
@@ -149,7 +154,7 @@ function getAvailablePackageManagers() {
|
|||||||
* 3. package.json packageManager field
|
* 3. package.json packageManager field
|
||||||
* 4. Lock file detection
|
* 4. Lock file detection
|
||||||
* 5. Global user preference (in ~/.claude/package-manager.json)
|
* 5. Global user preference (in ~/.claude/package-manager.json)
|
||||||
* 6. First available package manager (by priority)
|
* 6. Default to npm (no child processes spawned)
|
||||||
*
|
*
|
||||||
* @param {object} options - { projectDir, fallbackOrder }
|
* @param {object} options - { projectDir, fallbackOrder }
|
||||||
* @returns {object} - { name, config, source }
|
* @returns {object} - { name, config, source }
|
||||||
@@ -215,19 +220,13 @@ function getPackageManager(options = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Use first available package manager
|
// 6. Default to npm (always available with Node.js)
|
||||||
const available = getAvailablePackageManagers();
|
// NOTE: Previously this called getAvailablePackageManagers() which spawns
|
||||||
for (const pmName of fallbackOrder) {
|
// child processes (where.exe/which) for each PM. This caused plugin freezes
|
||||||
if (available.includes(pmName)) {
|
// on Windows (see #162) because session-start hooks run during Bun init,
|
||||||
return {
|
// and the spawned processes exceed Bun's spawn limit.
|
||||||
name: pmName,
|
// Steps 1-5 already cover all config-based and file-based detection.
|
||||||
config: PACKAGE_MANAGERS[pmName],
|
// If none matched, npm is the safe default.
|
||||||
source: 'fallback'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to npm (always available with Node.js)
|
|
||||||
return {
|
return {
|
||||||
name: 'npm',
|
name: 'npm',
|
||||||
config: PACKAGE_MANAGERS.npm,
|
config: PACKAGE_MANAGERS.npm,
|
||||||
@@ -306,22 +305,18 @@ function getExecCommand(binary, args = '', options = {}) {
|
|||||||
/**
|
/**
|
||||||
* Interactive prompt for package manager selection
|
* Interactive prompt for package manager selection
|
||||||
* Returns a message for Claude to show to user
|
* Returns a message for Claude to show to user
|
||||||
|
*
|
||||||
|
* NOTE: Does NOT spawn child processes to check availability.
|
||||||
|
* Lists all supported PMs and shows how to configure preference.
|
||||||
*/
|
*/
|
||||||
function getSelectionPrompt() {
|
function getSelectionPrompt() {
|
||||||
const available = getAvailablePackageManagers();
|
let message = '[PackageManager] No package manager preference detected.\n';
|
||||||
const current = getPackageManager();
|
message += 'Supported package managers: ' + Object.keys(PACKAGE_MANAGERS).join(', ') + '\n';
|
||||||
|
|
||||||
let message = '[PackageManager] Available package managers:\n';
|
|
||||||
|
|
||||||
for (const pmName of available) {
|
|
||||||
const indicator = pmName === current.name ? ' (current)' : '';
|
|
||||||
message += ` - ${pmName}${indicator}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
message += '\nTo set your preferred package manager:\n';
|
message += '\nTo set your preferred package manager:\n';
|
||||||
message += ' - Global: Set CLAUDE_PACKAGE_MANAGER environment variable\n';
|
message += ' - Global: Set CLAUDE_PACKAGE_MANAGER environment variable\n';
|
||||||
message += ' - Or add to ~/.claude/package-manager.json: {"packageManager": "pnpm"}\n';
|
message += ' - Or add to ~/.claude/package-manager.json: {"packageManager": "pnpm"}\n';
|
||||||
message += ' - Or add to package.json: {"packageManager": "pnpm@8"}\n';
|
message += ' - Or add to package.json: {"packageManager": "pnpm@8"}\n';
|
||||||
|
message += ' - Or add a lock file to your project (e.g., pnpm-lock.yaml)\n';
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user