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:
uroma
2026-01-23 18:23:28 +00:00
Unverified
parent 62bec9d554
commit 932529d37f
21 changed files with 1439 additions and 898 deletions

View File

@@ -1,270 +1,246 @@
#!/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
################################################################################
# Claude Code Agents Sync Script
# Syncs local agents with GitHub repository and backs up to Gitea
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'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
NC='\033[0m' # No Color
# 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"
# Logging function
log() {
local level=$1
shift
local message="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
# Print colored message
print_msg() {
local color=$1
shift
echo -e "${color}$*${NC}"
}
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"
# Create backup
create_backup() {
print_msg "$BLUE" "📦 Creating backup..."
if cp -r "$AGENTS_DIR" "$BACKUP_DIR"; then
print_msg "$GREEN" "✓ Backup created: $BACKUP_DIR"
log "INFO" "Backup created at $BACKUP_DIR"
else
log_warn "jq not found. Cannot parse config file."
log_info "Install jq: sudo apt-get install jq"
return 1
print_msg "$RED" "✗ Failed to create backup"
log "ERROR" "Backup creation failed"
exit 1
fi
}
sync_default_sources() {
log_step "Syncing from default sources"
# Download upstream agents
download_upstream() {
print_msg "$BLUE" "📥 Downloading agents from $GITHUB_REPO..."
mkdir -p "$TEMP_DIR"
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"
if command -v git &> /dev/null; then
# Use git if available (faster)
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
}
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
# 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"
local total_changes=$((${#new_agents[@]} + ${#updated_agents[@]}))
log "INFO" "Sync complete: ${#new_agents[@]} new, ${#updated_agents[@]} updated, ${#custom_agents[@]} preserved"
}
# 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 "$@"