Added all directories and files expected by supercharge.sh: - hooks/ (5 hook scripts for session management and AI consultation) - commands/ (3 custom slash commands: brainstorm, write-plan, execute-plan) - plugins/ (plugin references for glm-plan, rust-analyzer, marketplaces) - bin/ralphloop (Ralph Orchestrator wrapper for autonomous iteration) - scripts/sync-agents.sh (agent synchronization script) - templates/ (config templates: settings, hooks, config.json) This completes the repository structure so supercharge.sh can install all components without warnings. Co-Authored-By: Claude <noreply@anthropic.com>
271 lines
6.8 KiB
Bash
Executable File
271 lines
6.8 KiB
Bash
Executable File
#!/bin/bash
|
|
################################################################################
|
|
# sync-agents.sh - Agent Synchronization Script
|
|
################################################################################
|
|
# 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
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
# Directories
|
|
CLAUDE_DIR="${HOME}/.claude"
|
|
AGENTS_DIR="${CLAUDE_DIR}/agents"
|
|
CONFIG_FILE="${AGENTS_DIR}/sync-sources.json"
|
|
|
|
# Flags
|
|
FORCE=false
|
|
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() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
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
|
|
log_warn "jq not found. Cannot parse config file."
|
|
log_info "Install jq: sudo apt-get install jq"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
sync_default_sources() {
|
|
log_step "Syncing from default sources"
|
|
|
|
for source in "${DEFAULT_SOURCES[@]}"; do
|
|
sync_from_source "$source" "main"
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
# 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
|
|
sync_default_sources
|
|
fi
|
|
|
|
# Summary
|
|
local total_agents
|
|
total_agents=$(find "$AGENTS_DIR" -mindepth 1 -maxdepth 1 -type d | wc -l)
|
|
|
|
log_success "Agent sync complete!"
|
|
log_info "Total agents in $AGENTS_DIR: $total_agents"
|
|
}
|
|
|
|
# Run main
|
|
main "$@"
|