#!/bin/bash # Agent Factory — import-system.sh # Imports an exported agent system tarball into the current project. # Usage: bash import-system.sh [--force] # Bash 3.2 compatible. set -e TARBALL="$1" FORCE="${2:-}" STAGING_DIR="/tmp/agent-import-$$" if [ -z "$TARBALL" ]; then echo "Usage: bash import-system.sh [--force]" >&2 exit 1 fi if [ ! -f "$TARBALL" ]; then echo "ERROR: File not found: $TARBALL" >&2 exit 1 fi echo "[import] Importing: $TARBALL" mkdir -p "$STAGING_DIR" tar -xzf "$TARBALL" -C "$STAGING_DIR" # Read MANIFEST.md MANIFEST="${STAGING_DIR}/MANIFEST.md" if [ ! -f "$MANIFEST" ]; then echo "ERROR: No MANIFEST.md found in tarball — may not be a valid Agent Factory export" >&2 rm -rf "$STAGING_DIR" exit 1 fi echo "[import] Manifest found:" head -5 "$MANIFEST" echo "" # Check for conflicts (existing files in destination) CONFLICTS="" find "$STAGING_DIR" -type f | sort | while read -r fpath; do rel="${fpath#${STAGING_DIR}/}" dest="${PWD}/${rel}" if [ -f "$dest" ] && [ "$FORCE" != "--force" ]; then echo "[import] CONFLICT: $rel already exists" CONFLICTS="yes" fi done if [ -n "$CONFLICTS" ] && [ "$FORCE" != "--force" ]; then echo "" echo "Conflicts detected. Re-run with --force to overwrite, or remove conflicting files first." >&2 rm -rf "$STAGING_DIR" exit 1 fi # Extract files to project echo "[import] Extracting files" find "$STAGING_DIR" -type f | sort | while read -r fpath; do rel="${fpath#${STAGING_DIR}/}" dest="${PWD}/${rel}" destdir="$(dirname "$dest")" mkdir -p "$destdir" cp "$fpath" "$dest" echo "[import] Wrote: $rel" done # Replace {{PLACEHOLDER}} variables echo "[import] Replacing placeholders" PROJECT_DIR="$(pwd)" PROJECT_NAME="$(basename "$PROJECT_DIR")" find "$PROJECT_DIR/.claude" "$PROJECT_DIR/automation" "$PROJECT_DIR/hooks" \ "$PROJECT_DIR/CLAUDE.md" -type f 2>/dev/null | while read -r fpath; do case "$fpath" in *.sh|*.md|*.json|*.yml|*.yaml) python3 - "$fpath" "$PROJECT_DIR" "$PROJECT_NAME" << 'PYEOF' import sys, re path, project_dir, project_name = sys.argv[1], sys.argv[2], sys.argv[3] try: with open(path, 'r', encoding='utf-8') as f: content = f.read() content = content.replace('{{PROJECT_DIR}}', project_dir) content = content.replace('{{PROJECT_NAME}}', project_name) with open(path, 'w', encoding='utf-8') as f: f.write(content) except Exception: pass PYEOF ;; esac done # Make .sh files executable echo "[import] Setting executable permissions" find "$PROJECT_DIR/.claude/hooks" "$PROJECT_DIR/hooks" "$PROJECT_DIR/automation" \ -name "*.sh" -type f 2>/dev/null | while read -r fpath; do chmod +x "$fpath" echo "[import] chmod +x: $fpath" done # Validate frontmatter in agent files echo "[import] Validating agent frontmatter" INVALID_AGENTS="" if [ -d "$PROJECT_DIR/.claude/agents" ]; then for agent in "$PROJECT_DIR/.claude/agents"/*.md; do [ -f "$agent" ] || continue python3 - "$agent" << 'PYEOF' import sys, re path = sys.argv[1] try: with open(path, 'r') as f: content = f.read() if not content.startswith('---'): print(f"WARN: {path} missing YAML frontmatter") sys.exit(0) parts = content.split('---', 2) if len(parts) < 3: print(f"WARN: {path} malformed frontmatter") except Exception as e: print(f"WARN: {path} could not be validated: {e}") PYEOF done fi # Validate bash syntax on hook scripts echo "[import] Validating hook syntax" if [ -d "$PROJECT_DIR/.claude/hooks" ]; then for script in "$PROJECT_DIR/.claude/hooks"/*.sh; do [ -f "$script" ] || continue if bash -n "$script" 2>/dev/null; then echo "[import] OK: $script" else echo "[import] WARN: $script failed bash -n check" fi done fi rm -rf "$STAGING_DIR" echo "" echo "[import] Import complete." echo "[import] Next steps:" echo " 1. Review CLAUDE.md and update project-specific sections" echo " 2. Add your ANTHROPIC_API_KEY to .env" echo " 3. Run /agent-factory:status to verify the system"