mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-04 02:20:42 +08:00
- 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>
165 lines
4.5 KiB
Python
Executable File
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()
|