@@ -275,6 +275,31 @@ export async function handleRun(args: string[], io: CliIO): Promise<number> {
275275 }
276276 }
277277
278+ // #3350: Preflight check — verify Claude Code is authenticated before creating session.
279+ try {
280+ const { execFile } = await import ( 'node:child_process' ) ;
281+ const claudeCheck = await new Promise < { stdout : string ; stderr : string ; code : number } > ( ( resolve , reject ) => {
282+ const proc = execFile ( 'claude' , [ '-p' , '/version' ] , { timeout : 5000 } , ( err , stdout , stderr ) => {
283+ resolve ( { stdout : stdout ?? '' , stderr : stderr ?? '' , code : err ? ( err as any ) . code ?? 1 : 0 } ) ;
284+ } ) ;
285+ } ) ;
286+ if ( claudeCheck . stderr . includes ( 'Not logged in' ) || claudeCheck . stderr . includes ( 'Please run /login' ) || claudeCheck . code === 1 ) {
287+ writeLine ( io . stderr , '' ) ;
288+ writeLine ( io . stderr , ' ❌ Claude Code is not authenticated.' ) ;
289+ writeLine ( io . stderr , '' ) ;
290+ writeLine ( io . stderr , ' Aegis requires Claude Code to be logged in before creating sessions.' ) ;
291+ writeLine ( io . stderr , '' ) ;
292+ writeLine ( io . stderr , ' To fix this:' ) ;
293+ writeLine ( io . stderr , ' 1. Run: claude' ) ;
294+ writeLine ( io . stderr , ' 2. Follow the login prompts, or' ) ;
295+ writeLine ( io . stderr , ' 3. Set ANTHROPIC_API_KEY=<your-key> in your environment' ) ;
296+ writeLine ( io . stderr , '' ) ;
297+ return 1 ;
298+ }
299+ } catch {
300+ // claude CLI not found — let session creation proceed and fail naturally
301+ }
302+
278303 // Create session
279304 const headers : Record < string , string > = { 'Content-Type' : 'application/json' } ;
280305 if ( authToken ) headers [ 'Authorization' ] = `Bearer ${ authToken } ` ;
0 commit comments