From 584175351ae2f3ceb04b5766e7de1cfcdc4f6c1a Mon Sep 17 00:00:00 2001 From: Zhiqiang ZHOU Date: Tue, 9 Sep 2025 13:39:00 -0700 Subject: [PATCH 1/2] fix: support Claude CLI installed via migrate-installer After running `claude migrate-installer`, the Claude executable is moved from PATH to ~/.claude/local/claude. This change updates check_tool() to prioritize checking this local path before falling back to PATH lookup. Fixes: #123 Co-Authored-By: Claude --- src/specify_cli/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index aa3cf3c83..7991a64f1 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -332,6 +332,17 @@ def run_command(cmd: list[str], check_return: bool = True, capture: bool = False def check_tool(tool: str, install_hint: str) -> bool: """Check if a tool is installed.""" + + # Special handling for Claude CLI after `claude migrate-installer` + # See: https://github.com/github/spec-kit/issues/123 + # The migrate-installer command REMOVES the original executable from PATH + # and creates an alias at ~/.claude/local/claude instead + # This path should be prioritized over other claude executables in PATH + if tool == "claude": + claude_local_path = Path.home() / ".claude" / "local" / "claude" + if claude_local_path.exists() and claude_local_path.is_file(): + return True + if shutil.which(tool): return True else: From 24ba30444eb6ae4cce663b4c00d3fefee523c68e Mon Sep 17 00:00:00 2001 From: Zhiqiang ZHOU Date: Tue, 9 Sep 2025 13:40:54 -0700 Subject: [PATCH 2/2] refactor: extract Claude local path to constant for maintainability Extract the hardcoded Claude CLI local installation path to a constant CLAUDE_LOCAL_PATH to improve maintainability and make it easier to update if the installation path changes in the future. Co-Authored-By: Claude --- src/specify_cli/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index 7991a64f1..0fc068178 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -54,6 +54,9 @@ AI_CHOICES = { "gemini": "Gemini CLI" } +# Claude CLI local installation path after migrate-installer +CLAUDE_LOCAL_PATH = Path.home() / ".claude" / "local" / "claude" + # ASCII Art Banner BANNER = """ ███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗ ██╗ @@ -339,8 +342,7 @@ def check_tool(tool: str, install_hint: str) -> bool: # and creates an alias at ~/.claude/local/claude instead # This path should be prioritized over other claude executables in PATH if tool == "claude": - claude_local_path = Path.home() / ".claude" / "local" / "claude" - if claude_local_path.exists() and claude_local_path.is_file(): + if CLAUDE_LOCAL_PATH.exists() and CLAUDE_LOCAL_PATH.is_file(): return True if shutil.which(tool):