fix: prepend claude CLI install paths to subprocess PATH (env-sanitizer)
Root cause: worker launched by Claude Desktop inherits a narrow PATH that omits ~/.local/bin and ~/.bun/bin, so SDK subprocesses fail with "Claude executable not found" — observations pile up in the queue but are never processed, producing the "only my messages get recorded" symptom that patching session reset logic could not fix. env-sanitizer now prepends the common install locations (~/.local/bin, ~/.bun/bin, ~/bin, /opt/homebrew/bin, /usr/local/bin on Unix; matching Windows locations) to PATH before spawning SDK subprocesses, so the worker can locate the claude binary regardless of launch context. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -12,6 +12,35 @@ export const ENV_PRESERVE = new Set([
|
|||||||
'CLAUDE_CODE_GIT_BASH_PATH',
|
'CLAUDE_CODE_GIT_BASH_PATH',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common user-install locations where the `claude` CLI binary may live.
|
||||||
|
* Claude Desktop spawns the worker without inheriting the user's shell profile
|
||||||
|
* PATH, so `~/.local/bin` and `~/.bun/bin` are frequently missing — which
|
||||||
|
* causes the SDK subprocess to fail with "Claude executable not found" and
|
||||||
|
* silently blocks all memory processing.
|
||||||
|
*
|
||||||
|
* We unconditionally prepend these paths (skipping ones already present) so
|
||||||
|
* the worker can locate `claude` regardless of how it was launched.
|
||||||
|
*/
|
||||||
|
function extraClaudePathLocations(env: NodeJS.ProcessEnv): string[] {
|
||||||
|
const home = env.HOME || env.USERPROFILE;
|
||||||
|
if (!home) return ['/opt/homebrew/bin', '/usr/local/bin'];
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return [
|
||||||
|
`${home}\\AppData\\Local\\Programs\\claude`,
|
||||||
|
`${home}\\.bun\\bin`,
|
||||||
|
`${home}\\.local\\bin`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
`${home}/.local/bin`,
|
||||||
|
`${home}/.bun/bin`,
|
||||||
|
`${home}/bin`,
|
||||||
|
'/opt/homebrew/bin',
|
||||||
|
'/usr/local/bin'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export function sanitizeEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
export function sanitizeEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
||||||
const sanitized: NodeJS.ProcessEnv = {};
|
const sanitized: NodeJS.ProcessEnv = {};
|
||||||
|
|
||||||
@@ -23,5 +52,15 @@ export function sanitizeEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.Proces
|
|||||||
sanitized[key] = value;
|
sanitized[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure PATH includes common locations where `claude` CLI is installed.
|
||||||
|
// See extraClaudePathLocations() for the rationale.
|
||||||
|
const sep = process.platform === 'win32' ? ';' : ':';
|
||||||
|
const currentPath = sanitized.PATH || sanitized.Path || '';
|
||||||
|
const existing = new Set(currentPath.split(sep).filter(Boolean));
|
||||||
|
const toPrepend = extraClaudePathLocations(env).filter(p => !existing.has(p));
|
||||||
|
if (toPrepend.length > 0) {
|
||||||
|
sanitized.PATH = [...toPrepend, currentPath].filter(Boolean).join(sep);
|
||||||
|
}
|
||||||
|
|
||||||
return sanitized;
|
return sanitized;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user