Skill: halfdeadcat/gateway-restore (version 1.0.0)

--- name: restore description: Restore a gateway to its last known-good configuration, or tag the current config as known-good. Use when a gateway config change breaks something and you need to roll back fast. Responds to /restore slash command. user-invocable: true --- # Gateway Restore Roll back a gateway config to the last known-good state, then restart safely with health checks and automatic rollback on failure. ## Usage (as slash command or natural language) - `/restore` — restore the Slack gateway to known-good - `/restore discord` — restore the Discord gateway to known-good - `/restore tag` — tag the current Slack config as known-good - `/restore tag discord` — tag the current Discord config as known-good ## How It Works 1. Backs up the current (broken) config with a timestamped filename 2. Copies the `known-good.json` over the live config 3. Runs the appropriate safe restart script (`safe-slack-restart.sh` or `safe-gateway-restart.sh`) 4. The safe restart script validates health and rolls back if the gateway doesn't come up ## Tagging Known-Good After any successful config change + restart, tag the current config: ```bash bash skills/gateway-restore/scripts/gateway-restore.sh slack --tag-current bash skills/gateway-restore/scripts/gateway-restore.sh discord --tag-current ``` This saves it as `config-backups/known-good.json`. Old tagged versions are also kept as `known-good-TIMESTAMP.json`. ## Script Location `skills/gateway-restore/scripts/gateway-restore.sh` ## When Invoked via Slash Command The `command-bypass` hook handles `/restore` slash commands automatically — the script runs detached without LLM involvement. You do NOT need to execute the script. If the hook fires, simply reply confirming the restore is in progress. Do not call exec. ## When Invoked via Natural Language If the user asks to restore via natural language (not a slash command), THEN run the script: ```bash setsid bash /home/swabby/repos/swabby-brain/skills/gateway-restore/scripts/gateway-restore.sh [slack|discord] [--tag-current] > /tmp/restore-output.log 2>&1 & sleep 2 && cat /tmp/restore-output.log ``` Parse the request: - "restore" / "rollback" → slack gateway - "restore discord" → discord gateway - "restore tag" → tag current slack config as known-good If the gateway restarts mid-exec (SIGTERM), that's expected — the restart succeeded.

path: scripts/gateway-restore.sh
content: #!/bin/bash
# Gateway Restore — roll back a gateway to its last known-good config
# Usage: gateway-restore.sh [slack|discord] [--tag-current]
#   slack|discord  — which gateway to restore (default: slack)
#   --tag-current  — instead of restoring, tag the current config as known-good
#
# Exit codes: 0=success, 1=no known-good found, 2=restore+restart failed

set -euo pipefail
export PATH="/home/swabby/.npm-global/bin:/usr/local/bin:/usr/bin:/bin:$PATH"

GATEWAY="${1:-slack}"
ACTION="${2:-restore}"

log() { echo "[$(date '+%H:%M:%S')] $*"; }
err() { echo "[$(date '+%H:%M:%S')] ERROR: $*" >&2; }

case "$GATEWAY" in
  slack)
    CONFIG="$HOME/.openclaw-slack/openclaw.json"
    BACKUP_DIR="$HOME/.openclaw-slack/config-backups"
    RESTART_SCRIPT="$HOME/bin/safe-slack-restart.sh"
    ;;
  discord)
    CONFIG="$HOME/.openclaw/openclaw.json"
    BACKUP_DIR="$HOME/.openclaw/config-backups"
    RESTART_SCRIPT="$HOME/bin/safe-gateway-restart.sh"
    ;;
  *)
    err "Unknown gateway: $GATEWAY (use slack or discord)"
    exit 1
    ;;
esac

KNOWN_GOOD="$BACKUP_DIR/known-good.json"
mkdir -p "$BACKUP_DIR"

# --- Tag current config as known-good ---
if [ "$ACTION" = "--tag-current" ]; then
    cp "$CONFIG" "$KNOWN_GOOD"
    TIMESTAMP=$(date +%Y%m%d-%H%M%S)
    cp "$CONFIG" "$BACKUP_DIR/known-good-${TIMESTAMP}.json"
    log "✅ Current $GATEWAY config tagged as known-good: $KNOWN_GOOD"
    exit 0
fi

# --- Restore ---
if [ ! -f "$KNOWN_GOOD" ]; then
    # Fall back to the oldest *-known-good.json if the standard file doesn't exist
    FALLBACK=$(ls "$BACKUP_DIR"/*known-good*.json 2>/dev/null | sort | head -1 || true)
    if [ -z "$FALLBACK" ]; then
        err "No known-good config found at $KNOWN_GOOD — tag one first with --tag-current"
        exit 1
    fi
    log "Using fallback known-good: $FALLBACK"
    KNOWN_GOOD="$FALLBACK"
fi

log "Restoring $GATEWAY gateway from known-good config..."
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
CURRENT_BACKUP="$BACKUP_DIR/pre-restore-${TIMESTAMP}.json"
cp "$CONFIG" "$CURRENT_BACKUP"
log "Current config backed up to $CURRENT_BACKUP"

cp "$KNOWN_GOOD" "$CONFIG"
log "Known-good config restored. Restarting gateway..."

bash "$RESTART_SCRIPT" "restore to known-good config"
EXIT=$?

if [ $EXIT -eq 0 ]; then
    log "✅ $GATEWAY gateway restored and healthy"
elif [ $EXIT -eq 1 ]; then
    log "⚠️  Restart failed — rolled back to previous config"
    cp "$CURRENT_BACKUP" "$CONFIG"
else
    err "CRITICAL: Restart + rollback failed — check $GATEWAY gateway manually"
fi

exit $EXIT


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)