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

  1. Set HAPPY_PROJECT_ROOT to the absolute path of your happy repo checkout.
  2. Build the local launcher in that checkout (npm install && npm run build).
  3. Verify the launcher file exists: ls $HAPPY_PROJECT_ROOT/<expected launcher path>.
  4. If you are not developing the CLI itself, run the published CLI instead of local mode.
  5. 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

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


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/37333bbad94b5460. Report an issue: GitHub.