--- name: config-audit:rollback description: Restore configuration from backup — list available backups or rollback a specific one argument-hint: "[backup-id]" allowed-tools: Read, Write, Glob, Grep, Bash, AskUserQuestion model: sonnet --- # Config-Audit: Rollback Restore configuration files from a previous backup. Without arguments, lists available backups. With a backup ID, restores files from that backup. ## Arguments - `$ARGUMENTS` may contain a backup ID (format: `YYYYMMDD_HHMMSS`) - `--raw`: pass-through flag accepted for CLI surface consistency. Rollback is file restoration only (no scanner output, no findings prose), so `--raw` is a no-op here, but the flag is still parsed so users get uniform behaviour across the toolchain. ## Behavior ### List mode (no argument) Parse flags and list available backups from `~/.claude/config-audit/backups/`: ```bash RAW_FLAG="" if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi ls -1 ~/.claude/config-audit/backups/ ``` ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Available Backups ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. 20260403_163045 — 3 files (settings.json, hooks.json, typescript.md) 2. 20260403_141230 — 1 file (CLAUDE.md) 3. 20260402_092015 — 5 files (full audit) Usage: /config-audit rollback 20260403_163045 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` Use the Read tool on each backup's `manifest.yaml` (the list of changes captured at backup time) to extract the file list and timestamps. ### Restore mode (with backup ID) 1. Read the list of changes from `~/.claude/config-audit/backups/{backup-id}/manifest.yaml` using the Read tool 2. Classify the `original:` paths before showing them. A restore writes to the absolute path recorded at backup time, which may be machine-wide even when the backup was taken from a project — so the file list must be rendered as the absolute originals, never shortened to a repo-relative-looking form that implies the write stays local: ```bash node ${CLAUDE_PLUGIN_ROOT}/scanners/write-scope-cli.mjs --target "" --target "" --repo "$PWD" --output-file /tmp/config-audit-rollback-scope.json 2>/dev/null; echo $? ``` Exit 0 = classified; 3 = argument error (show the stderr message). Read `/tmp/config-audit-rollback-scope.json`, render each distinct string in `disclosures[]` verbatim, then ask for confirmation. When `requiresApproval` is false: ``` AskUserQuestion: question: "Restore 3 files from backup 20260403_163045?" options: - "Yes, restore" - "Cancel" ``` When `requiresApproval` is true, name the scope and put the safe option first: ``` AskUserQuestion: question: "This restores {K} of 3 files to locations outside this project. Restore all 3?" options: - "Cancel" - "Yes — restore, including outside this project" ``` 3. For each file in the list of changes: a. Read the backup file from `~/.claude/config-audit/backups/{backup-id}/files/{safeName}` b. Write to the original path c. Verify the checksum matches the recorded value in the list of changes 4. Show result: ``` Restored 3 files from backup 20260403_163045 - /abs/path/.claude/settings.json (checksum verified) - /abs/path/hooks/hooks.json (checksum verified) - .claude/rules/typescript.md (checksum verified) ``` 5. **Report what rollback cannot undo.** A backup only holds files that already existed, so files the implement step CREATED survive the restore. If the manifest has a `created:` section (or `restoreBackup()` returns a non-empty `createdNotRemoved`), list those paths and say plainly that they remain: ``` Left in place — created by implement, no backup exists: - .claude/rules/post-quality.md - guidelines/posting-rhythm.md Remove them manually if you want the pre-implement state exactly. ``` Never finish a restore without this section when the list is non-empty; a silently half-restored target reads as a clean rollback. ### Delete mode If user says "delete" after listing, confirm and remove the backup directory. ## Implementation Use the backup and rollback libraries directly: ```javascript import { listBackups, restoreBackup, deleteBackup } from '../scanners/rollback-engine.mjs'; import { parseManifest, getBackupDir } from '../scanners/lib/backup.mjs'; ``` Both read `~/.claude/config-audit/backups` and fall back to the pre-v2.2.0 `~/.config-audit/backups`, so a backup made before the move still resolves; `listBackups()` flags those with `legacy: true`. Prefer this API over ad-hoc `cp` — it verifies the checksum before and after each write. Or via Bash: ```bash # List backups ls -1 ~/.claude/config-audit/backups/ # Read manifest cat ~/.claude/config-audit/backups/{id}/manifest.yaml # Restore (copy back) cp ~/.claude/config-audit/backups/{id}/files/{safeName} {originalPath} ```