mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-17 17:56:46 +00:00
164 lines
4.5 KiB
Python
164 lines
4.5 KiB
Python
|
|
"""
|
||
|
|
Command Installation
|
||
|
|
|
||
|
|
Installs SuperClaude slash commands to ~/.claude/commands/ directory.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import List, Tuple
|
||
|
|
import shutil
|
||
|
|
|
||
|
|
|
||
|
|
def install_commands(
|
||
|
|
target_path: Path = None,
|
||
|
|
force: bool = False
|
||
|
|
) -> Tuple[bool, str]:
|
||
|
|
"""
|
||
|
|
Install all SuperClaude commands to Claude Code
|
||
|
|
|
||
|
|
Args:
|
||
|
|
target_path: Target installation directory (default: ~/.claude/commands)
|
||
|
|
force: Force reinstall if commands exist
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Tuple of (success: bool, message: str)
|
||
|
|
"""
|
||
|
|
# Default to ~/.claude/commands
|
||
|
|
if target_path is None:
|
||
|
|
target_path = Path.home() / ".claude" / "commands"
|
||
|
|
|
||
|
|
# Get command source directory
|
||
|
|
command_source = _get_commands_source()
|
||
|
|
|
||
|
|
if not command_source or not command_source.exists():
|
||
|
|
return False, f"Command source directory not found: {command_source}"
|
||
|
|
|
||
|
|
# Create target directory
|
||
|
|
target_path.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
# Get all command files
|
||
|
|
command_files = list(command_source.glob("*.md"))
|
||
|
|
|
||
|
|
if not command_files:
|
||
|
|
return False, f"No command files found in {command_source}"
|
||
|
|
|
||
|
|
installed_commands = []
|
||
|
|
skipped_commands = []
|
||
|
|
failed_commands = []
|
||
|
|
|
||
|
|
for command_file in command_files:
|
||
|
|
target_file = target_path / command_file.name
|
||
|
|
command_name = command_file.stem
|
||
|
|
|
||
|
|
# Check if already exists
|
||
|
|
if target_file.exists() and not force:
|
||
|
|
skipped_commands.append(command_name)
|
||
|
|
continue
|
||
|
|
|
||
|
|
# Copy command file
|
||
|
|
try:
|
||
|
|
shutil.copy2(command_file, target_file)
|
||
|
|
installed_commands.append(command_name)
|
||
|
|
except Exception as e:
|
||
|
|
failed_commands.append(f"{command_name}: {e}")
|
||
|
|
|
||
|
|
# Build result message
|
||
|
|
messages = []
|
||
|
|
|
||
|
|
if installed_commands:
|
||
|
|
messages.append(f"✅ Installed {len(installed_commands)} commands:")
|
||
|
|
for cmd in installed_commands:
|
||
|
|
messages.append(f" - /{cmd}")
|
||
|
|
|
||
|
|
if skipped_commands:
|
||
|
|
messages.append(f"\n⚠️ Skipped {len(skipped_commands)} existing commands (use --force to reinstall):")
|
||
|
|
for cmd in skipped_commands:
|
||
|
|
messages.append(f" - /{cmd}")
|
||
|
|
|
||
|
|
if failed_commands:
|
||
|
|
messages.append(f"\n❌ Failed to install {len(failed_commands)} commands:")
|
||
|
|
for fail in failed_commands:
|
||
|
|
messages.append(f" - {fail}")
|
||
|
|
|
||
|
|
if not installed_commands and not skipped_commands:
|
||
|
|
return False, "No commands were installed"
|
||
|
|
|
||
|
|
messages.append(f"\n📁 Installation directory: {target_path}")
|
||
|
|
messages.append("\n💡 Tip: Restart Claude Code to use the new commands")
|
||
|
|
|
||
|
|
success = len(failed_commands) == 0
|
||
|
|
return success, "\n".join(messages)
|
||
|
|
|
||
|
|
|
||
|
|
def _get_commands_source() -> Path:
|
||
|
|
"""
|
||
|
|
Get source directory for commands
|
||
|
|
|
||
|
|
Commands are stored in:
|
||
|
|
plugins/superclaude/commands/
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Path to commands source directory
|
||
|
|
"""
|
||
|
|
# Get package root (src/superclaude/)
|
||
|
|
package_root = Path(__file__).resolve().parent.parent
|
||
|
|
|
||
|
|
# Check if running from source checkout
|
||
|
|
# package_root = src/superclaude/
|
||
|
|
# repo_root = src/superclaude/../../ = project root
|
||
|
|
repo_root = package_root.parent.parent
|
||
|
|
|
||
|
|
# Try plugins/superclaude/commands/ in project root
|
||
|
|
commands_dir = repo_root / "plugins" / "superclaude" / "commands"
|
||
|
|
|
||
|
|
if commands_dir.exists():
|
||
|
|
return commands_dir
|
||
|
|
|
||
|
|
# If not found, try relative to package (for installed package)
|
||
|
|
# This would be in site-packages/superclaude/commands/
|
||
|
|
alt_commands_dir = package_root / "commands"
|
||
|
|
if alt_commands_dir.exists():
|
||
|
|
return alt_commands_dir
|
||
|
|
|
||
|
|
return commands_dir # Return first candidate even if doesn't exist
|
||
|
|
|
||
|
|
|
||
|
|
def list_available_commands() -> List[str]:
|
||
|
|
"""
|
||
|
|
List all available commands
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
List of command names
|
||
|
|
"""
|
||
|
|
command_source = _get_commands_source()
|
||
|
|
|
||
|
|
if not command_source.exists():
|
||
|
|
return []
|
||
|
|
|
||
|
|
commands = []
|
||
|
|
for file in command_source.glob("*.md"):
|
||
|
|
if file.stem != "README":
|
||
|
|
commands.append(file.stem)
|
||
|
|
|
||
|
|
return sorted(commands)
|
||
|
|
|
||
|
|
|
||
|
|
def list_installed_commands() -> List[str]:
|
||
|
|
"""
|
||
|
|
List installed commands in ~/.claude/commands/
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
List of installed command names
|
||
|
|
"""
|
||
|
|
commands_dir = Path.home() / ".claude" / "commands"
|
||
|
|
|
||
|
|
if not commands_dir.exists():
|
||
|
|
return []
|
||
|
|
|
||
|
|
installed = []
|
||
|
|
for file in commands_dir.glob("*.md"):
|
||
|
|
if file.stem != "README":
|
||
|
|
installed.append(file.stem)
|
||
|
|
|
||
|
|
return sorted(installed)
|