#!/bin/bash # sync.sh — Pull VoltAgent/awesome-codex-subagents and convert to Claude Code plugin marketplace # Usage: ./sync.sh [--dry-run] [--force] [--verbose] set -euo pipefail SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" UPSTREAM_DIR="${SCRIPT_DIR}/upstream" UPSTREAM_REPO="https://github.com/VoltAgent/awesome-codex-subagents" OUTPUT_DIR="${SCRIPT_DIR}/plugins" MANIFEST="${SCRIPT_DIR}/codex-manifest.json" DRY_RUN="" FORCE=false VERBOSE="" usage() { echo "Usage: $(basename "$0") [--dry-run] [--force] [--verbose]" echo "" echo "Pull upstream Codex agent definitions and convert to Claude Code plugins." echo "" echo "Options:" echo " --dry-run Print what would happen without writing files" echo " --force Re-run converter even if upstream hasn't changed" echo " --verbose Print per-file conversion status" echo " --help Show this help message" } log() { echo "[$(date '+%H:%M:%S')] $*" >&2 } while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN="--dry-run" shift ;; --force) FORCE=true shift ;; --verbose) VERBOSE="--verbose" shift ;; --help) usage exit 0 ;; *) echo "Unknown option: $1" >&2 usage exit 1 ;; esac done # Clone or pull upstream if [[ -d "${UPSTREAM_DIR}/.git" ]]; then log "Pulling upstream updates..." git -C "$UPSTREAM_DIR" pull --ff-only else log "Cloning upstream repo..." git clone "$UPSTREAM_REPO" "$UPSTREAM_DIR" fi CURRENT_COMMIT=$(git -C "$UPSTREAM_DIR" rev-parse --short HEAD) log "Upstream at commit ${CURRENT_COMMIT}" # Check manifest for skip if [[ "$FORCE" == false && -f "$MANIFEST" ]]; then LAST_COMMIT=$(python3 -c "import json; m=json.load(open('${MANIFEST}')); print(m.get('upstream_commit',''))" 2>/dev/null || echo "") if [[ "$LAST_COMMIT" == "$CURRENT_COMMIT" ]]; then log "Already up to date (commit ${CURRENT_COMMIT}). Use --force to re-run." exit 0 fi fi # Run converter log "Converting agents..." python3 "${SCRIPT_DIR}/convert.py" \ "${UPSTREAM_DIR}/categories" \ "${OUTPUT_DIR}" \ --manifest "${MANIFEST}" \ ${DRY_RUN} \ ${VERBOSE} # Update manifest with commit hash (converter writes the rest) if [[ -z "$DRY_RUN" && -f "$MANIFEST" ]]; then python3 -c " import json from pathlib import Path p = Path('${MANIFEST}') m = json.loads(p.read_text()) m['upstream_commit'] = '${CURRENT_COMMIT}' p.write_text(json.dumps(m, indent=2) + '\n') " log "Manifest updated with commit ${CURRENT_COMMIT}" fi log "Done."