slopus/happy · error
Claude local launcher not found. Please ensure HAPPY_PROJECT
Error message
Claude local launcher not found. Please ensure HAPPY_PROJECT_ROOT is set correctly for development.
What it means
In development mode the CLI spawns a locally-built Claude launcher script instead of the packaged one. Before spawning it checks that the resolved claudeCliPath exists on disk; if the path is unset or the file is missing, it throws this error telling the developer to set HAPPY_PROJECT_ROOT correctly.
Source
Thrown at packages/happy-cli/src/claude/claudeLocal.ts:254
}
if (opts.allowedTools && opts.allowedTools.length > 0) {
args.push('--allowedTools', opts.allowedTools.join(','));
}
// Add custom Claude arguments
if (opts.claudeArgs) {
args.push(...opts.claudeArgs)
}
// Add hook settings for session tracking (when available)
if (opts.hookSettingsPath) {
args.push('--settings', opts.hookSettingsPath);
logger.debug(`[ClaudeLocal] Using hook settings: ${opts.hookSettingsPath}`);
}
if (!claudeCliPath || !existsSync(claudeCliPath)) {
throw new Error('Claude local launcher not found. Please ensure HAPPY_PROJECT_ROOT is set correctly for development.');
}
// Prepare environment variables
// Note: Local mode uses global Claude installation with --session-id flag
// Launcher only intercepts fetch for thinking state tracking
const env = {
...process.env,
...opts.claudeEnvVars
}
if (opts.mcpServers && Object.keys(opts.mcpServers).length > 0) {
ensureLocalProxyBypass(env);
}
logger.debug(`[ClaudeLocal] Spawning launcher: ${claudeCliPath}`);
logger.debug(`[ClaudeLocal] Args: ${JSON.stringify(args)}`);
(async () => {View on GitHub (pinned to b824cd0a46)
Solutions
- Set HAPPY_PROJECT_ROOT to the absolute path of your happy repo checkout.
- Build the local launcher in that checkout (npm install && npm run build).
- Verify the launcher file exists: ls $HAPPY_PROJECT_ROOT/<expected launcher path>.
- If you are not developing the CLI itself, run the published CLI instead of local mode.
- Confirm the path has no trailing-slash/typo issues and the file is executable.
Example fix
// before export HAPPY_PROJECT_ROOT=./happy // after export HAPPY_PROJECT_ROOT=/home/me/src/happy && ls $HAPPY_PROJECT_ROOT/packages/happy-cli/dist && npm run build
Defensive patterns
Strategy: validation
Validate before calling
const root = process.env.HAPPY_PROJECT_ROOT;
if (!root) throw new Error('HAPPY_PROJECT_ROOT must be set for local development mode');
if (!existsSync(resolve(root, 'packages/happy-cli/dist'))) throw new Error(`No build found under ${root} — run npm run build`); Type guard
function hasLocalLauncher(p: string | null | undefined): p is string {
return typeof p === 'string' && p.length > 0 && existsSync(p);
} Try / catch
try {
await runClaude(options);
} catch (err) {
if ((err as Error).message.includes('Claude local launcher not found')) {
console.error('Dev launcher missing. Set HAPPY_PROJECT_ROOT to your happy checkout and build it.');
process.exit(1);
}
throw err;
} Prevention
- Export HAPPY_PROJECT_ROOT in your dev shell profile or direnv config.
- Always build after cloning or pulling before using local mode.
- Use the published CLI unless actively developing the CLI itself.
- Add a pre-flight existsSync check in wrapper scripts.
When it happens
Trigger: HAPPY_PROJECT_ROOT is unset, points to a directory that is not a happy repo checkout, or the launcher binary has not been built, so existsSync(claudeCliPath) returns false right before spawning the local Claude process.
Common situations: Running the CLI from source (dev mode) in a fresh clone without building; HAPPY_PROJECT_ROOT pointing at the wrong path after moving the repo; running from a packaged install where the dev launcher was never expected to exist.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- No machine ID found in settings
- Unknown agent: ${id}. Available agents: ${available}
- No machine ID found in settings
- Daemon-spawned sessions cannot use local/interactive mode. U
- Failed to logout: ${error instanceof Error ? error.message :
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/37333bbad94b5460.
Report an issue: GitHub.