Skip to content

TOOL enhance, feat: Add diff, backup --user-only, and migrate --auto for safer PAI release updates #973

@sauldataman

Description

@sauldataman

Problem

Updating PAI to a new release currently requires manual effort and carries risk of losing user data.

1. The migrate command misses most user data

Running migrate on a backup only identifies:

  • _-prefixed skills (most users don't use this convention)
  • Settings identity fields
  • MEMORY subdirectory names

It completely misses:

  • PAI/USER/ content (TELOS, identity, contacts, security patterns)
  • Non-prefixed custom skills, Packs installed after setup
  • User-modified system files (tweaked hooks, skills)
  • projects/ (Claude Code auto-memory), user knowledge bases, user-generated skills, installed Packs, plugins
  • settings.json hook/statusLine customizations
  • Claude Code generated data (file-history/, Plans/, tasks/, History/)

And it only produces a text report — it doesn't actually restore anything. Users must manually copy files from the backup.

2. No way to preview what a release update will change

Users run cp -r new-release/.claude ~/ blindly. There's no way to see which local files will be overwritten, which are unchanged, or which are new — until after it's done.

3. No automated restore after release update

After cp -r overwrites files, users must manually find their modifications in the backup directory and copy them back. This is error-prone and tedious, especially for users who have customized hooks, skills, or PAI/USER/ content.

Related: #893 (settings.json overwrite during update)

Proposed Solution

Three new capabilities added to the existing Tools/BackupRestore.ts. All existing commands (backup, restore, list, migrate) are completely unchanged.

1. diff --release <path> — Preview before updating

Compare every file in a release against the local ~/.claude/ using SHA-256 hashes:

bun Tools/BackupRestore.ts diff --release ./Releases/v4.1.0/.claude

Shows:

  • New files — in the release but not locally (will be added)
  • Unchanged — identical content (safe to overwrite)
  • Conflicts — exist locally with different content (user modifications that will be lost)

Automatically excludes from conflict reporting:

  • PAI/USER/*, MEMORY/* — always user data, always preserved separately
  • settings.json — always preserved separately, handled by install.sh merge
  • PAI-Install/* — always replaced by release
  • CLAUDE.md — regenerated by BuildCLAUDE.ts

2. backup --user-only --release <path> — Smart backup

Back up only user data, using the release directory as reference:

bun Tools/BackupRestore.ts backup --user-only --release ./Releases/v4.1.0/.claude

Captures three categories:

  1. Always-backup dataPAI/USER/*, MEMORY/*, settings.json, CLAUDE.md
  2. Modified system files — files in the release that the user has changed (SHA-256 differs)
  3. User-generated files — everything in ~/.claude/ that doesn't exist in the release (user-generated skills, installed Packs, knowledge bases, projects/ with Claude Code auto-memory, plugins, etc.)

Users can review the diff output first, then exclude specific conflict files they don't want to keep:

bun Tools/BackupRestore.ts backup --user-only --release ./Releases/v4.1.0/.claude \
  --exclude 'skills/SomeSkill/SKILL.md' \
  --exclude 'PAI/SomeDoc.md'

The existing full backup command is unchanged and remains the recommended safety net.

3. migrate --auto — Automated restore

After applying a new release (cp -r), restore user data from a user-only backup:

bun Tools/BackupRestore.ts migrate --auto --release ./Releases/v4.1.0/.claude
  • Automatically finds the latest user-only backup (or specify --backup <path>)
  • Restores all user files on top of the new release
  • Skips CLAUDE.md (regenerated by BuildCLAUDE.ts in the next step)
  • Restores settings.json so that install.sh's merge logic can read the user's existing config

Without --auto, migrate works exactly as before (text analysis report).

Complete Migration Flow

# 1. Full backup (safety net — required)
bun Tools/BackupRestore.ts backup --name "pre-v4.1"

# 2. Preview what the release will change
bun Tools/BackupRestore.ts diff --release ./Releases/v4.1.0/.claude

# 3. Smart backup of user data
bun Tools/BackupRestore.ts backup --user-only --release ./Releases/v4.1.0/.claude

# 4. Apply new release
cp -r ./Releases/v4.1.0/.claude ~/

# 5. Auto-restore user data
bun Tools/BackupRestore.ts migrate --auto --release ./Releases/v4.1.0/.claude

# 6. Merge settings (install.sh reads restored settings.json)
cd ~/.claude && bash install.sh

# 7. Rebuild CLAUDE.md
bun ~/.claude/PAI/Tools/BuildCLAUDE.ts

How It Works

The release directory itself serves as the reference — no manifest file needed.

diff compares each release file against the local copy using SHA-256:

  • Not in local → new file
  • Same hash → unchanged
  • Different hash → conflict (user modified)

backup --user-only collects:

  • Everything in PAI/USER/ and MEMORY/ (explicitly, regardless of release content)
  • settings.json and CLAUDE.md (always)
  • All local files not present in the release (user-generated)
  • Release files where local hash differs (user modifications)

migrate --auto copies the backup contents back into ~/.claude/, skipping only CLAUDE.md which is regenerated by BuildCLAUDE.ts.

Scope of Changes

File Change
Tools/BackupRestore.ts Add diff, backup --user-only, migrate --auto

All existing commands (backup, restore, list, migrate) are unchanged. No new files, no changes to release structure. Usage documentation is included in the tool's built-in help (bun BackupRestore.ts).

Future Work

  • PR 2: Integrate migration flow into install.sh wizard — detect existing user-only backups and offer to restore during installation
  • migrate --auto --dry-run to preview what would be restored
  • Interactive conflict resolution (per-file keep/overwrite choice)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions