diff --git a/src/codegen/cli/commands/claude/main.py b/src/codegen/cli/commands/claude/main.py index 4fa0e1e42..9f5b58d35 100644 --- a/src/codegen/cli/commands/claude/main.py +++ b/src/codegen/cli/commands/claude/main.py @@ -184,22 +184,15 @@ def _run_claude_interactive(resolved_org_id: int, no_mcp: bool | None) -> None: # Initialize log watcher manager log_watcher_manager = ClaudeLogWatcherManager() - # Resolve Claude CLI path and test accessibility + # Resolve Claude CLI path (we already checked it exists in the main claude() function) claude_path = resolve_claude_path() if not claude_path: + # This should not happen since we check earlier, but handle it just in case logger.error( - "Claude CLI not found", + "Claude CLI not found in interactive mode", extra={"operation": "claude.interactive", "org_id": resolved_org_id, "claude_session_id": session_id, "error_type": "claude_cli_not_found", **_get_session_context()}, ) console.print("❌ Claude Code CLI not found.", style="red") - console.print( - "💡 If you migrated a local install, ensure `~/.claude/local/claude` exists, or add it to PATH.", - style="dim", - ) - console.print( - "💡 Otherwise install globally via npm (e.g., `npm i -g claude`) or run `claude /migrate`.", - style="dim", - ) update_claude_session_status(session_id, "ERROR", resolved_org_id) raise typer.Exit(1) @@ -373,6 +366,24 @@ def claude( }, ) + # Check if Claude is installed for interactive mode (not needed for background mode) + if background is None: + claude_path = resolve_claude_path() + if not claude_path: + logger.error( + "Claude CLI not found", + extra={"operation": "claude.command", "error_type": "claude_cli_not_found", **_get_session_context()}, + ) + # Use t_console (the visible console) for error messages instead of the quiet console + t_console.print("\n[red bold]❌ Claude Code Not Installed[/red bold]") + t_console.print("\n[yellow]Claude Code CLI is not installed or cannot be found.[/yellow]") + t_console.print("\n[bold]To install Claude Code:[/bold]") + t_console.print(" • Install globally: [cyan]npm install -g @anthropic-ai/claude-code[/cyan]") + t_console.print(" • Or run: [cyan]claude /migrate-installer[/cyan] for local installation") + t_console.print("\n[dim]If you migrated a local install, ensure ~/.claude/local/claude exists[/dim]") + t_console.print("[dim]or add it to your PATH.[/dim]") + raise typer.Exit(1) + # Resolve org_id early for session management resolved_org_id = resolve_org_id(org_id) if resolved_org_id is None: diff --git a/src/codegen/cli/tui/app.py b/src/codegen/cli/tui/app.py index b0f6acfc9..c602bd116 100644 --- a/src/codegen/cli/tui/app.py +++ b/src/codegen/cli/tui/app.py @@ -570,9 +570,26 @@ def _display_dashboard_tab(self): def _display_claude_tab(self): """Display the Claude Code interface tab.""" - print(" \033[37m→ Run Claude Code\033[0m") - print() - print("Press Enter to launch Claude Code with session tracking.") + # Check if Claude Code is installed + from codegen.cli.commands.claude.utils import resolve_claude_path + + claude_path = resolve_claude_path() + if not claude_path: + # Display error message when Claude is not installed + print(" \033[31m✗ Claude Code Not Installed\033[0m") + print() + print("\033[33m⚠ Claude Code CLI is not installed or cannot be found.\033[0m") + print() + print("To install Claude Code:") + print(" • Install globally: \033[36mnpm install -g @anthropic-ai/claude-code\033[0m") + print(" • Or run: \033[36mclaude /migrate-installer\033[0m for local installation") + print() + print("Once installed, restart this CLI to use Claude Code.") + else: + print(" \033[37m→ Run Claude Code\033[0m") + print() + print("Press Enter to launch Claude Code with session tracking.") + # The claude tab main content area should be a fixed 10 lines self._pad_to_lines(7) @@ -892,6 +909,15 @@ def _handle_dashboard_tab_keypress(self, key: str): def _handle_claude_tab_keypress(self, key: str): """Handle keypresses in the claude tab.""" if key == "\r" or key == "\n": # Enter - run Claude Code + # Check if Claude is installed before attempting to run + from codegen.cli.commands.claude.utils import resolve_claude_path + + claude_path = resolve_claude_path() + if not claude_path: + # Claude is not installed, don't try to launch + logger.warning("Attempted to launch Claude Code but it's not installed", extra={"operation": "tui.launch_claude", "error": "not_installed"}) + return + self._run_claude_code() def _run_claude_code(self):