mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-02-15 10:53:18 +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();
|
||||
log(`[SessionStart] Package manager: ${pm.name} (${pm.source})`);
|
||||
|
||||
// If package manager was detected via fallback, show selection prompt
|
||||
if (pm.source === 'fallback' || pm.source === 'default') {
|
||||
// If no explicit package manager config was found, show selection prompt
|
||||
if (pm.source === 'default') {
|
||||
log('[SessionStart] No package manager preference found.');
|
||||
log(getSelectionPrompt());
|
||||
}
|
||||
|
||||
@@ -127,6 +127,11 @@ function detectFromPackageJson(projectDir = process.cwd()) {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
const available = [];
|
||||
@@ -149,7 +154,7 @@ function getAvailablePackageManagers() {
|
||||
* 3. package.json packageManager field
|
||||
* 4. Lock file detection
|
||||
* 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 }
|
||||
* @returns {object} - { name, config, source }
|
||||
@@ -215,19 +220,13 @@ function getPackageManager(options = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
// 6. Use first available package manager
|
||||
const available = getAvailablePackageManagers();
|
||||
for (const pmName of fallbackOrder) {
|
||||
if (available.includes(pmName)) {
|
||||
return {
|
||||
name: pmName,
|
||||
config: PACKAGE_MANAGERS[pmName],
|
||||
source: 'fallback'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Default to npm (always available with Node.js)
|
||||
// 6. Default to npm (always available with Node.js)
|
||||
// NOTE: Previously this called getAvailablePackageManagers() which spawns
|
||||
// child processes (where.exe/which) for each PM. This caused plugin freezes
|
||||
// on Windows (see #162) because session-start hooks run during Bun init,
|
||||
// and the spawned processes exceed Bun's spawn limit.
|
||||
// Steps 1-5 already cover all config-based and file-based detection.
|
||||
// If none matched, npm is the safe default.
|
||||
return {
|
||||
name: 'npm',
|
||||
config: PACKAGE_MANAGERS.npm,
|
||||
@@ -306,22 +305,18 @@ function getExecCommand(binary, args = '', options = {}) {
|
||||
/**
|
||||
* Interactive prompt for package manager selection
|
||||
* 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() {
|
||||
const available = getAvailablePackageManagers();
|
||||
const current = getPackageManager();
|
||||
|
||||
let message = '[PackageManager] Available package managers:\n';
|
||||
|
||||
for (const pmName of available) {
|
||||
const indicator = pmName === current.name ? ' (current)' : '';
|
||||
message += ` - ${pmName}${indicator}\n`;
|
||||
}
|
||||
|
||||
let message = '[PackageManager] No package manager preference detected.\n';
|
||||
message += 'Supported package managers: ' + Object.keys(PACKAGE_MANAGERS).join(', ') + '\n';
|
||||
message += '\nTo set your preferred package manager:\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 package.json: {"packageManager": "pnpm@8"}\n';
|
||||
message += ' - Or add a lock file to your project (e.g., pnpm-lock.yaml)\n';
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user