# `.claude.json` settings keep getting wiped Claude Code intermittently erases configurations from `~/.claude.json` — no error, no warning, settings just gone. Set up a launchd file watcher to catch it in the act. ## The watcher `~/Library/LaunchAgents/com.user.watch-claude-json.plist` — copies a timestamped snapshot into `~/.claude/backups/` on every write to the file. ```xml Label com.user.watch-claude-json ProgramArguments /bin/bash -c cp ~/.claude.json ~/.claude/backups/claude-json-$(date +%Y%m%d-%H%M%S).json WatchPaths /Users/user/.claude.json ``` ## Scripts **`diff-backups.sh`** — diffs consecutive snapshots and pipes into `diffnav`: ```bash #!/usr/bin/env bash set -euo pipefail BACKUP_DIR="${1:-$(dirname "$0")}" mapfile -t files < <(ls -1 "$BACKUP_DIR"/claude-json-*.json 2>/dev/null | sort) if [[ ${#files[@]} -lt 2 ]]; then echo "Need at least 2 backup files to diff." exit 1 fi combined="" for ((i = 0; i < ${#files[@]} - 1; i++)); do older="${files[$i]}" newer="${files[$i + 1]}" older_name=$(basename "$older") newer_name=$(basename "$newer") chunk=$(diff -u --label "a/${older_name}" --label "b/${newer_name}" "$older" "$newer" 2>/dev/null || true) if [[ -n "$chunk" ]]; then combined+="${chunk} " fi done if [[ -z "$combined" ]]; then echo "No differences found between any consecutive backups." exit 0 fi echo "$combined" | diffnav ``` **`prune-backups.sh`** — removes snapshots identical to the previous one (`DRY_RUN=true` to preview): ```bash #!/usr/bin/env bash set -euo pipefail BACKUP_DIR="${1:-$(dirname "$0")}" DRY_RUN="${DRY_RUN:-false}" mapfile -t files < <(ls -1 "$BACKUP_DIR"/claude-json-*.json 2>/dev/null | sort) if [[ ${#files[@]} -lt 2 ]]; then echo "Need at least 2 backup files to compare." exit 0 fi removed=0 for ((i = 1; i < ${#files[@]}; i++)); do prev="${files[$i - 1]}" curr="${files[$i]}" if cmp -s "$prev" "$curr"; then if [[ "$DRY_RUN" == "true" ]]; then echo "[dry-run] would remove $(basename "$curr") (same as $(basename "$prev"))" else echo "Removing $(basename "$curr") (same as $(basename "$prev"))" rm "$curr" fi removed=$((removed + 1)) fi done if [[ "$DRY_RUN" == "true" ]]; then echo "Done. ${removed} duplicate(s) would be removed." else echo "Done. ${removed} duplicate(s) removed." fi ```