Replace placeholder files with originals from system
Found and copied original files from ~/.claude installation: - hooks/ - Original Qwen and Ralph hook scripts with full functionality - commands/ - Original command definitions (brainstorm, write-plan, execute-plan) - bin/ralphloop - Original 223-line Python wrapper (6,290 bytes) - scripts/sync-agents.sh - Original sync script with GitHub/Gitea backup - templates/ - Original config templates from working installation - plugins/ - Original comprehensive plugin README Files sourced from: - ~/.claude/skills/skills/hooks/ - ~/.claude/skills/skills/commands/ - ~/.claude/skills/skills/templates/ - /home/uroma/obsidian-web-interface/bin/ralphloop - ~/.claude/agents/sync-agents.sh These are the production files from the working Claude Code installation, replacing the placeholder files I created earlier. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
425
bin/ralphloop
425
bin/ralphloop
@@ -1,282 +1,223 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
RalphLoop - Ralph Orchestrator Wrapper for Claude Code
|
RalphLoop - "Tackle Until Solved" Autonomous Agent Loop
|
||||||
|
|
||||||
This wrapper integrates Ralph Orchestrator with Claude Code skills,
|
Integration of Ralph Orchestrator with Claude Code CLI.
|
||||||
providing autonomous "Tackle Until Solved" capabilities.
|
This script runs an autonomous agent loop that continues until the task is complete.
|
||||||
|
|
||||||
Environment Variables:
|
|
||||||
RALPH_AGENT Agent to use (claude|gemini|kiro|q|auto)
|
|
||||||
RALPH_MAX_ITERATIONS Maximum iterations (default: 100)
|
|
||||||
RALPH_MAX_RUNTIME Maximum runtime in seconds (default: 14400)
|
|
||||||
RALPH_VERBOSE Enable verbose output (default: false)
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
ralphloop "Design a microservices architecture"
|
./ralphloop "Your task description here"
|
||||||
ralphloop --agent claude --max-iterations 50 "Implement auth"
|
./ralphloop -i task.md
|
||||||
|
./ralphloop --agent claude --max-iterations 50
|
||||||
|
|
||||||
|
Environment Variables:
|
||||||
|
ANTHROPIC_API_KEY Required for Claude agent
|
||||||
|
RALPH_AGENT Override agent selection (claude, gemini, etc.)
|
||||||
|
RALPH_MAX_ITERATIONS Override max iterations (default: 100)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
|
||||||
import argparse
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
DEFAULT_AGENT = os.getenv("RALPH_AGENT", "claude")
|
DEFAULT_AGENT = "claude"
|
||||||
DEFAULT_MAX_ITERATIONS = int(os.getenv("RALPH_MAX_ITERATIONS", 100))
|
DEFAULT_MAX_ITERATIONS = 100
|
||||||
DEFAULT_MAX_RUNTIME = int(os.getenv("RALPH_MAX_RUNTIME", 14400))
|
DEFAULT_MAX_RUNTIME = 14400 # 4 hours
|
||||||
VERBOSE = os.getenv("RALPH_VERBOSE", "false").lower() == "true"
|
|
||||||
|
|
||||||
# Ralph directory
|
# Path to Ralph in venv
|
||||||
RALPH_DIR = Path(".ralph")
|
SCRIPT_DIR = Path(__file__).parent.parent
|
||||||
STATE_FILE = RALPH_DIR / "state.json"
|
VENV_BIN = SCRIPT_DIR / ".venv" / "bin"
|
||||||
PROMPT_FILE = RALPH_DIR / "PROMPT.md"
|
RALPH_CMD = str(VENV_BIN / "ralph")
|
||||||
CONFIG_FILE = RALPH_DIR / "ralph.yml"
|
|
||||||
ITERATIONS_DIR = RALPH_DIR / "iterations"
|
|
||||||
|
|
||||||
|
def check_dependencies():
|
||||||
def setup_ralph_directory():
|
"""Check if Ralph Orchestrator is available."""
|
||||||
"""Create .ralph directory structure."""
|
|
||||||
RALPH_DIR.mkdir(exist_ok=True)
|
|
||||||
ITERATIONS_DIR.mkdir(exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
def load_state():
|
|
||||||
"""Load current Ralph state."""
|
|
||||||
if STATE_FILE.exists():
|
|
||||||
with open(STATE_FILE, "r") as f:
|
|
||||||
return json.load(f)
|
|
||||||
return {
|
|
||||||
"iteration": 0,
|
|
||||||
"status": "not_started",
|
|
||||||
"started_at": None,
|
|
||||||
"completed_at": None,
|
|
||||||
"last_error": None
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def save_state(state):
|
|
||||||
"""Save Ralph state."""
|
|
||||||
with open(STATE_FILE, "w") as f:
|
|
||||||
json.dump(state, f, indent=2)
|
|
||||||
|
|
||||||
|
|
||||||
def create_prompt(task, agent, max_iterations, max_runtime):
|
|
||||||
"""Create PROMPT.md with task and success criteria."""
|
|
||||||
prompt = f"""# RalphLoop Task
|
|
||||||
|
|
||||||
## Task
|
|
||||||
{task}
|
|
||||||
|
|
||||||
## Success Criteria
|
|
||||||
- Task fully analyzed and understood
|
|
||||||
- All requirements addressed
|
|
||||||
- Implementation/design complete
|
|
||||||
- Quality standards met
|
|
||||||
- No critical issues remaining
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
- Agent: {agent}
|
|
||||||
- Max Iterations: {max_iterations}
|
|
||||||
- Max Runtime: {max_runtime} seconds ({timedelta(seconds=max_runtime)})
|
|
||||||
- Started: {datetime.now().isoformat()}
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
Run autonomous iterations until all success criteria are met.
|
|
||||||
Update state.json after each iteration.
|
|
||||||
Save final result to iterations/final.md when complete.
|
|
||||||
"""
|
|
||||||
with open(PROMPT_FILE, "w") as f:
|
|
||||||
f.write(prompt)
|
|
||||||
|
|
||||||
|
|
||||||
def create_config(agent, max_iterations, max_runtime):
|
|
||||||
"""Create ralph.yml configuration."""
|
|
||||||
config = f"""# RalphLoop Configuration
|
|
||||||
agent: {agent}
|
|
||||||
max_iterations: {max_iterations}
|
|
||||||
max_runtime: {max_runtime}
|
|
||||||
verbose: {VERBOSE}
|
|
||||||
|
|
||||||
# Output
|
|
||||||
iterations_dir: iterations
|
|
||||||
state_file: state.json
|
|
||||||
final_output: iterations/final.md
|
|
||||||
|
|
||||||
# Claude Code Integration
|
|
||||||
skill_path: ~/.claude/skills/ralph
|
|
||||||
brainstorming_skill: ~/.claude/skills/brainstorming
|
|
||||||
"""
|
|
||||||
with open(CONFIG_FILE, "w") as f:
|
|
||||||
f.write(config)
|
|
||||||
|
|
||||||
|
|
||||||
def run_ralph_iteration(task, iteration, agent):
|
|
||||||
"""Run a single Ralph iteration."""
|
|
||||||
iteration_file = ITERATIONS_DIR / f"{iteration:03d}.md"
|
|
||||||
|
|
||||||
# Check if ralph-orchestrator is installed
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["ralph", "--agent", agent, "--prompt", task],
|
[RALPH_CMD, "run", "-h"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=300
|
timeout=5
|
||||||
|
)
|
||||||
|
if result.returncode == 0 or "usage:" in result.stdout:
|
||||||
|
return True
|
||||||
|
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Fallback: check if pip package is installed
|
||||||
|
try:
|
||||||
|
import ralph_orchestrator
|
||||||
|
return True
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_ralph_project(task_description=None, task_file=None):
|
||||||
|
"""Create a Ralph project in the current directory."""
|
||||||
|
ralph_dir = Path(".ralph")
|
||||||
|
ralph_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# Create prompt file
|
||||||
|
prompt_file = Path("PROMPT.md")
|
||||||
|
|
||||||
|
if task_file:
|
||||||
|
# Read from file
|
||||||
|
content = Path(task_file).read_text()
|
||||||
|
prompt_file.write_text(content)
|
||||||
|
elif task_description:
|
||||||
|
# Use inline task
|
||||||
|
prompt_file.write_text(f"# Task: {task_description}\n\n<!-- Ralph will continue iterating until task is complete -->\n\n## Success Criteria\n\nThe task is complete when:\n- All requirements are implemented\n- Tests pass\n- Code is documented\n\n<!-- When complete, add <!-- COMPLETE --> marker to this file -->")
|
||||||
|
else:
|
||||||
|
print("Error: Either provide task description or task file")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Create config file
|
||||||
|
config_file = Path("ralph.yml")
|
||||||
|
config = {
|
||||||
|
"agent": os.getenv("RALPH_AGENT", DEFAULT_AGENT),
|
||||||
|
"prompt_file": "PROMPT.md",
|
||||||
|
"max_iterations": int(os.getenv("RALPH_MAX_ITERATIONS", DEFAULT_MAX_ITERATIONS)),
|
||||||
|
"max_runtime": int(os.getenv("RALPH_MAX_RUNTIME", DEFAULT_MAX_RUNTIME)),
|
||||||
|
"verbose": True,
|
||||||
|
"adapters": {
|
||||||
|
"claude": {
|
||||||
|
"enabled": True,
|
||||||
|
"timeout": 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
with open(config_file, "w") as f:
|
||||||
|
yaml.dump(config, f, default_flow_style=False)
|
||||||
|
|
||||||
|
print(f"✅ Ralph project initialized")
|
||||||
|
print(f" Prompt: {prompt_file}")
|
||||||
|
print(f" Config: {config_file}")
|
||||||
|
|
||||||
|
def run_ralph_loop(task=None, task_file=None, agent=None, max_iterations=None, max_runtime=None):
|
||||||
|
"""Run the Ralph autonomous loop."""
|
||||||
|
print("🔄 RalphLoop: 'Tackle Until Solved' Autonomous Agent Loop")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Initialize project
|
||||||
|
create_ralph_project(task, task_file)
|
||||||
|
|
||||||
|
# Build command
|
||||||
|
cmd = [RALPH_CMD, "run"]
|
||||||
|
|
||||||
|
if agent:
|
||||||
|
cmd.extend(["-a", agent])
|
||||||
|
|
||||||
|
if max_iterations:
|
||||||
|
cmd.extend(["-i", str(max_iterations)])
|
||||||
|
|
||||||
|
if max_runtime:
|
||||||
|
cmd.extend(["-t", str(max_runtime)])
|
||||||
|
|
||||||
|
cmd.append("-v") # Verbose output
|
||||||
|
|
||||||
|
print(f"Command: {' '.join(cmd)}")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Run Ralph
|
||||||
|
try:
|
||||||
|
process = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
text=True,
|
||||||
|
bufsize=1
|
||||||
)
|
)
|
||||||
|
|
||||||
output = result.stdout or result.stderr
|
# Stream output
|
||||||
|
for line in process.stdout:
|
||||||
|
print(line, end='', flush=True)
|
||||||
|
|
||||||
with open(iteration_file, "w") as f:
|
process.wait()
|
||||||
f.write(f"""# Iteration {iteration}
|
return process.returncode
|
||||||
|
|
||||||
## Agent: {agent}
|
|
||||||
## Time: {datetime.now().isoformat()}
|
|
||||||
|
|
||||||
## Output
|
|
||||||
{output}
|
|
||||||
|
|
||||||
## Status
|
|
||||||
{'COMPLETE' if result.returncode == 0 else 'IN_PROGRESS'}
|
|
||||||
""")
|
|
||||||
return result.returncode == 0
|
|
||||||
|
|
||||||
except FileNotFoundError:
|
|
||||||
# Ralph not installed, use placeholder
|
|
||||||
with open(iteration_file, "w") as f:
|
|
||||||
f.write(f"""# Iteration {iteration}
|
|
||||||
|
|
||||||
## Agent: {agent}
|
|
||||||
## Time: {datetime.now().isoformat()}
|
|
||||||
|
|
||||||
## Note
|
|
||||||
Ralph Orchestrator not installed. Install with:
|
|
||||||
pip install ralph-orchestrator
|
|
||||||
|
|
||||||
## Task Analysis
|
|
||||||
{task}
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
1. Install Ralph Orchestrator
|
|
||||||
2. Re-run ralphloop command
|
|
||||||
""")
|
|
||||||
return False
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
with open(iteration_file, "w") as f:
|
|
||||||
f.write(f"""# Iteration {iteration}
|
|
||||||
|
|
||||||
## Agent: {agent}
|
|
||||||
## Time: {datetime.now().isoformat()}
|
|
||||||
|
|
||||||
## Status: TIMEOUT
|
|
||||||
|
|
||||||
Iteration exceeded 300 second timeout.
|
|
||||||
""")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def run_ralph(task, agent, max_iterations, max_runtime):
|
|
||||||
"""Run Ralph autonomous loop."""
|
|
||||||
setup_ralph_directory()
|
|
||||||
|
|
||||||
state = load_state()
|
|
||||||
if state["status"] == "completed":
|
|
||||||
print(f"Task already completed at {state['completed_at']}")
|
|
||||||
print(f"See {ITERATIONS_DIR / 'final.md'} for results")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Initialize
|
|
||||||
state["status"] = "running"
|
|
||||||
state["started_at"] = datetime.now().isoformat()
|
|
||||||
save_state(state)
|
|
||||||
|
|
||||||
create_prompt(task, agent, max_iterations, max_runtime)
|
|
||||||
create_config(agent, max_iterations, max_runtime)
|
|
||||||
|
|
||||||
start_time = datetime.now()
|
|
||||||
completed = False
|
|
||||||
|
|
||||||
for iteration in range(1, max_iterations + 1):
|
|
||||||
# Check runtime
|
|
||||||
elapsed = (datetime.now() - start_time).total_seconds()
|
|
||||||
if elapsed > max_runtime:
|
|
||||||
print(f"Max runtime ({max_runtime}s) exceeded")
|
|
||||||
break
|
|
||||||
|
|
||||||
if VERBOSE:
|
|
||||||
print(f"[Ralph] Iteration {iteration}/{max_iterations}")
|
|
||||||
|
|
||||||
state["iteration"] = iteration
|
|
||||||
save_state(state)
|
|
||||||
|
|
||||||
# Run iteration
|
|
||||||
if run_ralph_iteration(task, iteration, agent):
|
|
||||||
completed = True
|
|
||||||
break
|
|
||||||
|
|
||||||
# Finalize
|
|
||||||
state["status"] = "completed" if completed else "max_iterations_reached"
|
|
||||||
state["completed_at"] = datetime.now().isoformat()
|
|
||||||
save_state(state)
|
|
||||||
|
|
||||||
# Create final output
|
|
||||||
final_file = ITERATIONS_DIR / "final.md"
|
|
||||||
with open(final_file, "w") as f:
|
|
||||||
f.write(f"""# RalphLoop Final Result
|
|
||||||
|
|
||||||
## Task
|
|
||||||
{task}
|
|
||||||
|
|
||||||
## Agent: {agent}
|
|
||||||
## Iterations: {state['iteration']}
|
|
||||||
## Status: {state['status']}
|
|
||||||
## Started: {state['started_at']}
|
|
||||||
## Completed: {state['completed_at']}
|
|
||||||
|
|
||||||
## Result
|
|
||||||
{'Task completed successfully!' if completed else 'Max iterations reached. Manual review needed.'}
|
|
||||||
|
|
||||||
## Output Files
|
|
||||||
- iterations/001.md through iterations/{iteration:03d}.md
|
|
||||||
- state.json - Progress tracking
|
|
||||||
- ralph.yml - Configuration
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
{'Implement the solution from the final iteration.' if completed else 'Review iterations and continue manually or increase max_iterations.'}
|
|
||||||
""")
|
|
||||||
|
|
||||||
print(f"\n[Ralph] {state['status'].upper()}")
|
|
||||||
print(f"[Ralph] Iterations: {state['iteration']}/{max_iterations}")
|
|
||||||
print(f"[Ralph] Output: {final_file}")
|
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n\n⚠️ Interrupted by user")
|
||||||
|
return 130
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="RalphLoop - Ralph Orchestrator Wrapper",
|
description="RalphLoop - Autonomous agent loop for Claude Code CLI",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
epilog=__doc__
|
epilog=__doc__
|
||||||
)
|
)
|
||||||
parser.add_argument("task", help="Task description")
|
|
||||||
parser.add_argument("--agent", default=DEFAULT_AGENT, help="Agent to use")
|
parser.add_argument(
|
||||||
parser.add_argument("--max-iterations", type=int, default=DEFAULT_MAX_ITERATIONS)
|
"task",
|
||||||
parser.add_argument("--max-runtime", type=int, default=DEFAULT_MAX_RUNTIME)
|
nargs="?",
|
||||||
parser.add_argument("--verbose", action="store_true")
|
help="Task description (inline)"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-i", "--input",
|
||||||
|
dest="task_file",
|
||||||
|
help="Read task from file"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-a", "--agent",
|
||||||
|
choices=["claude", "kiro", "q", "gemini", "acp", "auto"],
|
||||||
|
default=os.getenv("RALPH_AGENT", DEFAULT_AGENT),
|
||||||
|
help="AI agent to use"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--max-iterations",
|
||||||
|
type=int,
|
||||||
|
default=int(os.getenv("RALPH_MAX_ITERATIONS", DEFAULT_MAX_ITERATIONS)),
|
||||||
|
help="Maximum iterations"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--max-runtime",
|
||||||
|
type=int,
|
||||||
|
default=int(os.getenv("RALPH_MAX_RUNTIME", DEFAULT_MAX_RUNTIME)),
|
||||||
|
help="Maximum runtime in seconds"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--init-only",
|
||||||
|
action="store_true",
|
||||||
|
help="Only initialize project, don't run"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.verbose:
|
# Check dependencies
|
||||||
global VERBOSE
|
if not check_dependencies():
|
||||||
VERBOSE = True
|
print("⚠️ Ralph Orchestrator not found at:", RALPH_CMD)
|
||||||
|
print("\nTo install:")
|
||||||
|
print(f" .venv/bin/pip install ralph-orchestrator")
|
||||||
|
print("\nFor now, creating project files only...")
|
||||||
|
args.init_only = True
|
||||||
|
|
||||||
run_ralph(
|
# Initialize only mode
|
||||||
|
if args.init_only:
|
||||||
|
create_ralph_project(args.task, args.task_file)
|
||||||
|
print("\n💡 To run the loop later:")
|
||||||
|
print(f" {RALPH_CMD} run")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Run the loop
|
||||||
|
return run_ralph_loop(
|
||||||
task=args.task,
|
task=args.task,
|
||||||
|
task_file=args.task_file,
|
||||||
agent=args.agent,
|
agent=args.agent,
|
||||||
max_iterations=args.max_iterations,
|
max_iterations=args.max_iterations,
|
||||||
max_runtime=args.max_runtime
|
max_runtime=args.max_runtime
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
sys.exit(main() or 0)
|
||||||
|
|||||||
@@ -1,44 +1,6 @@
|
|||||||
# /brainstorm
|
---
|
||||||
|
description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores requirements and design before implementation."
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
Multi-AI brainstorming session with Ralph integration.
|
Invoke the superpowers:brainstorming skill and follow it exactly as presented to you
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
/brainstorm "Design a feature for user authentication"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Launches a collaborative brainstorming session using multiple AI perspectives:
|
|
||||||
- Claude (primary)
|
|
||||||
- Qwen (consultation)
|
|
||||||
- Ralph Orchestrator (autonomous iteration)
|
|
||||||
|
|
||||||
## Modes
|
|
||||||
|
|
||||||
**Direct Mode** (simple tasks):
|
|
||||||
- Quick ideation
|
|
||||||
- Feature exploration
|
|
||||||
- Design discussions
|
|
||||||
|
|
||||||
**Ralph Mode** (complex tasks):
|
|
||||||
- Architecture design
|
|
||||||
- System planning
|
|
||||||
- Multi-phase projects
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
```bash
|
|
||||||
QWEN_CONSULT_MODE=always|delegate|off
|
|
||||||
RALPH_AUTO=true|false
|
|
||||||
QWEN_MAX_ITERATIONS=3
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```
|
|
||||||
/brainstorm "How should we structure the API?"
|
|
||||||
/brainstorm "Design a notification system"
|
|
||||||
/brainstorm "Plan the database schema"
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,52 +1,6 @@
|
|||||||
# /execute-plan
|
---
|
||||||
|
description: Execute plan in batches with review checkpoints
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
Execute a previously created implementation plan.
|
Invoke the superpowers:executing-plans skill and follow it exactly as presented to you
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
/execute-plan
|
|
||||||
/execute-plan my-plan.md
|
|
||||||
/execute-plan --review
|
|
||||||
```
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Executes implementation plans created with `/write-plan`:
|
|
||||||
- Reads plan from `.claude/plans/`
|
|
||||||
- Executes each step in order
|
|
||||||
- Creates checkpoints for rollback
|
|
||||||
- Validates each step completion
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
```
|
|
||||||
--review # Review plan before executing
|
|
||||||
--from=N # Start from step N
|
|
||||||
--to=N # Execute through step N
|
|
||||||
--dry-run # Show what would be done
|
|
||||||
--continue # Continue after error
|
|
||||||
```
|
|
||||||
|
|
||||||
## Execution Process
|
|
||||||
|
|
||||||
1. **Load Plan** - Read and parse plan file
|
|
||||||
2. **Review** (optional) - Show steps and confirm
|
|
||||||
3. **Execute** - Run each step sequentially
|
|
||||||
4. **Validate** - Verify each step completed
|
|
||||||
5. **Checkpoint** - Save progress after each step
|
|
||||||
6. **Report** - Summary of changes
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```
|
|
||||||
/execute-plan # Execute latest plan
|
|
||||||
/execute-plan auth-plan.md # Execute specific plan
|
|
||||||
/execute-plan --review # Review before executing
|
|
||||||
/execute-plan --from=5 # Start from step 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## Checkpoints
|
|
||||||
|
|
||||||
Each step creates a checkpoint in `.claude/plans/<plan-name>.checkpoint/`
|
|
||||||
Use `--continue` to resume from last checkpoint after failure.
|
|
||||||
|
|||||||
@@ -1,40 +1,6 @@
|
|||||||
# /write-plan
|
---
|
||||||
|
description: Create detailed implementation plan with bite-sized tasks
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
Create implementation plans from requirements or specifications.
|
Invoke the superpowers:writing-plans skill and follow it exactly as presented to you
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
/write-plan "Add user authentication with OAuth"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Creates detailed, step-by-step implementation plans including:
|
|
||||||
- Technical approach
|
|
||||||
- File changes needed
|
|
||||||
- Testing strategy
|
|
||||||
- Dependencies
|
|
||||||
- Risks and mitigations
|
|
||||||
|
|
||||||
## Plan Structure
|
|
||||||
|
|
||||||
1. **Summary** - High-level overview
|
|
||||||
2. **Technical Approach** - Architecture decisions
|
|
||||||
3. **Implementation Steps** - Ordered task list
|
|
||||||
4. **Files to Create/Modify** - Specific files
|
|
||||||
5. **Testing Strategy** - Validation approach
|
|
||||||
6. **Dependencies** - Required packages/changes
|
|
||||||
7. **Risks & Mitigations** - Potential issues
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```
|
|
||||||
/write-plan "Implement Stripe subscriptions"
|
|
||||||
/write-plan "Add real-time notifications with WebSockets"
|
|
||||||
/write-plan "Migrate from REST to GraphQL"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Output
|
|
||||||
|
|
||||||
Saves plan to `.claude/plans/` directory for later execution with `/execute-plan`.
|
|
||||||
|
|||||||
88
hooks/QWEN-HOOK-README.md
Normal file
88
hooks/QWEN-HOOK-README.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# Qwen Consultation Hook for Claude Code
|
||||||
|
|
||||||
|
Allows Claude Code to consult with the local Qwen installation (`/usr/local/bin/qwen`) for assistance with tasks.
|
||||||
|
|
||||||
|
## Files Created
|
||||||
|
|
||||||
|
- `/home/uroma/.claude/hooks/qwen-consult.sh` - Main hook script
|
||||||
|
- `/home/uroma/.claude/hooks/hooks.json` - Updated with Qwen hook
|
||||||
|
- `/home/uroma/.claude/hooks.json` - Updated with Qwen hook
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The hook behavior is controlled via environment variables:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `QWEN_CONSULT_MODE` | `off` | When to consult Qwen: `off`, `delegate`, or `always` |
|
||||||
|
| `QWEN_MODEL` | (default) | Optional: specify Qwen model to use |
|
||||||
|
| `QWEN_MAX_ITERATIONS` | `30` | Max iterations for Qwen execution |
|
||||||
|
|
||||||
|
## Usage Modes
|
||||||
|
|
||||||
|
### 1. Off Mode (Default)
|
||||||
|
```bash
|
||||||
|
export QWEN_CONSULT_MODE=off
|
||||||
|
```
|
||||||
|
Qwen is never consulted. Hook is disabled.
|
||||||
|
|
||||||
|
### 2. Delegate Mode
|
||||||
|
```bash
|
||||||
|
export QWEN_CONSULT_MODE=delegate
|
||||||
|
```
|
||||||
|
Qwen is consulted when you use keywords like:
|
||||||
|
- "consult qwen"
|
||||||
|
- "ask qwen"
|
||||||
|
- "delegate to qwen"
|
||||||
|
- "get a second opinion"
|
||||||
|
- "alternative approach"
|
||||||
|
|
||||||
|
### 3. Always Mode
|
||||||
|
```bash
|
||||||
|
export QWEN_CONSULT_MODE=always
|
||||||
|
```
|
||||||
|
Qwen is consulted for every request.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Enable delegate mode in current session
|
||||||
|
```bash
|
||||||
|
export QWEN_CONSULT_MODE=delegate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use with a specific model
|
||||||
|
```bash
|
||||||
|
export QWEN_CONSULT_MODE=delegate
|
||||||
|
export QWEN_MODEL=qwen2.5-coder-32b-instruct
|
||||||
|
```
|
||||||
|
|
||||||
|
### Make permanent (add to ~/.bashrc)
|
||||||
|
```bash
|
||||||
|
echo 'export QWEN_CONSULT_MODE=delegate' >> ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring Qwen
|
||||||
|
|
||||||
|
When Qwen is triggered, it runs in the background. You can monitor it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View Qwen output in real-time
|
||||||
|
tail -f ~/.claude/qwen-output.log
|
||||||
|
|
||||||
|
# Check if Qwen is running
|
||||||
|
ps aux | grep qwen
|
||||||
|
|
||||||
|
# Stop Qwen manually
|
||||||
|
kill $(cat ~/.claude/qwen.lock)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hook Event
|
||||||
|
|
||||||
|
This hook triggers on `UserPromptSubmit` - every time you submit a prompt to Claude Code.
|
||||||
|
|
||||||
|
## State Files
|
||||||
|
|
||||||
|
- `~/.claude/qwen-consult.md` - Current consultation state
|
||||||
|
- `~/.claude/qwen-output.log` - Qwen execution output
|
||||||
|
- `~/.claude/qwen.lock` - PID file for running Qwen process
|
||||||
|
- `~/.claude/qwen-consult.log` - Consultation trigger log
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Qwen Consultation Wrapper Hook
|
# Simple Qwen Consultation Script
|
||||||
# Trigger: user-prompt
|
# Usage: consult-qwen.sh "your question here"
|
||||||
# Wrapper for Qwen consultation functionality
|
|
||||||
|
|
||||||
# This hook integrates with the brainstorming skill
|
set -euo pipefail
|
||||||
# to provide multi-AI consultation capabilities
|
|
||||||
|
|
||||||
QWEN_MAX_ITERATIONS="${QWEN_MAX_ITERATIONS:-3}"
|
QUESTION="${1:-}"
|
||||||
|
|
||||||
# Delegate to the brainstorming skill when appropriate
|
if [[ -z "$QUESTION" ]]; then
|
||||||
# The actual consultation logic is in the skill
|
echo "Usage: $0 \"your question\""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
exit 0
|
echo "=== Consulting Qwen ==="
|
||||||
|
echo "Question: $QUESTION"
|
||||||
|
echo ""
|
||||||
|
echo "Qwen's Response:"
|
||||||
|
echo "---"
|
||||||
|
|
||||||
|
# Run Qwen with the question
|
||||||
|
echo "$QUESTION" | timeout 30 qwen -p - 2>&1
|
||||||
|
|||||||
@@ -1,11 +1,72 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Demo Qwen Integration Hook
|
# Demo script showing how to use Qwen consultation hook
|
||||||
# Trigger: user-prompt
|
|
||||||
# Demonstrates Qwen AI consultation capabilities
|
|
||||||
|
|
||||||
# This is a demo hook showing how to integrate
|
set -euo pipefail
|
||||||
# Qwen AI for consultation and multi-AI brainstorming
|
|
||||||
|
|
||||||
# The actual implementation is in the multi-ai-brainstorm skill
|
echo "====================================="
|
||||||
|
echo " Qwen Consultation Hook Demo"
|
||||||
|
echo "====================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
exit 0
|
# Step 1: Show current mode
|
||||||
|
echo "1. Current QWEN_CONSULT_MODE: ${QWEN_CONSULT_MODE:-off (default)}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 2: Enable delegate mode
|
||||||
|
echo "2. Enabling delegate mode..."
|
||||||
|
export QWEN_CONSULT_MODE=delegate
|
||||||
|
echo " QWEN_CONSULT_MODE is now: $QWEN_CONSULT_MODE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 3: Trigger consultation with delegate keyword
|
||||||
|
echo "3. Triggering Qwen consultation..."
|
||||||
|
echo " Prompt: 'please consult qwen for advice on bash scripting best practices'"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Clear previous log
|
||||||
|
> ~/.claude/qwen-output.log
|
||||||
|
|
||||||
|
# Trigger the hook
|
||||||
|
echo '{"prompt": "please consult qwen for advice on bash scripting best practices"}' | \
|
||||||
|
/home/uroma/.claude/hooks/qwen-consult.sh 2>&1
|
||||||
|
|
||||||
|
# Wait a moment for Qwen to start
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Step 4: Show Qwen is running
|
||||||
|
echo "4. Checking if Qwen is running..."
|
||||||
|
if [[ -f ~/.claude/qwen.lock ]]; then
|
||||||
|
PID=$(cat ~/.claude/qwen.lock)
|
||||||
|
if kill -0 "$PID" 2>/dev/null; then
|
||||||
|
echo " ✓ Qwen is running (PID: $PID)"
|
||||||
|
else
|
||||||
|
echo " ✗ Qwen process not found"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✗ Qwen lock file not found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 5: Wait for output and show it
|
||||||
|
echo "5. Waiting for Qwen's response (10 seconds)..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "====================================="
|
||||||
|
echo " Qwen's Response:"
|
||||||
|
echo "====================================="
|
||||||
|
tail -n +4 ~/.claude/qwen-output.log
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "====================================="
|
||||||
|
echo " Monitoring Commands:"
|
||||||
|
echo "====================================="
|
||||||
|
echo "View output in real-time:"
|
||||||
|
echo " tail -f ~/.claude/qwen-output.log"
|
||||||
|
echo ""
|
||||||
|
echo "Check if Qwen is running:"
|
||||||
|
echo " ps aux | grep qwen"
|
||||||
|
echo ""
|
||||||
|
echo "Stop Qwen:"
|
||||||
|
echo " kill \$(cat ~/.claude/qwen.lock)"
|
||||||
|
echo ""
|
||||||
|
|||||||
@@ -1,22 +1,163 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Qwen AI Consultation Hook
|
# Qwen Consult Hook - Integration with Qwen Code CLI
|
||||||
# Trigger: user-prompt
|
# Allows Claude Code to consult with local Qwen installation for tasks
|
||||||
# Consults Qwen AI for additional perspectives
|
#
|
||||||
|
# Modes (via QWEN_CONSULT_MODE environment variable):
|
||||||
|
# "always" - Consult Qwen for every request
|
||||||
|
# "delegate" - Only when explicitly asked to delegate/consult
|
||||||
|
# "off" - Disable Qwen consultation (default)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# Set QWEN_CONSULT_MODE environment variable to control behavior
|
||||||
|
# The hook runs Qwen in non-blocking mode and logs output
|
||||||
|
|
||||||
QWEN_MODE="${QWEN_CONSULT_MODE:-delegate}"
|
set -euo pipefail
|
||||||
QWEN_MODEL="${QWEN_MODEL:-qwen-coder-plus}"
|
|
||||||
|
|
||||||
# Only run in delegate or always mode
|
# Configuration
|
||||||
if [ "$QWEN_MODE" != "delegate" ] && [ "$QWEN_MODE" != "always" ]; then
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
|
QWEN_STATE_FILE="$CLAUDE_DIR/qwen-consult.md"
|
||||||
|
QWEN_OUTPUT_LOG="$CLAUDE_DIR/qwen-output.log"
|
||||||
|
QWEN_LOCK_FILE="$CLAUDE_DIR/qwen.lock"
|
||||||
|
|
||||||
|
# Read hook input from stdin
|
||||||
|
HOOK_INPUT=$(cat)
|
||||||
|
USER_PROMPT=$(echo "$HOOK_INPUT" | jq -r '.prompt // empty' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# Fallback: if no JSON input, use first argument
|
||||||
|
if [[ -z "$USER_PROMPT" && $# -gt 0 ]]; then
|
||||||
|
USER_PROMPT="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get Qwen mode (default: off - requires explicit opt-in)
|
||||||
|
QWEN_CONSULT_MODE="${QWEN_CONSULT_MODE:-off}"
|
||||||
|
QWEN_MODEL="${QWEN_MODEL:-}"
|
||||||
|
QWEN_MAX_ITERATIONS="${QWEN_MAX_ITERATIONS:-30}"
|
||||||
|
|
||||||
|
# Exit if consultation is disabled
|
||||||
|
if [[ "$QWEN_CONSULT_MODE" == "off" ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if qwen CLI is available
|
# Check if Qwen is already running
|
||||||
if ! command -v qwen &> /dev/null; then
|
if [[ -f "$QWEN_LOCK_FILE" ]]; then
|
||||||
exit 0
|
LOCK_PID=$(cat "$QWEN_LOCK_FILE" 2>/dev/null || echo "")
|
||||||
|
if [[ -n "$LOCK_PID" ]] && kill -0 "$LOCK_PID" 2>/dev/null; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
rm -f "$QWEN_LOCK_FILE"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Run consultation (would be called by the skill, not here directly)
|
# Keywords that trigger Qwen consultation (in delegate mode)
|
||||||
# This is a placeholder for the hook mechanism
|
DELEGATE_KEYWORDS="consult|qwen|delegate|second opinion|alternative|get.*advice|ask.*qwen"
|
||||||
|
|
||||||
|
# Determine if we should consult Qwen
|
||||||
|
should_consult=false
|
||||||
|
|
||||||
|
case "$QWEN_CONSULT_MODE" in
|
||||||
|
"always")
|
||||||
|
should_consult=true
|
||||||
|
;;
|
||||||
|
"delegate")
|
||||||
|
if echo "$USER_PROMPT" | grep -iqE "$DELEGATE_KEYWORDS"; then
|
||||||
|
should_consult=true
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$should_consult" == true ]]; then
|
||||||
|
# Create state directory
|
||||||
|
mkdir -p "$CLAUDE_DIR"
|
||||||
|
|
||||||
|
# Build Qwen command arguments
|
||||||
|
QWEN_ARGS=()
|
||||||
|
if [[ -n "$QWEN_MODEL" ]]; then
|
||||||
|
QWEN_ARGS+=(-m "$QWEN_MODEL")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prepare prompt for Qwen with context
|
||||||
|
QWEN_PROMPT="You are Qwen, consulted by Claude Code for assistance. The user asks: $USER_PROMPT
|
||||||
|
|
||||||
|
Please provide your analysis, suggestions, or solution. Be concise and actionable."
|
||||||
|
|
||||||
|
# Create state file
|
||||||
|
cat > "$QWEN_STATE_FILE" << EOF
|
||||||
|
# Qwen Consult State
|
||||||
|
# Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
||||||
|
|
||||||
|
**User Request:**
|
||||||
|
$USER_PROMPT
|
||||||
|
|
||||||
|
**Mode:** $QWEN_CONSULT_MODE
|
||||||
|
**Model:** ${QWEN_MODEL:-default}
|
||||||
|
**Timestamp:** $(date -Iseconds)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
This state file was generated by the Qwen consultation hook. Qwen Code CLI
|
||||||
|
is being consulted to provide additional insights on this request.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- Hook: UserPromptSubmit
|
||||||
|
- Trigger mode: $QWEN_CONSULT_MODE
|
||||||
|
- Log file: $QWEN_OUTPUT_LOG
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Qwen is running autonomously in the background. Monitor progress:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# View Qwen output in real-time
|
||||||
|
tail -f ~/.claude/qwen-output.log
|
||||||
|
|
||||||
|
# Check if Qwen is still running
|
||||||
|
ps aux | grep qwen
|
||||||
|
|
||||||
|
# Stop Qwen manually
|
||||||
|
kill \$(cat ~/.claude/qwen.lock)
|
||||||
|
\`\`\`
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Check if Qwen is available
|
||||||
|
if command -v qwen &> /dev/null; then
|
||||||
|
# Create log file
|
||||||
|
touch "$QWEN_OUTPUT_LOG"
|
||||||
|
|
||||||
|
# Start Qwen in background
|
||||||
|
{
|
||||||
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Qwen consultation started"
|
||||||
|
echo "Mode: $QWEN_CONSULT_MODE"
|
||||||
|
echo "Model: ${QWEN_MODEL:-default}"
|
||||||
|
echo "---"
|
||||||
|
} >> "$QWEN_OUTPUT_LOG"
|
||||||
|
|
||||||
|
# Run Qwen in background
|
||||||
|
if [[ ${#QWEN_ARGS[@]} -gt 0 ]]; then
|
||||||
|
nohup qwen "${QWEN_ARGS[@]}" -p "$QWEN_PROMPT" >> "$QWEN_OUTPUT_LOG" 2>&1 &
|
||||||
|
else
|
||||||
|
nohup qwen -p "$QWEN_PROMPT" >> "$QWEN_OUTPUT_LOG" 2>&1 &
|
||||||
|
fi
|
||||||
|
|
||||||
|
QWEN_PID=$!
|
||||||
|
echo "$QWEN_PID" > "$QWEN_LOCK_FILE"
|
||||||
|
|
||||||
|
# Log the consultation
|
||||||
|
{
|
||||||
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Qwen consultation triggered"
|
||||||
|
echo " Mode: $QWEN_CONSULT_MODE"
|
||||||
|
echo " Model: ${QWEN_MODEL:-default}"
|
||||||
|
echo " PID: $QWEN_PID"
|
||||||
|
echo " Log: $QWEN_OUTPUT_LOG"
|
||||||
|
} >> "$CLAUDE_DIR/qwen-consult.log" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Notify user
|
||||||
|
echo "🤖 Qwen consultation started (PID: $QWEN_PID)" >&2
|
||||||
|
echo " Monitor: tail -f ~/.claude/qwen-output.log" >&2
|
||||||
|
else
|
||||||
|
echo "⚠️ Qwen CLI not found at /usr/local/bin/qwen" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit immediately (non-blocking)
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,17 +1,193 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Ralph Auto-Trigger Hook
|
# Ralph Auto-Trigger Hook - Enhanced with Background Task Spawning
|
||||||
# Trigger: user-prompt
|
# Automatically starts Ralph CLI in background when needed
|
||||||
# Automatically triggers Ralph for complex tasks
|
#
|
||||||
|
# Modes (via RALPH_AUTO_MODE environment variable):
|
||||||
|
# "always" - Start Ralph for every request
|
||||||
|
# "agents" - Only for agent requests (default)
|
||||||
|
# "off" - Disable auto-trigger
|
||||||
|
#
|
||||||
|
# Background Execution:
|
||||||
|
# - Ralph runs as background process (non-blocking)
|
||||||
|
# - Claude Code continues immediately
|
||||||
|
# - Ralph output logged to: ~/.claude/ralph-output.log
|
||||||
|
# - Ralph PID tracked in: ~/.claude/ralph.pid
|
||||||
|
|
||||||
# Analyze task complexity and auto-trigger Ralph
|
set -euo pipefail
|
||||||
# when RALPH_AUTO=true or task appears complex
|
|
||||||
|
|
||||||
RALPH_AUTO="${RALPH_AUTO:-false}"
|
# Configuration
|
||||||
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
|
RALPH_STATE_FILE="$CLAUDE_DIR/ralph-loop.local.md"
|
||||||
|
RALPH_PID_FILE="$CLAUDE_DIR/ralph.pid"
|
||||||
|
RALPH_LOG_FILE="$CLAUDE_DIR/ralph-output.log"
|
||||||
|
RALPH_LOCK_FILE="$CLAUDE_DIR/ralph.lock"
|
||||||
|
|
||||||
if [ "$RALPH_AUTO" = "true" ]; then
|
# Read hook input from stdin
|
||||||
# Auto-delegate to Ralph for complex tasks
|
HOOK_INPUT=$(cat)
|
||||||
# The actual delegation logic is in the ralph skill
|
USER_PROMPT=$(echo "$HOOK_INPUT" | jq -r '.prompt // empty' 2>/dev/null || echo "")
|
||||||
:
|
|
||||||
|
# Fallback: if no JSON input, use first argument
|
||||||
|
if [[ -z "$USER_PROMPT" && $# -gt 0 ]]; then
|
||||||
|
USER_PROMPT="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Get Ralph mode (default: agents)
|
||||||
|
RALPH_AUTO_MODE="${RALPH_AUTO_MODE:-agents}"
|
||||||
|
RALPH_MAX_ITERATIONS="${RALPH_MAX_ITERATIONS:-50}"
|
||||||
|
|
||||||
|
# Exit if auto-trigger is disabled
|
||||||
|
if [[ "$RALPH_AUTO_MODE" == "off" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Ralph is already running (via lock file)
|
||||||
|
if [[ -f "$RALPH_LOCK_FILE" ]]; then
|
||||||
|
# Check if process is still alive
|
||||||
|
LOCK_PID=$(cat "$RALPH_LOCK_FILE" 2>/dev/null || echo "")
|
||||||
|
if [[ -n "$LOCKPD" ]] && kill -0 "$LOCK_PID" 2>/dev/null; then
|
||||||
|
# Ralph is already running, don't start another instance
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
# Lock file exists but process is dead, clean up
|
||||||
|
rm -f "$RALPH_LOCK_FILE" "$RALPH_PID_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Agent detection list (lowercase for matching)
|
||||||
|
AGENTS=(
|
||||||
|
"ai-engineer" "backend-architect" "devops-automator" "frontend-developer"
|
||||||
|
"mobile-app-builder" "rapid-prototyper" "test-writer-fixer"
|
||||||
|
"tiktok-strategist" "growth-hacker" "content-creator" "instagram-curator"
|
||||||
|
"reddit-builder" "twitter-engager" "app-store-optimizer"
|
||||||
|
"brand-guardian" "ui-designer" "ux-researcher" "visual-storyteller"
|
||||||
|
"whimsy-injector" "ui-ux-pro-max"
|
||||||
|
"feedback-synthesizer" "sprint-prioritizer" "trend-researcher"
|
||||||
|
"experiment-tracker" "project-shipper" "studio-producer" "studio-coach"
|
||||||
|
"analytics-reporter" "finance-tracker" "infrastructure-maintainer"
|
||||||
|
"legal-compliance-checker" "support-responder"
|
||||||
|
"api-tester" "performance-benchmarker" "test-results-analyzer"
|
||||||
|
"tool-evaluator" "workflow-optimizer"
|
||||||
|
"joker" "agent-updater"
|
||||||
|
"explore" "plan" "general-purpose"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Detect agent request (case-insensitive)
|
||||||
|
agent_detected=false
|
||||||
|
detected_agent=""
|
||||||
|
|
||||||
|
for agent in "${AGENTS[@]}"; do
|
||||||
|
if echo "$USER_PROMPT" | grep -iq "$agent"; then
|
||||||
|
agent_detected=true
|
||||||
|
detected_agent="$agent"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Determine if we should start Ralph
|
||||||
|
should_trigger=false
|
||||||
|
|
||||||
|
case "$RALPH_AUTO_MODE" in
|
||||||
|
"always")
|
||||||
|
# Trigger on all prompts
|
||||||
|
should_trigger=true
|
||||||
|
;;
|
||||||
|
"agents")
|
||||||
|
# Only trigger on agent requests OR development keywords
|
||||||
|
if [[ "$agent_detected" == true ]]; then
|
||||||
|
should_trigger=true
|
||||||
|
elif echo "$USER_PROMPT" | grep -qiE "build|create|implement|develop|fix|add|refactor|optimize|write|generate|delegate|autonomous"; then
|
||||||
|
should_trigger=true
|
||||||
|
detected_agent="general-development"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$should_trigger" == true ]]; then
|
||||||
|
# Create Ralph state file
|
||||||
|
mkdir -p "$CLAUDE_DIR"
|
||||||
|
|
||||||
|
cat > "$RALPH_STATE_FILE" << EOF
|
||||||
|
# Ralph Loop State - Auto-Triggered
|
||||||
|
# Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
||||||
|
|
||||||
|
**User Request:**
|
||||||
|
$USER_PROMPT
|
||||||
|
|
||||||
|
**Detected Agent:** $detected_agent
|
||||||
|
**Mode:** $RALPH_AUTO_MODE
|
||||||
|
**Max Iterations:** $RALPH_MAX_ITERATIONS
|
||||||
|
**Timestamp:** $(date -Iseconds)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
This state file was automatically generated by the Ralph auto-trigger hook.
|
||||||
|
Ralph CLI will read this file and autonomously execute the request.
|
||||||
|
|
||||||
|
## Auto-Trigger Details
|
||||||
|
|
||||||
|
- Triggered by: Claude Code UserPromptSubmit hook
|
||||||
|
- Trigger mode: $RALPH_AUTO_MODE
|
||||||
|
- Background execution: Yes (non-blocking)
|
||||||
|
- Log file: $RALPH_LOG_FILE
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Ralph is running autonomously in the background. Monitor progress:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# View Ralph output in real-time
|
||||||
|
tail -f ~/.claude/ralph-output.log
|
||||||
|
|
||||||
|
# Check if Ralph is still running
|
||||||
|
ps aux | grep ralph
|
||||||
|
|
||||||
|
# Stop Ralph manually
|
||||||
|
kill \$(cat ~/.claude/ralph.pid)
|
||||||
|
rm ~/.claude/ralph.lock
|
||||||
|
\`\`\`
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Spawn Ralph in background (NON-BLOCKING)
|
||||||
|
if command -v ralph &> /dev/null; then
|
||||||
|
# Create log file
|
||||||
|
touch "$RALPH_LOG_FILE"
|
||||||
|
|
||||||
|
# Start Ralph in background with nohup (survives terminal close)
|
||||||
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Starting Ralph in background..." >> "$RALPH_LOG_FILE"
|
||||||
|
echo "Mode: $RALPH_AUTO_MODE" >> "$RALPH_LOG_FILE"
|
||||||
|
echo "Agent: $detected_agent" >> "$RALPH_LOG_FILE"
|
||||||
|
echo "Max iterations: $RALPH_MAX_ITERATIONS" >> "$RALPH_LOG_FILE"
|
||||||
|
echo "---" >> "$RALPH_LOG_FILE"
|
||||||
|
|
||||||
|
# Start Ralph in background
|
||||||
|
nohup ralph build "$RALPH_MAX_ITERATIONS" >> "$RALPH_LOG_FILE" 2>&1 &
|
||||||
|
RALPH_PID=$!
|
||||||
|
|
||||||
|
# Save PID for tracking
|
||||||
|
echo "$RALPH_PID" > "$RALPH_PID_FILE"
|
||||||
|
echo "$RALPH_PID" > "$RALPH_LOCK_FILE"
|
||||||
|
|
||||||
|
# Log the trigger
|
||||||
|
{
|
||||||
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Ralph auto-triggered"
|
||||||
|
echo " Mode: $RALPH_AUTO_MODE"
|
||||||
|
echo " Agent: $detected_agent"
|
||||||
|
echo " PID: $RALPH_PID"
|
||||||
|
echo " Log: $RALPH_LOG_FILE"
|
||||||
|
} >> "$CLAUDE_DIR/ralph-trigger.log" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Notify user via stderr (visible in Claude Code)
|
||||||
|
echo "🔄 Ralph CLI auto-started in background" >&2
|
||||||
|
echo " PID: $RALPH_PID" >&2
|
||||||
|
echo " Agent: $detected_agent" >&2
|
||||||
|
echo " Monitor: tail -f ~/.claude/ralph-output.log" >&2
|
||||||
|
echo " Stop: kill \$(cat ~/.claude/ralph.pid)" >&2
|
||||||
|
else
|
||||||
|
# Ralph not installed, just create state file
|
||||||
|
echo "⚠️ Ralph CLI not installed. State file created for manual use." >&2
|
||||||
|
echo " Install: npm install -g @iannuttall/ralph" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit immediately (NON-BLOCKING - Claude Code continues)
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Session Start Hook - Auto-inject superpowers context
|
set -euo pipefail
|
||||||
# This hook runs on every session start/resume
|
|
||||||
# Trigger: session-start
|
|
||||||
|
|
||||||
# Check if AUTO_SUPERPOWERS is enabled
|
# Read skill files and inject into session context
|
||||||
if [ "${AUTO_SUPERPOWERS:-false}" = "true" ]; then
|
auto_superpowers_content=$(cat "${HOME}/.claude/skills/auto-superpowers/SKILL.md" 2>/dev/null || echo "Skill not found")
|
||||||
# Inject superpowers context into the session
|
using_superpowers_content=$(cat "${HOME}/.claude/skills/using-superpowers/SKILL.md" 2>/dev/null || echo "Skill not found")
|
||||||
if [ -f "$HOME/.claude/skills/using-superpowers/skill.md" ]; then
|
|
||||||
cat "$HOME/.claude/skills/using-superpowers/skill.md"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
# Output JSON with skills injected
|
||||||
|
cat <<EOF
|
||||||
|
{
|
||||||
|
"hookSpecificOutput": {
|
||||||
|
"hookEventName": "SessionStart",
|
||||||
|
"additionalContext": "\n**AUTO-SUPERPOWERS IS ACTIVE**\n\n${auto_superpowers_content}\n\n**USING-SUPERPOWERS INSTRUCTION:**\n\n${using_superpowers_content}\n\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,30 +1,450 @@
|
|||||||
# Plugins Directory
|
# Claude Code Plugin System
|
||||||
|
|
||||||
This directory contains plugin references and configurations for Claude Code.
|
A Conduit-inspired plugin and hooks system for Claude Code, enabling extensible functionality through GitHub-based plugins, event-driven hooks, and secure sandboxed execution.
|
||||||
|
|
||||||
## Plugin Categories
|
## Table of Contents
|
||||||
|
|
||||||
### Agent Plugins
|
- [Features](#features)
|
||||||
- `agent-browse` - Web browsing capabilities for agents
|
- [Installation](#installation)
|
||||||
- `claude-delegator` - Task delegation system
|
- [Quick Start](#quick-start)
|
||||||
|
- [Plugin Development](#plugin-development)
|
||||||
### UI/UX Plugins
|
- [Hooks System](#hooks-system)
|
||||||
- `claude-hud` - Heads-up display for Claude Code
|
- [CLI Reference](#cli-reference)
|
||||||
- `frontend-design` - Frontend design tools
|
- [Security](#security)
|
||||||
|
- [Examples](#examples)
|
||||||
### Safety Plugins
|
|
||||||
- `claude-code-safety-net` - Safety validation layer
|
## Features
|
||||||
|
|
||||||
### Marketplace
|
### 🎯 Core Capabilities
|
||||||
- `marketplaces` - Plugin marketplace references
|
|
||||||
|
- **GitHub-based Discovery**: Automatically discover plugins from GitHub repositories
|
||||||
## Installation
|
- **Zero-Configuration Install**: One-command installation from any GitHub repo
|
||||||
|
- **Event-Driven Hooks**: Hook into any Claude Code event (pre/post execution)
|
||||||
Plugins are referenced here and installed via:
|
- **Security Sandboxing**: Isolated execution with permission validation
|
||||||
```bash
|
- **Command Extensions**: Add custom commands to Claude Code
|
||||||
npm install <plugin-name>
|
- **Tool Extensions**: Extend Claude Code's built-in tools
|
||||||
```
|
- **Version Management**: Track, update, and manage plugin versions
|
||||||
|
- **Integrity Checking**: SHA-256 verification for plugin security
|
||||||
## Configuration
|
|
||||||
|
### 🔐 Security Features
|
||||||
Plugin settings go in `~/.claude/settings.json` under `plugins` section.
|
|
||||||
|
- Permission-based access control
|
||||||
|
- File system sandboxing
|
||||||
|
- Command execution validation
|
||||||
|
- Network access control
|
||||||
|
- Code injection prevention
|
||||||
|
- Binary integrity verification
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
The plugin system is included with Claude Code. No additional installation required.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Discover Plugins
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all available plugins
|
||||||
|
claude-plugin discover
|
||||||
|
|
||||||
|
# Search for specific plugins
|
||||||
|
claude-plugin discover git
|
||||||
|
claude-plugin discover docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install Plugins
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install from a marketplace
|
||||||
|
claude-plugin install claude-plugins-official hookify
|
||||||
|
|
||||||
|
# Install directly from GitHub
|
||||||
|
claude-plugin install-github username/my-plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manage Plugins
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View plugin information
|
||||||
|
claude-plugin info hookify
|
||||||
|
|
||||||
|
# Enable/disable plugins
|
||||||
|
claude-plugin enable hookify
|
||||||
|
claude-plugin disable hookify
|
||||||
|
|
||||||
|
# Update plugins
|
||||||
|
claude-plugin update hookify
|
||||||
|
|
||||||
|
# Uninstall plugins
|
||||||
|
claude-plugin uninstall hookify
|
||||||
|
```
|
||||||
|
|
||||||
|
## Plugin Development
|
||||||
|
|
||||||
|
### Plugin Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
my-plugin/
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json # Plugin metadata
|
||||||
|
├── commands/ # Command handlers
|
||||||
|
│ └── my-command.ts
|
||||||
|
├── hooks/ # Hook handlers
|
||||||
|
│ └── my-hook.ts
|
||||||
|
├── skills/ # Skill definitions
|
||||||
|
│ └── my-skill.md
|
||||||
|
├── install.sh # Installation script (optional)
|
||||||
|
└── uninstall.sh # Uninstallation script (optional)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plugin Metadata
|
||||||
|
|
||||||
|
Create a `.claude-plugin/plugin.json` file:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "my-plugin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "My awesome plugin for Claude Code",
|
||||||
|
"author": "Your Name",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "https://github.com/username/my-plugin",
|
||||||
|
"claude": {
|
||||||
|
"minVersion": "1.0.0",
|
||||||
|
"permissions": [
|
||||||
|
"read:files",
|
||||||
|
"write:files",
|
||||||
|
"execute:commands"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"name": "my:command",
|
||||||
|
"description": "Does something awesome",
|
||||||
|
"handler": "commands/my-command.ts",
|
||||||
|
"permissions": ["read:files"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"event": "PostFileEdit",
|
||||||
|
"handler": "hooks/my-hook.ts",
|
||||||
|
"priority": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Commands
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// commands/my-command.ts
|
||||||
|
export interface MyCommandOptions {
|
||||||
|
input: string
|
||||||
|
option?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handle(
|
||||||
|
args: MyCommandOptions,
|
||||||
|
context: any
|
||||||
|
): Promise<string> {
|
||||||
|
const { input, option } = args
|
||||||
|
|
||||||
|
// Your logic here
|
||||||
|
return `✓ Command executed with: ${input}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { handle }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Hooks
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// hooks/my-hook.ts
|
||||||
|
export interface HookContext {
|
||||||
|
event: string
|
||||||
|
timestamp: string
|
||||||
|
data: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handle(
|
||||||
|
context: HookContext
|
||||||
|
): Promise<void> {
|
||||||
|
console.log(`Hook triggered: ${context.event}`)
|
||||||
|
console.log(`Data:`, context.data)
|
||||||
|
|
||||||
|
// Your logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { handle }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publishing Your Plugin
|
||||||
|
|
||||||
|
1. Create a GitHub repository with your plugin
|
||||||
|
2. Add the `.claude-plugin/plugin.json` metadata file
|
||||||
|
3. Push to GitHub
|
||||||
|
4. Users can install with:
|
||||||
|
```bash
|
||||||
|
claude-plugin install-github username/your-plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hooks System
|
||||||
|
|
||||||
|
### Available Hook Events
|
||||||
|
|
||||||
|
| Event | Description | When It Fires |
|
||||||
|
|-------|-------------|---------------|
|
||||||
|
| `UserPromptSubmit` | User submits a prompt | Before sending to Claude |
|
||||||
|
| `PreToolUse` | Before tool execution | Tool about to be used |
|
||||||
|
| `PostToolUse` | After tool execution | Tool completed |
|
||||||
|
| `PreFileEdit` | Before file edit | File about to be modified |
|
||||||
|
| `PostFileEdit` | After file edit | File was modified |
|
||||||
|
| `PreCommand` | Before CLI command | Command about to run |
|
||||||
|
| `PostCommand` | After CLI command | Command completed |
|
||||||
|
| `SessionStart` | Session starts | New session begins |
|
||||||
|
| `SessionEnd` | Session ends | Session closing |
|
||||||
|
| `PluginLoad` | Plugin loads | Plugin loaded into memory |
|
||||||
|
| `PluginUnload` | Plugin unloads | Plugin being unloaded |
|
||||||
|
| `Error` | Error occurs | Any error happens |
|
||||||
|
|
||||||
|
### Hook Priority
|
||||||
|
|
||||||
|
Hooks execute in priority order (higher = earlier). Default priority is 0.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"event": "PostFileEdit",
|
||||||
|
"handler": "hooks/auto-save.ts",
|
||||||
|
"priority": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Registering Hooks via Config
|
||||||
|
|
||||||
|
You can register hooks in your `.claude/hooks.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PostFileEdit": [
|
||||||
|
{
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "/path/to/hook-script.sh",
|
||||||
|
"timeout": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI Reference
|
||||||
|
|
||||||
|
### `claude-plugin discover [query]`
|
||||||
|
List available plugins, optionally filtering by search query.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin discover
|
||||||
|
claude-plugin discover git
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin install <marketplace> [plugin-name]`
|
||||||
|
Install a plugin from a marketplace.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin install claude-plugins-official hookify
|
||||||
|
claude-plugin install claude-plugins-official # List all plugins
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin install-github <repo>`
|
||||||
|
Install a plugin directly from GitHub.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin install-github username/my-plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin uninstall <plugin-name> [marketplace]`
|
||||||
|
Uninstall a plugin.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin uninstall hookify
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin enable/disable <plugin-name> [marketplace]`
|
||||||
|
Enable or disable a plugin without uninstalling.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin enable hookify
|
||||||
|
claude-plugin disable hookify
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin update <plugin-name> [marketplace]`
|
||||||
|
Update a plugin to the latest version.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin update hookify
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin info <plugin-name>`
|
||||||
|
Show detailed information about a plugin.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin info hookify
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin hooks [event]`
|
||||||
|
List registered hooks.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin hooks # All hooks
|
||||||
|
claude-plugin hooks PostFileEdit # Specific event
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin add-marketplace <name> <github-url>`
|
||||||
|
Add a new plugin marketplace.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin add-marketplace my-marketplace https://github.com/user/repo
|
||||||
|
```
|
||||||
|
|
||||||
|
### `claude-plugin validate <path>`
|
||||||
|
Validate a plugin structure and integrity.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin validate /path/to/plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Permissions
|
||||||
|
|
||||||
|
Plugins request permissions in their `plugin.json`:
|
||||||
|
|
||||||
|
| Permission | Description |
|
||||||
|
|------------|-------------|
|
||||||
|
| `read:files` | Read files from the file system |
|
||||||
|
| `write:files` | Write files to the file system |
|
||||||
|
| `execute:commands` | Execute shell commands |
|
||||||
|
| `network:request` | Make network requests |
|
||||||
|
| `read:config` | Read Claude Code configuration |
|
||||||
|
| `write:config` | Write Claude Code configuration |
|
||||||
|
| `hook:events` | Register event hooks |
|
||||||
|
| `read:secrets` | Access sensitive data (API keys, etc.) |
|
||||||
|
|
||||||
|
### Sandboxing
|
||||||
|
|
||||||
|
Plugins execute in a sandboxed environment with:
|
||||||
|
|
||||||
|
- **File System**: Access restricted to allowed paths
|
||||||
|
- **Commands**: Dangerous patterns blocked (rm -rf /, etc.)
|
||||||
|
- **Network**: Domain whitelist/blacklist enforcement
|
||||||
|
- **Code**: Injection prevention and sanitization
|
||||||
|
|
||||||
|
### Integrity Verification
|
||||||
|
|
||||||
|
All plugins are verified with SHA-256 hashes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View plugin integrity
|
||||||
|
claude-plugin info my-plugin
|
||||||
|
|
||||||
|
# Verify manually
|
||||||
|
claude-plugin validate /path/to/plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Git Workflow Plugin
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
- `git:smart-commit` - Auto-stage and commit
|
||||||
|
- `git:pr-create` - Create pull requests
|
||||||
|
- `git:branch-cleanup` - Clean up merged branches
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin install-github yourusername/git-workflow
|
||||||
|
git:smart-commit --type feat --scope api
|
||||||
|
git:pr-create --title "Add new feature" --base main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Docker Helper Plugin
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
- `docker:deploy` - Deploy with zero-downtime
|
||||||
|
- `docker:logs` - View and filter logs
|
||||||
|
- `docker:cleanup` - Clean up resources
|
||||||
|
- `docker:env` - Manage environment variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin install-github yourusername/docker-helper
|
||||||
|
docker:deploy --env production --no-downtime
|
||||||
|
docker:logs --service app --tail 100 --follow
|
||||||
|
docker:cleanup --containers --images --volumes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Knowledge Base Plugin
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
- `knowledge:add` - Add knowledge entries
|
||||||
|
- `knowledge:search` - Search knowledge base
|
||||||
|
- `knowledge:list` - List all entries
|
||||||
|
- `knowledge:export` - Export to JSON/Markdown/CSV
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude-plugin install-github yourusername/knowledge-base
|
||||||
|
knowledge:add --content "How to deploy to production" --tags deploy,ops
|
||||||
|
knowledge:search --query "deploy" --category ops
|
||||||
|
knowledge:export --format markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ Claude Code Core │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────┼─────────────┐
|
||||||
|
│ │ │
|
||||||
|
┌───────▼──────┐ ┌───▼────┐ ┌─────▼─────┐
|
||||||
|
│ Plugin │ │ Hook │ │ Security │
|
||||||
|
│ Manager │ │ System │ │ Manager │
|
||||||
|
└──────────────┘ └────────┘ └───────────┘
|
||||||
|
│ │ │
|
||||||
|
└─────────────┼─────────────┘
|
||||||
|
│
|
||||||
|
┌───────▼───────┐
|
||||||
|
│ Plugins │
|
||||||
|
│ (Sandboxed) │
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data Flow
|
||||||
|
|
||||||
|
1. **Installation**: Plugin downloaded from GitHub → Validation → Registration
|
||||||
|
2. **Loading**: Plugin metadata read → Security context created → Hooks registered
|
||||||
|
3. **Execution**: Command/tool called → Permission check → Sandboxed execution
|
||||||
|
4. **Hooks**: Event fires → Hooks executed by priority → Results collected
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome contributions! Please see our contributing guidelines for more information.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - see LICENSE file for details
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
- GitHub Issues: https://github.com/anthropics/claude-code/issues
|
||||||
|
- Documentation: https://docs.anthropic.com
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
Inspired by [Conduit](https://github.com/conduit-ui/conduit) - the developer liberation platform.
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "glm-plan-bug:case-feedback",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Bug case feedback system for GLM Coding Plan",
|
|
||||||
"type": "feedback",
|
|
||||||
"author": "GLM Team",
|
|
||||||
"capabilities": ["case-feedback"],
|
|
||||||
"triggers": ["/glm-plan-bug:case-feedback"],
|
|
||||||
"config": {
|
|
||||||
"endpoint": "https://glm-plan-bug.example.com/api/feedback"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "glm-plan-usage:usage-query",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Usage query system for GLM Coding Plan",
|
|
||||||
"type": "usage",
|
|
||||||
"author": "GLM Team",
|
|
||||||
"capabilities": ["usage-query"],
|
|
||||||
"triggers": ["/glm-plan-usage:usage-query"],
|
|
||||||
"config": {
|
|
||||||
"endpoint": "https://glm-plan-usage.example.com/api/query"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Plugin Marketplace
|
|
||||||
|
|
||||||
References to external plugin marketplaces for Claude Code.
|
|
||||||
|
|
||||||
## Available Marketplaces
|
|
||||||
|
|
||||||
### Superpowers Marketplace
|
|
||||||
- **URL**: https://github.com/obra/superpowers-marketplace
|
|
||||||
- **Description**: Community-driven skills and plugins marketplace
|
|
||||||
- **Install**: Add to `config.json` marketplaces section
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
To add a marketplace, edit `~/.claude/config.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"marketplaces": {
|
|
||||||
"obra/superpowers-marketplace": "/path/to/marketplace"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Featured Plugins
|
|
||||||
|
|
||||||
Browse the marketplace to discover:
|
|
||||||
- Custom skills
|
|
||||||
- Agent templates
|
|
||||||
- Tool integrations
|
|
||||||
- Theme packages
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "rust-analyzer-lsp",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Rust language support via LSP",
|
|
||||||
"type": "lsp",
|
|
||||||
"language": "rust",
|
|
||||||
"capabilities": ["definition", "references", "hover", "completion"],
|
|
||||||
"install": "rust-analyzer"
|
|
||||||
}
|
|
||||||
@@ -1,270 +1,246 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
################################################################################
|
# Claude Code Agents Sync Script
|
||||||
# sync-agents.sh - Agent Synchronization Script
|
# Syncs local agents with GitHub repository and backs up to Gitea
|
||||||
################################################################################
|
|
||||||
# Synchronizes agents from GitHub/Gitea repositories to local Claude Code
|
|
||||||
# installation.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# ./sync-agents.sh [options]
|
|
||||||
#
|
|
||||||
# Options:
|
|
||||||
# --source URL Source repository URL
|
|
||||||
# --branch NAME Branch to sync from (default: main)
|
|
||||||
# --force Force overwrite existing agents
|
|
||||||
# --dry-run Show what would be done without doing it
|
|
||||||
# --verbose Enable verbose output
|
|
||||||
#
|
|
||||||
# Configuration:
|
|
||||||
# Sources can be configured in ~/.claude/agents/sync-sources.json
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
set -e
|
set -euo pipefail
|
||||||
|
|
||||||
# Colors
|
# Configuration
|
||||||
|
AGENTS_DIR="${HOME}/.claude/agents"
|
||||||
|
BACKUP_DIR="${AGENTS_DIR}.backup.$(date +%Y%m%d-%H%M%S)"
|
||||||
|
GITHUB_REPO="https://github.com/contains-studio/agents"
|
||||||
|
TEMP_DIR="/tmp/claude-agents-sync-$RANDOM"
|
||||||
|
UPSTREAM_DIR="$TEMP_DIR/upstream"
|
||||||
|
LOG_FILE="${AGENTS_DIR}/update.log"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
CYAN='\033[0;36m'
|
NC='\033[0m' # No Color
|
||||||
BOLD='\033[1m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
# Directories
|
# Logging function
|
||||||
CLAUDE_DIR="${HOME}/.claude"
|
log() {
|
||||||
AGENTS_DIR="${CLAUDE_DIR}/agents"
|
local level=$1
|
||||||
CONFIG_FILE="${AGENTS_DIR}/sync-sources.json"
|
shift
|
||||||
|
local message="$@"
|
||||||
# Flags
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
FORCE=false
|
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
||||||
DRY_RUN=false
|
|
||||||
VERBOSE=false
|
|
||||||
|
|
||||||
# Default sources
|
|
||||||
DEFAULT_SOURCES=(
|
|
||||||
"https://github.com/anthropics/anthropic-agents"
|
|
||||||
"https://github.com/contains-cafe/studio-agents"
|
|
||||||
)
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Helper Functions
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}[INFO]${NC} $1"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_success() {
|
# Print colored message
|
||||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
print_msg() {
|
||||||
|
local color=$1
|
||||||
|
shift
|
||||||
|
echo -e "${color}$*${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warn() {
|
# Create backup
|
||||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
create_backup() {
|
||||||
}
|
print_msg "$BLUE" "📦 Creating backup..."
|
||||||
|
if cp -r "$AGENTS_DIR" "$BACKUP_DIR"; then
|
||||||
log_error() {
|
print_msg "$GREEN" "✓ Backup created: $BACKUP_DIR"
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
log "INFO" "Backup created at $BACKUP_DIR"
|
||||||
}
|
|
||||||
|
|
||||||
log_step() {
|
|
||||||
echo -e "${CYAN}${BOLD}==>${NC} ${BOLD}$1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Agent Synchronization
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
sync_from_source() {
|
|
||||||
local source_url="$1"
|
|
||||||
local branch="${2:-main}"
|
|
||||||
local temp_dir
|
|
||||||
|
|
||||||
log_step "Syncing from $source_url"
|
|
||||||
|
|
||||||
# Create temp directory for clone
|
|
||||||
temp_dir=$(mktemp -d)
|
|
||||||
|
|
||||||
if [ "$DRY_RUN" = true ]; then
|
|
||||||
log_info "[DRY RUN] Would clone $source_url (branch: $branch)"
|
|
||||||
rm -rf "$temp_dir"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clone repository
|
|
||||||
if ! git clone --depth 1 --branch "$branch" "$source_url" "$temp_dir" 2>/dev/null; then
|
|
||||||
log_warn "Failed to clone $source_url"
|
|
||||||
rm -rf "$temp_dir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy agents
|
|
||||||
local agent_count=0
|
|
||||||
local copied_count=0
|
|
||||||
local skipped_count=0
|
|
||||||
|
|
||||||
# Find agent definitions (look for common patterns)
|
|
||||||
while IFS= read -r -d '' agent_file; do
|
|
||||||
((agent_count++))
|
|
||||||
|
|
||||||
local agent_name
|
|
||||||
agent_name=$(basename "$(dirname "$agent_file")")
|
|
||||||
local dest_dir="${AGENTS_DIR}/${agent_name}"
|
|
||||||
|
|
||||||
# Check if already exists
|
|
||||||
if [ -d "$dest_dir" ] && [ "$FORCE" = false ]; then
|
|
||||||
((skipped_count++))
|
|
||||||
[ "$VERBOSE" = true ] && log_info "Skipped: $agent_name (exists)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create destination and copy
|
|
||||||
mkdir -p "$dest_dir"
|
|
||||||
cp -r "$(dirname "$agent_file")"/* "$dest_dir/" 2>/dev/null || true
|
|
||||||
((copied_count++))
|
|
||||||
|
|
||||||
[ "$VERBOSE" = true ] && log_info "Copied: $agent_name"
|
|
||||||
|
|
||||||
done < <(find "$temp_dir" -type f \( -name "agent.md" -o -name "skill.md" -o -name "AGENT.md" -o -name "SKILL.md" \) -print0 2>/dev/null)
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
rm -rf "$temp_dir"
|
|
||||||
|
|
||||||
log_success "Synced from $source_url: $copied_count copied, $skipped_count skipped (found $agent_count total)"
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_from_config() {
|
|
||||||
local config_file="$1"
|
|
||||||
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
log_warn "Config file not found: $config_file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Parse JSON config (requires jq)
|
|
||||||
if command -v jq &> /dev/null; then
|
|
||||||
local sources
|
|
||||||
sources=$(jq -r '.sources[].url' "$config_file" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$sources" ]; then
|
|
||||||
log_warn "No sources found in config"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
while IFS= read -r source; do
|
|
||||||
local branch
|
|
||||||
branch=$(jq -r ".sources[] | select(.url==\"$source\") | .branch // \"main\"" "$config_file")
|
|
||||||
sync_from_source "$source" "$branch"
|
|
||||||
done <<< "$sources"
|
|
||||||
else
|
else
|
||||||
log_warn "jq not found. Cannot parse config file."
|
print_msg "$RED" "✗ Failed to create backup"
|
||||||
log_info "Install jq: sudo apt-get install jq"
|
log "ERROR" "Backup creation failed"
|
||||||
return 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_default_sources() {
|
# Download upstream agents
|
||||||
log_step "Syncing from default sources"
|
download_upstream() {
|
||||||
|
print_msg "$BLUE" "📥 Downloading agents from $GITHUB_REPO..."
|
||||||
|
mkdir -p "$TEMP_DIR"
|
||||||
|
|
||||||
for source in "${DEFAULT_SOURCES[@]}"; do
|
if command -v git &> /dev/null; then
|
||||||
sync_from_source "$source" "main"
|
# Use git if available (faster)
|
||||||
done
|
git clone --depth 1 "$GITHUB_REPO" "$UPSTREAM_DIR" 2>/dev/null || {
|
||||||
}
|
print_msg "$RED" "✗ Failed to clone repository"
|
||||||
|
log "ERROR" "Git clone failed"
|
||||||
################################################################################
|
exit 1
|
||||||
# Main
|
}
|
||||||
################################################################################
|
|
||||||
|
|
||||||
print_usage() {
|
|
||||||
cat << EOF
|
|
||||||
Usage: $0 [options]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--source URL Source repository URL
|
|
||||||
--branch NAME Branch to sync from (default: main)
|
|
||||||
--force Force overwrite existing agents
|
|
||||||
--dry-run Show what would be done without doing it
|
|
||||||
--verbose Enable verbose output
|
|
||||||
-h, --help Show this help message
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
$0 # Sync from default sources
|
|
||||||
$0 --source https://github.com/user/repo
|
|
||||||
$0 --force --verbose # Force overwrite, verbose output
|
|
||||||
$0 --dry-run # Preview changes
|
|
||||||
|
|
||||||
Configuration:
|
|
||||||
Sources can be configured in ~/.claude/agents/sync-sources.json
|
|
||||||
|
|
||||||
Format:
|
|
||||||
{
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/user/repo",
|
|
||||||
"branch": "main"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local custom_source=""
|
|
||||||
local custom_branch="main"
|
|
||||||
|
|
||||||
# Parse arguments
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case $1 in
|
|
||||||
--source)
|
|
||||||
custom_source="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--branch)
|
|
||||||
custom_branch="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--force)
|
|
||||||
FORCE=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--dry-run)
|
|
||||||
DRY_RUN=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--verbose)
|
|
||||||
VERBOSE=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
print_usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_error "Unknown option: $1"
|
|
||||||
print_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Ensure agents directory exists
|
|
||||||
mkdir -p "$AGENTS_DIR"
|
|
||||||
|
|
||||||
# Sync
|
|
||||||
if [ -n "$custom_source" ]; then
|
|
||||||
sync_from_source "$custom_source" "$custom_branch"
|
|
||||||
elif [ -f "$CONFIG_FILE" ]; then
|
|
||||||
sync_from_config "$CONFIG_FILE"
|
|
||||||
else
|
else
|
||||||
sync_default_sources
|
# Fallback to wget/curl
|
||||||
|
print_msg "$YELLOW" "⚠ Git not found, downloading archive..."
|
||||||
|
local archive="$TEMP_DIR/agents.tar.gz"
|
||||||
|
if command -v wget &> /dev/null; then
|
||||||
|
wget -q "$GITHUB_REPO/archive/main.tar.gz" -O "$archive"
|
||||||
|
elif command -v curl &> /dev/null; then
|
||||||
|
curl -sL "$GITHUB_REPO/archive/main.tar.gz" -o "$archive"
|
||||||
|
else
|
||||||
|
print_msg "$RED" "✗ Need git, wget, or curl"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$UPSTREAM_DIR"
|
||||||
|
tar -xzf "$archive" -C "$UPSTREAM_DIR" --strip-components=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_msg "$GREEN" "✓ Downloaded upstream agents"
|
||||||
|
log "INFO" "Downloaded agents from $GITHUB_REPO"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compare and sync agents
|
||||||
|
sync_agents() {
|
||||||
|
print_msg "$BLUE" "🔄 Syncing agents..."
|
||||||
|
|
||||||
|
local new_agents=()
|
||||||
|
local updated_agents=()
|
||||||
|
local custom_agents=()
|
||||||
|
|
||||||
|
# Find all agent files in upstream
|
||||||
|
while IFS= read -r upstream_file; do
|
||||||
|
local rel_path="${upstream_file#$UPSTREAM_DIR/}"
|
||||||
|
local local_file="$AGENTS_DIR/$rel_path"
|
||||||
|
|
||||||
|
if [[ ! -f "$local_file" ]]; then
|
||||||
|
# New agent
|
||||||
|
new_agents+=("$rel_path")
|
||||||
|
mkdir -p "$(dirname "$local_file")"
|
||||||
|
cp "$upstream_file" "$local_file"
|
||||||
|
log "INFO" "Added new agent: $rel_path"
|
||||||
|
elif ! diff -q "$upstream_file" "$local_file" &>/dev/null; then
|
||||||
|
# Updated agent - check if customized
|
||||||
|
if grep -q "CUSTOMIZED" "$local_file" 2>/dev/null || \
|
||||||
|
[[ -f "${local_file}.local" ]]; then
|
||||||
|
custom_agents+=("$rel_path")
|
||||||
|
log "WARN" "Skipped customized agent: $rel_path"
|
||||||
|
else
|
||||||
|
updated_agents+=("$rel_path")
|
||||||
|
cp "$upstream_file" "$local_file"
|
||||||
|
log "INFO" "Updated agent: $rel_path"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(find "$UPSTREAM_DIR" -name "*.md" -type f)
|
||||||
|
|
||||||
|
# Report results
|
||||||
|
echo ""
|
||||||
|
print_msg "$GREEN" "✨ New agents (${#new_agents[@]}):"
|
||||||
|
for agent in "${new_agents[@]}"; do
|
||||||
|
echo " + $agent"
|
||||||
|
done | head -20
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_msg "$YELLOW" "📝 Updated agents (${#updated_agents[@]}):"
|
||||||
|
for agent in "${updated_agents[@]}"; do
|
||||||
|
echo " ~ $agent"
|
||||||
|
done | head -20
|
||||||
|
|
||||||
|
if [[ ${#custom_agents[@]} -gt 0 ]]; then
|
||||||
|
echo ""
|
||||||
|
print_msg "$YELLOW" "⚠️ Preserved custom agents (${#custom_agents[@]}):"
|
||||||
|
for agent in "${custom_agents[@]}"; do
|
||||||
|
echo " • $agent"
|
||||||
|
done | head -20
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
local total_agents
|
local total_changes=$((${#new_agents[@]} + ${#updated_agents[@]}))
|
||||||
total_agents=$(find "$AGENTS_DIR" -mindepth 1 -maxdepth 1 -type d | wc -l)
|
log "INFO" "Sync complete: ${#new_agents[@]} new, ${#updated_agents[@]} updated, ${#custom_agents[@]} preserved"
|
||||||
|
|
||||||
log_success "Agent sync complete!"
|
|
||||||
log_info "Total agents in $AGENTS_DIR: $total_agents"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run main
|
# Commit to git
|
||||||
|
commit_to_git() {
|
||||||
|
print_msg "$BLUE" "💾 Committing to git..."
|
||||||
|
|
||||||
|
cd "$AGENTS_DIR"
|
||||||
|
|
||||||
|
# Check if there are changes
|
||||||
|
if git diff --quiet && git diff --cached --quiet; then
|
||||||
|
print_msg "$YELLOW" "⚠️ No changes to commit"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add all agents
|
||||||
|
git add . -- '*.md'
|
||||||
|
|
||||||
|
# Commit with descriptive message
|
||||||
|
local commit_msg="Update agents from upstream
|
||||||
|
|
||||||
|
$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- $(git diff --cached --name-only | wc -l) files updated
|
||||||
|
- From: $GITHUB_REPO"
|
||||||
|
|
||||||
|
git commit -m "$commit_msg" 2>/dev/null || {
|
||||||
|
print_msg "$YELLOW" "⚠️ Nothing to commit or git not configured"
|
||||||
|
log "WARN" "Git commit skipped"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
print_msg "$GREEN" "✓ Committed to local git"
|
||||||
|
log "INFO" "Committed changes to git"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Push to Gitea
|
||||||
|
push_to_gitea() {
|
||||||
|
if [[ -z "${GITEA_REPO_URL:-}" ]]; then
|
||||||
|
print_msg "$YELLOW" "⚠️ GITEA_REPO_URL not set, skipping push"
|
||||||
|
print_msg "$YELLOW" " Set it with: export GITEA_REPO_URL='your-gitea-repo-url'"
|
||||||
|
log "WARN" "GITEA_REPO_URL not set, push skipped"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_msg "$BLUE" "📤 Pushing to Gitea..."
|
||||||
|
|
||||||
|
cd "$AGENTS_DIR"
|
||||||
|
|
||||||
|
# Ensure remote exists
|
||||||
|
if ! git remote get-url origin &>/dev/null; then
|
||||||
|
git remote add origin "$GITEA_REPO_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git push -u origin main 2>/dev/null || git push -u origin master 2>/dev/null; then
|
||||||
|
print_msg "$GREEN" "✓ Pushed to Gitea"
|
||||||
|
log "INFO" "Pushed to Gitea: $GITEA_REPO_URL"
|
||||||
|
else
|
||||||
|
print_msg "$YELLOW" "⚠️ Push failed (check credentials/URL)"
|
||||||
|
log "ERROR" "Push to Gitea failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rollback function
|
||||||
|
rollback() {
|
||||||
|
print_msg "$RED" "🔄 Rolling back to backup..."
|
||||||
|
if [[ -d "$BACKUP_DIR" ]]; then
|
||||||
|
rm -rf "$AGENTS_DIR"
|
||||||
|
mv "$BACKUP_DIR" "$AGENTS_DIR"
|
||||||
|
print_msg "$GREEN" "✓ Rolled back successfully"
|
||||||
|
log "INFO" "Rolled back to $BACKUP_DIR"
|
||||||
|
else
|
||||||
|
print_msg "$RED" "✗ No backup found!"
|
||||||
|
log "ERROR" "Rollback failed - no backup"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
print_msg "$BLUE" "🚀 Claude Code Agents Sync"
|
||||||
|
print_msg "$BLUE" "════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
trap rollback ERR
|
||||||
|
|
||||||
|
create_backup
|
||||||
|
download_upstream
|
||||||
|
sync_agents
|
||||||
|
commit_to_git
|
||||||
|
push_to_gitea
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_msg "$GREEN" "✅ Sync complete!"
|
||||||
|
print_msg "$BLUE" "💾 Backup: $BACKUP_DIR"
|
||||||
|
print_msg "$BLUE" "📋 Log: $LOG_FILE"
|
||||||
|
echo ""
|
||||||
|
print_msg "$YELLOW" "To rollback: rm -rf $AGENTS_DIR && mv $BACKUP_DIR $AGENTS_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
# Configuration Templates
|
|
||||||
|
|
||||||
This directory contains template configuration files for Claude Code.
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
| File | Purpose | Location After Install |
|
|
||||||
|------|---------|----------------------|
|
|
||||||
| `settings.json` | Main Claude Code settings | `~/.claude/settings.json` |
|
|
||||||
| `settings.local.json` | Local permissions and settings | `~/.claude/settings.local.json` |
|
|
||||||
| `hooks.json` | Hook configuration | `~/.claude/hooks.json` |
|
|
||||||
| `config.json` | Marketplace and plugins config | `~/.claude/config.json` |
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
The `supercharge.sh` script will install these templates if they don't already exist.
|
|
||||||
|
|
||||||
Existing configurations are preserved - templates are only installed if the target file doesn't exist.
|
|
||||||
|
|
||||||
## Settings Overview
|
|
||||||
|
|
||||||
### settings.json
|
|
||||||
- **cursorFormatting**: How to format code cursors
|
|
||||||
- **skills**: Auto-load skills and priorities
|
|
||||||
- **hooks**: Hook configuration
|
|
||||||
|
|
||||||
### settings.local.json
|
|
||||||
- **permissions**: Allowed prompt patterns
|
|
||||||
- **local**: Local environment settings
|
|
||||||
|
|
||||||
### hooks.json
|
|
||||||
- **session-start**: Hooks that run when session starts
|
|
||||||
- **user-prompt**: Hooks that run on each user prompt
|
|
||||||
- **environment**: Environment variables for hooks
|
|
||||||
|
|
||||||
### config.json
|
|
||||||
- **marketplaces**: Plugin marketplace sources
|
|
||||||
- **plugins**: Plugin sources
|
|
||||||
- **agents**: Agent sync sources
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
After installation, edit the files in `~/.claude/` to customize your setup.
|
|
||||||
|
|
||||||
Templates will not be overwritten on subsequent runs - your changes are preserved.
|
|
||||||
@@ -1,25 +1 @@
|
|||||||
{
|
{"marketplaces": {"obra/superpowers-marketplace": "/home/uroma/.claude/plugins/marketplaces/superpowers-marketplace"}}
|
||||||
"marketplaces": {
|
|
||||||
"obra/superpowers-marketplace": "https://github.com/obra/superpowers-marketplace"
|
|
||||||
},
|
|
||||||
"plugins": {
|
|
||||||
"sources": [
|
|
||||||
"https://github.com/anthropics/claude-code-plugins"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"agents": {
|
|
||||||
"syncOnStartup": true,
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/anthropics/anthropic-agents",
|
|
||||||
"branch": "main",
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/contains-cafe/studio-agents",
|
|
||||||
"branch": "main",
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,40 +1,21 @@
|
|||||||
{
|
{
|
||||||
|
"description": "User hooks for Ralph auto-trigger and Qwen consultation",
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"session-start": [
|
"UserPromptSubmit": [
|
||||||
{
|
{
|
||||||
"file": "session-start-superpowers.sh",
|
"hooks": [
|
||||||
"enabled": true,
|
{
|
||||||
"description": "Auto-inject superpowers context on session start"
|
"type": "command",
|
||||||
|
"command": "/home/uroma/.claude/hooks/ralph-auto-trigger.sh",
|
||||||
|
"timeout": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "/home/uroma/.claude/hooks/qwen-consult.sh",
|
||||||
|
"timeout": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"session-end": [],
|
|
||||||
"user-prompt": [
|
|
||||||
{
|
|
||||||
"file": "qwen-consult.sh",
|
|
||||||
"enabled": true,
|
|
||||||
"description": "Qwen AI consultation on complex tasks"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file": "ralph-auto-trigger.sh",
|
|
||||||
"enabled": false,
|
|
||||||
"description": "Auto-trigger Ralph for autonomous iteration"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file": "consult-qwen.sh",
|
|
||||||
"enabled": true,
|
|
||||||
"description": "Qwen consultation wrapper"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tool-use": [],
|
|
||||||
"response": []
|
|
||||||
},
|
|
||||||
"environment": {
|
|
||||||
"RALPH_AGENT": "claude",
|
|
||||||
"RALPH_MAX_ITERATIONS": "100",
|
|
||||||
"RALPH_MAX_RUNTIME": "14400",
|
|
||||||
"QWEN_CONSULT_MODE": "delegate",
|
|
||||||
"QWEN_MODEL": "qwen-coder-plus",
|
|
||||||
"QWEN_MAX_ITERATIONS": "3",
|
|
||||||
"AUTO_SUPERPOWERS": "true"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,15 @@
|
|||||||
{
|
{
|
||||||
"cursorFormatting": "compact",
|
"env": {
|
||||||
"inlineChatPreview": "compact",
|
"ANTHROPIC_AUTH_TOKEN": "020f54a283144bfea9f182f2f2e37d9c.PsqKSA7AFIfKuaEl",
|
||||||
"ensureConsistency": true,
|
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
|
||||||
"experimentalFeatures": {
|
"API_TIMEOUT_MS": "3000000",
|
||||||
"contextMenu": true,
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
||||||
"debugTools": true
|
"ANTHROPIC_MODEL": "glm-4.7"
|
||||||
},
|
},
|
||||||
"permissions": {},
|
"enabledPlugins": {
|
||||||
"skills": {
|
"glm-plan-bug@zai-coding-plugins": true,
|
||||||
"autoLoad": [
|
"glm-plan-usage@zai-coding-plugins": true,
|
||||||
"always-use-superpowers",
|
"superpowers@superpowers-marketplace": true,
|
||||||
"auto-superpowers"
|
"rust-analyzer-lsp@claude-plugins-official": true
|
||||||
],
|
|
||||||
"priority": {
|
|
||||||
"always-use-superpowers": 9999
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hooks": {
|
|
||||||
"session-start": [
|
|
||||||
"session-start-superpowers.sh"
|
|
||||||
],
|
|
||||||
"user-prompt": [
|
|
||||||
"qwen-consult.sh",
|
|
||||||
"ralph-auto-trigger.sh"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
{
|
{
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"allowedPrompts": []
|
"allow": [
|
||||||
},
|
"Bash(npm install:*)",
|
||||||
"local": {
|
"Bash(npm run content:*)",
|
||||||
"autoSuperpowers": true,
|
"Bash(npm run build:*)",
|
||||||
"ralphAuto": false,
|
"Bash(grep:*)",
|
||||||
"qwenConsultMode": "delegate"
|
"Bash(find:*)",
|
||||||
|
"Bash(for:*)",
|
||||||
|
"Bash(do sed:*)",
|
||||||
|
"Bash(done)",
|
||||||
|
"Bash(python3:*)",
|
||||||
|
"Bash(while read f)",
|
||||||
|
"Bash(do echo \"$f%-* $f\")",
|
||||||
|
"Bash(ls:*)",
|
||||||
|
"Bash(node:*)",
|
||||||
|
"Bash(pm2 delete:*)",
|
||||||
|
"Bash(pm2 start npm:*)",
|
||||||
|
"Bash(pm2 save:*)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user