#!/usr/bin/env bash # sync.sh - Deploy last30days skill to all host locations # Usage: bash skills/last30days/scripts/sync.sh (run from repo root) set -euo pipefail SRC="$(cd "$(dirname "$0")/.." && pwd)" echo "Source: $SRC" COMMON_TARGETS=( # Claude Code plugin cache for this (public) repo's marketplace install. # Marketplace name = last30days-skill (.claude-plugin/marketplace.json). # Plugin name = last30days (.claude-plugin/plugin.json). # Path shape = .../cache/{marketplace-name}/{plugin-name}/{version}. # Marketplace pulls overwrite this on update; local sync keeps it fresh # against the working tree so /last30days reflects local dev without # waiting for a release. Do NOT add ~/.claude/skills/last30days - it # creates a duplicate slash-command entry alongside the plugin version. "$HOME/.claude/plugins/cache/last30days-skill/last30days/3.2.2" "$HOME/.agents/skills/last30days" "$HOME/.codex/skills/last30days" ) OPENCLAW_TARGET="$HOME/.openclaw/skills/last30days" sync_target() { local target="$1" local skill_md="$2" echo "" echo "--- Syncing to $target ---" mkdir -p "$target/scripts/lib" cp "$skill_md" "$target/SKILL.md" rsync -a \ "$SRC/scripts/last30days.py" \ "$SRC/scripts/watchlist.py" \ "$SRC/scripts/briefing.py" \ "$SRC/scripts/store.py" \ "$target/scripts/" rsync -a "$SRC/scripts/lib/"*.py "$target/scripts/lib/" # The OpenClaw variant lives in the private repo only. Skip cleanly when # running this script from the public repo where variants/open does not exist. if [ -d "$SRC/variants/open" ]; then mkdir -p "$target/variants/open/references" rsync -a "$SRC/variants/open/" "$target/variants/open/" fi if [ -d "$SRC/scripts/lib/vendor" ]; then rsync -a "$SRC/scripts/lib/vendor" "$target/scripts/lib/" fi if [ -d "$SRC/fixtures" ]; then mkdir -p "$target/fixtures" rsync -a "$SRC/fixtures/" "$target/fixtures/" fi mod_count=$(ls "$target/scripts/lib/"*.py 2>/dev/null | wc -l | tr -d ' ') echo " Copied $mod_count modules" if ( cd "$target/scripts" && python3 -c "import briefing, store, watchlist; from lib import youtube_yt, bird_x, render, ui; print(' Import check: OK')" ); then true else echo " Import check FAILED" fi } for t in "${COMMON_TARGETS[@]}"; do sync_target "$t" "$SRC/SKILL.md" done # Hermes sync: deploy to Hermes skills directory if it exists HERMES_TARGET="$HOME/.hermes/skills/research/last30days" if [ -d "$HOME/.hermes/skills/research" ]; then echo "" echo "--- Syncing to Hermes ---" mkdir -p "$HERMES_TARGET/scripts/lib" cp "$SRC/SKILL.md" "$HERMES_TARGET/SKILL.md" rsync -a \ "$SRC/scripts/last30days.py" \ "$SRC/scripts/watchlist.py" \ "$SRC/scripts/briefing.py" \ "$SRC/scripts/store.py" \ "$HERMES_TARGET/scripts/" rsync -a "$SRC/scripts/lib/"*.py "$HERMES_TARGET/scripts/lib/" if [ -d "$SRC/scripts/lib/vendor" ]; then rsync -a "$SRC/scripts/lib/vendor" "$HERMES_TARGET/scripts/lib/" fi if [ -d "$SRC/fixtures" ]; then mkdir -p "$HERMES_TARGET/fixtures" rsync -a "$SRC/fixtures/" "$HERMES_TARGET/fixtures/" fi mod_count=$(ls "$HERMES_TARGET/scripts/lib/"*.py 2>/dev/null | wc -l | tr -d ' ') echo " Copied $mod_count modules to Hermes" if ( cd "$HERMES_TARGET/scripts" && python3 -c "import briefing, store, watchlist; from lib import youtube_yt, bird_x, render, ui; print(' Import check: OK')" ); then true else echo " Import check FAILED" fi fi # OpenClaw sync only runs when the private-repo OpenClaw variant is present # in the source tree. The public repo does not ship variants/open (the variant # is sanitized via strip_for_openclaw.py and published separately from # last30days-skill-private). if [ -d "$SRC/variants/open" ]; then sync_target "$OPENCLAW_TARGET" "$SRC/variants/open/SKILL.md" else echo "" echo "Skipping OpenClaw target (no variants/open in this repo)" fi echo "" echo "Sync complete."