Files
myclaude/skills/do/install.py
cexll 74e4d181c2 feat: add worktree support and refactor do skill to Python
- Add worktree module for git worktree management
- Refactor do skill scripts from shell to Python for better maintainability
- Add install.py for do skill installation
- Update stop-hook to Python implementation
- Enhance executor with additional configuration options
- Update CLAUDE.md with first-principles thinking guidelines

Generated with SWE-Agent.ai

Co-Authored-By: SWE-Agent.ai <noreply@swe-agent.ai>
2026-02-03 21:58:08 +08:00

165 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Install/uninstall do skill to ~/.claude/skills/do"""
import argparse
import json
import os
import shutil
import sys
from pathlib import Path
SKILL_NAME = "do"
HOOK_PATH = "~/.claude/skills/do/hooks/stop-hook.py"
MODELS_JSON_TEMPLATE = {
"agents": {
"code-explorer": {
"backend": "claude",
"model": "claude-sonnet-4-5-20250929"
},
"code-architect": {
"backend": "claude",
"model": "claude-sonnet-4-5-20250929"
},
"code-reviewer": {
"backend": "claude",
"model": "claude-sonnet-4-5-20250929"
}
}
}
def get_settings_path() -> Path:
return Path.home() / ".claude" / "settings.json"
def load_settings() -> dict:
path = get_settings_path()
if path.exists():
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
return {}
def save_settings(settings: dict):
path = get_settings_path()
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
json.dump(settings, f, indent=2)
def add_hook(settings: dict) -> dict:
hook_command = str(Path(HOOK_PATH).expanduser())
hook_entry = {
"type": "command",
"command": f"python3 {hook_command}"
}
if "hooks" not in settings:
settings["hooks"] = {}
if "Stop" not in settings["hooks"]:
settings["hooks"]["Stop"] = []
stop_hooks = settings["hooks"]["Stop"]
for item in stop_hooks:
if "hooks" in item:
for h in item["hooks"]:
if "stop-hook" in h.get("command", "") and "do" in h.get("command", ""):
h["command"] = f"python3 {hook_command}"
return settings
stop_hooks.append({"hooks": [hook_entry]})
return settings
def remove_hook(settings: dict) -> dict:
if "hooks" not in settings or "Stop" not in settings["hooks"]:
return settings
stop_hooks = settings["hooks"]["Stop"]
new_stop_hooks = []
for item in stop_hooks:
if "hooks" in item:
filtered = [h for h in item["hooks"]
if "stop-hook" not in h.get("command", "")
or "do" not in h.get("command", "")]
if filtered:
item["hooks"] = filtered
new_stop_hooks.append(item)
else:
new_stop_hooks.append(item)
settings["hooks"]["Stop"] = new_stop_hooks
if not settings["hooks"]["Stop"]:
del settings["hooks"]["Stop"]
if not settings["hooks"]:
del settings["hooks"]
return settings
def install_models_json():
"""Install ~/.codeagent/models.json if not exists"""
path = Path.home() / ".codeagent" / "models.json"
if path.exists():
print(f"{path} already exists, skipping")
return
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
json.dump(MODELS_JSON_TEMPLATE, f, indent=2)
print(f"✓ Created {path}")
def install():
src = Path(__file__).parent.resolve()
dest = Path.home() / ".claude" / "skills" / SKILL_NAME
dest.mkdir(parents=True, exist_ok=True)
exclude = {".git", "__pycache__", ".DS_Store", "install.py"}
for item in src.iterdir():
if item.name in exclude:
continue
target = dest / item.name
if target.exists():
if target.is_dir():
shutil.rmtree(target)
else:
target.unlink()
if item.is_dir():
shutil.copytree(item, target)
else:
shutil.copy2(item, target)
settings = load_settings()
settings = add_hook(settings)
save_settings(settings)
install_models_json()
print(f"✓ Installed to {dest}")
print(f"✓ Hook added to settings.json")
def uninstall():
dest = Path.home() / ".claude" / "skills" / SKILL_NAME
settings = load_settings()
settings = remove_hook(settings)
save_settings(settings)
print(f"✓ Hook removed from settings.json")
if dest.exists():
shutil.rmtree(dest)
print(f"✓ Removed {dest}")
else:
print(f"{dest} not found")
def main():
parser = argparse.ArgumentParser(description="Install/uninstall do skill")
parser.add_argument("--uninstall", "-u", action="store_true", help="Uninstall the skill")
args = parser.parse_args()
if args.uninstall:
uninstall()
else:
install()
if __name__ == "__main__":
main()