mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-14 03:31:58 +08:00
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>
This commit is contained in:
164
skills/do/install.py
Executable file
164
skills/do/install.py
Executable file
@@ -0,0 +1,164 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user