Pipeline that pulls VoltAgent/awesome-codex-subagents and converts TOML agent definitions to Claude Code plugin marketplace format. Includes SHA-256 hash-based incremental updates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
102 lines
2.5 KiB
Bash
Executable File
102 lines
2.5 KiB
Bash
Executable File
#!/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."
|