#!/usr/bin/env bash # Sync OpenClaw custom skills between docker-test:/opt/openclaw and local openclaw-skills. # Run from this directory. Uses scp (rsync not available on docker-test). set -euo pipefail REMOTE="${REMOTE:-docker-test}" OPENCLAW_BASE="/opt/openclaw" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" # Runtime files to exclude from sync (tokens, cache, state) EXCLUDE_PATTERNS=( "state.json" "seen-connections.json" "authorized-ips.json" "memory" "*.bak" ) # Skills to skip during pull (duplicates or deprecated versions on remote) SKIP_SKILLS=( "workspace-home/monitor-unauthorized" # superseded by workspace-security version ) usage() { cat < $local_path" mkdir -p "$local_path" scp -r "${REMOTE}:${OPENCLAW_BASE}/${remote_path}/"* "$local_path/" 2>/dev/null || true } push_skill_dir() { local local_path="$1" local remote_path="$2" echo "Pushing $local_path -> $remote_path" ssh "$REMOTE" "mkdir -p ${OPENCLAW_BASE}/${remote_path}" for skill in "$local_path"/*/; do [ -d "$skill" ] || continue skill_name="$(basename "$skill")" scp -r "$skill" "${REMOTE}:${OPENCLAW_BASE}/${remote_path}/" done } remove_runtime_files() { find . -name 'state.json' -delete 2>/dev/null || true find . -name 'seen-connections.json' -delete 2>/dev/null || true find . -name 'authorized-ips.json' -delete 2>/dev/null || true find . -type d -name 'memory' -exec rm -rf {} + 2>/dev/null || true find . -name '*.bak' -delete 2>/dev/null || true } remove_skipped_skills() { for skip in "${SKIP_SKILLS[@]}"; do if [ -d "$skip" ]; then echo " Removing skipped skill: $skip" rm -rf "$skip" fi done } pull() { echo "=== Pulling skills from $REMOTE ===" pull_skill_dir "workspace/skills" "workspace" pull_skill_dir "state/workspace-security/skills" "workspace-security" pull_skill_dir "state/workspace-home/skills" "workspace-home" pull_skill_dir "state/extensions/openclaw-plugin-vt-sentinel/skills" "extensions" remove_runtime_files remove_skipped_skills echo "Done. Run 'git status' to see changes." } push() { echo "=== Pushing skills to $REMOTE ===" push_skill_dir "workspace" "workspace/skills" push_skill_dir "workspace-security" "state/workspace-security/skills" push_skill_dir "workspace-home" "state/workspace-home/skills" push_skill_dir "extensions" "state/extensions/openclaw-plugin-vt-sentinel/skills" echo "Done. Restart OpenClaw or start a new session to pick up changes." } main() { local direction="${1:-pull}" case "$direction" in pull) pull ;; push) push ;; -h|--help) usage ;; *) echo "Unknown direction: $direction"; usage; exit 1 ;; esac } main "$@"