diff --git a/src/claude/runClaude.ts b/src/claude/runClaude.ts index cd75cf7f..7f86b210 100644 --- a/src/claude/runClaude.ts +++ b/src/claude/runClaude.ts @@ -31,6 +31,7 @@ export interface StartOptions { claudeEnvVars?: Record claudeArgs?: string[] startedBy?: 'daemon' | 'terminal' + name?: string } export async function runClaude(credentials: Credentials, options: StartOptions = {}): Promise { @@ -75,6 +76,10 @@ export async function runClaude(credentials: Credentials, options: StartOptions host: os.hostname(), version: packageJson.version, os: os.platform(), + summary: options.name ? { + text: options.name, + updatedAt: Date.now() + } : undefined, machineId: machineId, homeDir: os.homedir(), happyHomeDir: configuration.happyHomeDir, diff --git a/src/codex/runCodex.ts b/src/codex/runCodex.ts index 62b4b5fd..f0808298 100644 --- a/src/codex/runCodex.ts +++ b/src/codex/runCodex.ts @@ -62,6 +62,7 @@ export function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, not export async function runCodex(opts: { credentials: Credentials; startedBy?: 'daemon' | 'terminal'; + name?: string; }): Promise { type PermissionMode = 'default' | 'read-only' | 'safe-yolo' | 'yolo'; interface EnhancedMode { @@ -107,6 +108,10 @@ export async function runCodex(opts: { host: os.hostname(), version: packageJson.version, os: os.platform(), + summary: opts.name ? { + text: opts.name, + updatedAt: Date.now() + } : undefined, machineId: machineId, homeDir: os.homedir(), happyHomeDir: configuration.happyHomeDir, diff --git a/src/index.ts b/src/index.ts index c0293eb2..b74bc479 100644 --- a/src/index.ts +++ b/src/index.ts @@ -82,18 +82,21 @@ import { execFileSync } from 'node:child_process' try { const { runCodex } = await import('@/codex/runCodex'); - // Parse startedBy argument + // Parse startedBy and name arguments let startedBy: 'daemon' | 'terminal' | undefined = undefined; + let name: string | undefined = undefined; for (let i = 1; i < args.length; i++) { if (args[i] === '--started-by') { startedBy = args[++i] as 'daemon' | 'terminal'; + } else if (args[i] === '--name') { + name = args[++i]; } } - + const { credentials } = await authAndSetupMachineIfNeeded(); - await runCodex({credentials, startedBy}); + await runCodex({credentials, startedBy, name}); // Do not force exit here; allow instrumentation to show lingering handles } catch (error) { console.error(chalk.red('Error:'), error instanceof Error ? error.message : 'Unknown error') @@ -271,6 +274,8 @@ ${chalk.bold('To clean up runaway processes:')} Use ${chalk.cyan('happy doctor c unknownArgs.push('--dangerously-skip-permissions') } else if (arg === '--started-by') { options.startedBy = args[++i] as 'daemon' | 'terminal' + } else if (arg === '--name') { + options.name = args[++i] } else { // Pass unknown arguments through to claude unknownArgs.push(arg) @@ -303,11 +308,15 @@ ${chalk.bold('Usage:')} ${chalk.bold('Examples:')} happy Start session - happy --yolo Start with bypassing permissions + happy --name "Project" Set custom session name (shows in mobile app) + happy --yolo Start with bypassing permissions happy sugar for --dangerously-skip-permissions happy auth login --force Authenticate happy doctor Run diagnostics +${chalk.bold('Happy-specific options:')} + --name Set session title (avoids Claude roundtrip) + ${chalk.bold('Happy supports ALL Claude options!')} Use any claude flag with happy as you would with claude. Our favorite: