From 81dbc4bc160497d245608163bade319fc3f099cd Mon Sep 17 00:00:00 2001 From: mantarayDigital Date: Thu, 8 Jan 2026 07:19:51 +0200 Subject: [PATCH 1/3] fix: Update start.sh to use correct Claude CLI auth detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous credential check looked for ~/.claude/.credentials.json, which no longer exists in recent versions of Claude CLI. This caused the script to incorrectly prompt users to login even when they were already authenticated. Changes: - Remove check for non-existent .credentials.json file - Check for ~/.claude directory existence instead - Always remind users about 'claude login' since we can't verify auth status without making an API call - If ~/.claude doesn't exist, pause and warn (but allow continuing) - Add explanatory comments about the limitation The new approach is honest about what we can and can't verify: - We CAN check if the CLI is installed (command -v claude) - We CAN check if ~/.claude directory exists (CLI has been run) - We CANNOT verify actual auth status without an API call 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- start.sh | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/start.sh b/start.sh index d90c097..c54caee 100644 --- a/start.sh +++ b/start.sh @@ -20,40 +20,18 @@ fi echo "[OK] Claude CLI found" -# Check if user has credentials -CLAUDE_CREDS="$HOME/.claude/.credentials.json" -if [ -f "$CLAUDE_CREDS" ]; then - echo "[OK] Claude credentials found" +# Note: Claude CLI no longer stores credentials in ~/.claude/.credentials.json +# We can't reliably check auth status without making an API call, so we just +# verify the CLI is installed and remind the user to login if needed +if [ -d "$HOME/.claude" ]; then + echo "[OK] Claude CLI directory found" + echo " (If you're not logged in, run: claude login)" else - echo "[!] Not authenticated with Claude" + echo "[!] Claude CLI not configured" echo "" - echo "You need to run 'claude login' to authenticate." - echo "This will open a browser window to sign in." + echo "Please run 'claude login' to authenticate before continuing." echo "" - read -p "Would you like to run 'claude login' now? (y/n): " LOGIN_CHOICE - - if [[ "$LOGIN_CHOICE" =~ ^[Yy]$ ]]; then - echo "" - echo "Running 'claude login'..." - echo "Complete the login in your browser, then return here." - echo "" - claude login - - # Check if login succeeded - if [ -f "$CLAUDE_CREDS" ]; then - echo "" - echo "[OK] Login successful!" - else - echo "" - echo "[ERROR] Login failed or was cancelled." - echo "Please try again." - exit 1 - fi - else - echo "" - echo "Please run 'claude login' manually, then try again." - exit 1 - fi + read -p "Press Enter to continue anyway, or Ctrl+C to exit..." fi echo "" From 780cfd343f79948f398b471c602eab9c5af4a6c5 Mon Sep 17 00:00:00 2001 From: mantarayDigital Date: Thu, 8 Jan 2026 07:30:41 +0200 Subject: [PATCH 2/3] feat: Add authentication error handling to start.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add detection and helpful messaging for Claude CLI authentication errors in the Python launcher, complementing the shell script improvements. Changes: - Add is_auth_error() helper with regex patterns for common auth errors - Add print_auth_error_help() for consistent, actionable error messages - Update run_spec_creation() to capture stderr and detect auth failures - Update run_agent() to capture stderr and detect auth failures - Both functions now provide helpful "run claude login" guidance Error patterns detected: - "not logged in" / "not authenticated" - "authentication failed/required/error" - "login required" - "please run claude login" - "unauthorized" - "invalid token/credential/api key" - "expired token/session/credential" This aligns the Python UX with the shell script's non-blocking warning approach while adding proactive error detection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- start.py | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/start.py b/start.py index 0236122..455bc97 100644 --- a/start.py +++ b/start.py @@ -9,6 +9,7 @@ Supports two paths for new projects: """ import os +import re import subprocess import sys from pathlib import Path @@ -24,6 +25,53 @@ from registry import ( register_project, ) +# Patterns that indicate Claude CLI authentication errors +AUTH_ERROR_PATTERNS = [ + r"not\s+logged\s+in", + r"not\s+authenticated", + r"authentication\s+(failed|required|error)", + r"login\s+required", + r"please\s+(run\s+)?['\"]?claude\s+login", + r"unauthorized", + r"invalid\s+(token|credential|api.?key)", + r"expired\s+(token|session|credential)", + r"could\s+not\s+authenticate", + r"sign\s+in\s+(to|required)", +] + + +def is_auth_error(output: str) -> bool: + """ + Check if output contains Claude CLI authentication error messages. + + Args: + output: Combined stdout/stderr from subprocess + + Returns: + True if authentication error detected, False otherwise + """ + if not output: + return False + + output_lower = output.lower() + for pattern in AUTH_ERROR_PATTERNS: + if re.search(pattern, output_lower): + return True + return False + + +def print_auth_error_help() -> None: + """Print helpful message when authentication error is detected.""" + print("\n" + "=" * 50) + print(" Authentication Error Detected") + print("=" * 50) + print("\nClaude CLI requires authentication to work.") + print("\nTo fix this, run:") + print(" claude login") + print("\nThis will open a browser window to sign in.") + print("After logging in, try running this command again.") + print("=" * 50 + "\n") + def check_spec_exists(project_dir: Path) -> bool: """ @@ -203,6 +251,7 @@ def run_spec_creation(project_dir: Path) -> bool: Run Claude Code with /create-spec command to create project specification. The project path is passed as an argument so create-spec knows where to write files. + Captures stderr to detect authentication errors and provide helpful guidance. """ print("\n" + "=" * 50) print(" Project Specification Setup") @@ -217,12 +266,25 @@ def run_spec_creation(project_dir: Path) -> bool: try: # Launch Claude Code with /create-spec command # Project path included in command string so it populates $ARGUMENTS - subprocess.run( + # Capture stderr to detect auth errors while letting stdout flow to terminal + result = subprocess.run( ["claude", f"/create-spec {project_dir}"], check=False, # Don't raise on non-zero exit - cwd=str(Path(__file__).parent) # Run from project root + cwd=str(Path(__file__).parent), # Run from project root + stderr=subprocess.PIPE, + text=True ) + # Check for authentication errors in stderr + stderr_output = result.stderr or "" + if result.returncode != 0 and is_auth_error(stderr_output): + print_auth_error_help() + return False + + # If there was stderr output but not an auth error, show it + if stderr_output.strip() and result.returncode != 0: + print(f"\nClaude CLI error: {stderr_output.strip()}") + # Check if spec was created in project prompts directory if check_spec_exists(project_dir): print("\n" + "-" * 50) @@ -232,6 +294,9 @@ def run_spec_creation(project_dir: Path) -> bool: print("\n" + "-" * 50) print("Spec creation incomplete.") print(f"Please ensure app_spec.txt exists in: {get_project_prompts_dir(project_dir)}") + # If failed with non-zero exit and no spec, might be auth issue + if result.returncode != 0: + print("\nIf you're having authentication issues, try running: claude login") return False except FileNotFoundError: @@ -348,6 +413,8 @@ def create_new_project_flow() -> tuple[str, Path] | None: def run_agent(project_name: str, project_dir: Path) -> None: """Run the autonomous agent with the given project. + Captures stderr to detect authentication errors and provide helpful guidance. + Args: project_name: Name of the project project_dir: Absolute path to the project directory @@ -367,9 +434,28 @@ def run_agent(project_name: str, project_dir: Path) -> None: # Build the command - pass absolute path cmd = [sys.executable, "autonomous_agent_demo.py", "--project-dir", str(project_dir.resolve())] - # Run the agent + # Run the agent with stderr capture to detect auth errors + # stdout goes directly to terminal for real-time output try: - subprocess.run(cmd, check=False) + result = subprocess.run( + cmd, + check=False, + stderr=subprocess.PIPE, + text=True + ) + + # Check for authentication errors + stderr_output = result.stderr or "" + if result.returncode != 0: + if is_auth_error(stderr_output): + print_auth_error_help() + elif stderr_output.strip(): + # Show any other errors + print(f"\nAgent error:\n{stderr_output.strip()}") + # Still hint about auth if exit was unexpected + if "error" in stderr_output.lower() or "exception" in stderr_output.lower(): + print("\nIf this is an authentication issue, try running: claude login") + except KeyboardInterrupt: print("\n\nAgent interrupted. Run again to resume.") From b2c19b0c4c5c1cd78cde454a32bcf25aa8580732 Mon Sep 17 00:00:00 2001 From: mantarayDigital Date: Thu, 8 Jan 2026 07:37:04 +0200 Subject: [PATCH 3/3] feat: Add authentication error handling to UI flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend auth error detection to the web UI flow: server/main.py: - Fix setup_status() endpoint to check ~/.claude directory instead of non-existent .credentials.json file - Add explanatory comments about Claude CLI credential storage changes server/services/process_manager.py: - Add AUTH_ERROR_PATTERNS for detecting auth errors in agent output - Add is_auth_error() helper function - Add AUTH_ERROR_HELP message template - Update _stream_output() to detect auth errors in real-time - Buffer last 20 lines to catch auth errors on process exit - Broadcast clear help message to WebSocket clients when auth fails start_ui.sh: - Add Claude CLI installation check with helpful guidance - Add ~/.claude directory check with login reminder - Non-blocking warnings that don't prevent UI from starting This ensures users get clear, actionable feedback when authentication fails, whether using the CLI or the web UI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- server/main.py | 8 ++-- server/services/process_manager.py | 62 ++++++++++++++++++++++++++++++ start_ui.sh | 21 ++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/server/main.py b/server/main.py index f48e9f2..5efd4af 100644 --- a/server/main.py +++ b/server/main.py @@ -120,9 +120,11 @@ async def setup_status(): # Check for Claude CLI claude_cli = shutil.which("claude") is not None - # Check for credentials file - credentials_path = Path.home() / ".claude" / ".credentials.json" - credentials = credentials_path.exists() + # Check for Claude CLI configuration directory + # Note: Claude CLI no longer stores credentials in ~/.claude/.credentials.json + # The existence of ~/.claude indicates the CLI has been configured + claude_dir = Path.home() / ".claude" + credentials = claude_dir.exists() and claude_dir.is_dir() # Check for Node.js and npm node = shutil.which("node") is not None diff --git a/server/services/process_manager.py b/server/services/process_manager.py index d2b4f0b..31352fc 100644 --- a/server/services/process_manager.py +++ b/server/services/process_manager.py @@ -36,6 +36,47 @@ SENSITIVE_PATTERNS = [ r'aws[_-]?secret[=:][^\s]+', ] +# Patterns that indicate Claude CLI authentication errors +AUTH_ERROR_PATTERNS = [ + r"not\s+logged\s+in", + r"not\s+authenticated", + r"authentication\s+(failed|required|error)", + r"login\s+required", + r"please\s+(run\s+)?['\"]?claude\s+login", + r"unauthorized", + r"invalid\s+(token|credential|api.?key)", + r"expired\s+(token|session|credential)", + r"could\s+not\s+authenticate", + r"sign\s+in\s+(to|required)", +] + + +def is_auth_error(text: str) -> bool: + """Check if text contains Claude CLI authentication error messages.""" + if not text: + return False + text_lower = text.lower() + for pattern in AUTH_ERROR_PATTERNS: + if re.search(pattern, text_lower): + return True + return False + + +AUTH_ERROR_HELP = """ +================================================================================ + AUTHENTICATION ERROR DETECTED +================================================================================ + +Claude CLI requires authentication to work. + +To fix this, run: + claude login + +This will open a browser window to sign in. +After logging in, try starting the agent again. +================================================================================ +""" + def sanitize_output(line: str) -> str: """Remove sensitive information from output lines.""" @@ -185,6 +226,9 @@ class AgentProcessManager: if not self.process or not self.process.stdout: return + auth_error_detected = False + output_buffer = [] # Buffer recent lines for auth error detection + try: loop = asyncio.get_running_loop() while True: @@ -198,6 +242,18 @@ class AgentProcessManager: decoded = line.decode("utf-8", errors="replace").rstrip() sanitized = sanitize_output(decoded) + # Buffer recent output for auth error detection + output_buffer.append(decoded) + if len(output_buffer) > 20: + output_buffer.pop(0) + + # Check for auth errors + if not auth_error_detected and is_auth_error(decoded): + auth_error_detected = True + # Broadcast auth error help message + for help_line in AUTH_ERROR_HELP.strip().split('\n'): + await self._broadcast_output(help_line) + await self._broadcast_output(sanitized) except asyncio.CancelledError: @@ -209,6 +265,12 @@ class AgentProcessManager: if self.process and self.process.poll() is not None: exit_code = self.process.returncode if exit_code != 0 and self.status == "running": + # Check buffered output for auth errors if we haven't detected one yet + if not auth_error_detected: + combined_output = '\n'.join(output_buffer) + if is_auth_error(combined_output): + for help_line in AUTH_ERROR_HELP.strip().split('\n'): + await self._broadcast_output(help_line) self.status = "crashed" elif self.status == "running": self.status = "stopped" diff --git a/start_ui.sh b/start_ui.sh index 644db74..895c4dd 100644 --- a/start_ui.sh +++ b/start_ui.sh @@ -9,6 +9,27 @@ echo " AutoCoder UI" echo "====================================" echo "" +# Check if Claude CLI is installed +if ! command -v claude &> /dev/null; then + echo "[!] Claude CLI not found" + echo "" + echo " The agent requires Claude CLI to work." + echo " Install it from: https://claude.ai/download" + echo "" + echo " After installing, run: claude login" + echo "" +else + echo "[OK] Claude CLI found" + # Note: Claude CLI no longer stores credentials in ~/.claude/.credentials.json + # We can't reliably check auth status without making an API call + if [ -d "$HOME/.claude" ]; then + echo " (If you're not logged in, run: claude login)" + else + echo "[!] Claude CLI not configured - run 'claude login' first" + fi +fi +echo "" + # Check if Python is available if ! command -v python3 &> /dev/null; then if ! command -v python &> /dev/null; then