Commit Graph

9 Commits

Author SHA1 Message Date
Oliver Surke d849400f63 fix: skip dot-paths already declared in Mackup built-in app definitions
Previously ssr-custom cfg generation only checked whether the path was
already in the cloud backup directory.  It did not consult Mackup's
~400 built-in app definitions, causing duplicates like ssr-claude.cfg
when Mackup already has a 'claude-code' entry covering .claude.

Changes:
- _ssr_mackup_declared_paths(): parses all built-in *.cfg files from
  Mackup's Python package apps/ dir + hand-written ~/.mackup/*.cfg
  (excluding our own ssr-*.cfg) into a sorted path set
- generate_custom_cfg now skips any path already in that set
- Stale ssr-*.cfg files that now duplicate a built-in are removed
  automatically on the next sync run

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 11:49:04 +02:00
Oliver Surke b50ab61d5c fix: remove dangling symlinks before mackup backup
shutil.copy fails on dangling symlinks with [Errno 2] No such file or
directory (e.g. ~/.claude/debug/latest → missing target).

Pre-backup cleanup now handles two cases:
  - Unix sockets  (-type s)     → Errno 102
  - Dangling links (-type l !-e) → Errno 2

Both are ephemeral runtime artefacts that cannot be meaningfully backed up.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 11:00:25 +02:00
Oliver Surke 894062adcd refactor: one ~/.mackup/ssr-<name>.cfg per dot-dir instead of combined file
Each discovered dot-dir now gets its own Mackup app definition:
  .claude  → ~/.mackup/ssr-claude.cfg
  .cursor  → ~/.mackup/ssr-cursor.cfg
  .config/gh → ~/.mackup/ssr-config-gh.cfg
  …

This matches Mackup's own convention, keeps definitions independent,
and makes it easy to add/remove individual apps. The old combined
ssr-custom.cfg is removed automatically on the next sync run.

Files are written idempotently (skipped when content is unchanged).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 10:50:42 +02:00
Oliver Surke c6ac73bc83 fix: remove Unix socket files before mackup backup
Mackup fails with shutil.Error [Errno 102] when it tries to copy Unix
socket files (e.g. iTerm2's iterm2-daemon-1.socket, sockets/secrets).
Sockets are ephemeral runtime artefacts — they cannot be meaningfully
backed up and are always recreated by the owning app on startup.

Purge all -type s files from $HOME before calling mackup backup.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 10:43:13 +02:00
Oliver Surke 649449c628 feat: auto-generate ~/.mackup/ssr-custom.cfg for uncovered dot-dirs
Before each `ssr sync`, scan $HOME for dot-dirs/files not yet present
in the Mackup backup directory and write them into
~/.mackup/ssr-custom.cfg. This covers tools like .claude, .cursor,
.easymcp, .codex, .factory, and any future dot-dir without requiring
the user to write manual Mackup app definitions.

Curated list handles common developer tools; auto-discovery adds the
rest while skipping caches, credential dirs (.ssh, .gnupg, .aws,
.azure) and other volatile state.

Configurable via:
  SSR_MACKUP_AUTODISCOVER=true   (opt-out with false)
  SSR_MACKUP_EXTRA_PATHS="..."   (space-separated $HOME-relative paths)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 10:05:16 +02:00
Oliver Surke cf7f61e95d feat: add progress watchdog and iCloud hints to mackup restore
- Pre-materialize iCloud stubs before restore (same as backup)
- Report stub count so user knows why it might be slow
- Background watchdog prints '… still running (Ns elapsed)' every 15s
  so long iCloud download pauses don't look like a hang
- Report total elapsed time on completion

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 22:07:42 +02:00
Oliver Surke 873cb3d51f fix: replace removed brctl download with open -g; add -f to mackup restore
brctl download was removed in macOS Sonoma — the remaining subcommands are
diagnose/log/dump/status/accounts/quota/monitor. Replace the dead call with
a find loop that uses 'open -g <real-path>' to request per-file iCloud
download from the daemon, followed by a 1-second settle pause and the
existing .icloud stub deletion.

Also add -f to mackup restore for consistency with the backup call.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 21:06:29 +02:00
Oliver Surke a4465f37c6 Improve schedule and mackup reliability
- bin/ssr-schedule: use `launchctl bootstrap`/`bootout` (modern API) with
  legacy `load -w` fallback. The previous `load -w`-only flow silently
  no-op'd on macOS 10.15+ in some configurations, leaving `ssr status`
  reporting `inactive` after a successful `ssr schedule on`.
- bin/ssr-status: query the service via `launchctl print`/`list <label>`
  for consistent active/inactive detection.
- lib/mackup.sh: pre-materialize iCloud placeholders via `brctl download`
  and retry `mackup -f backup` up to three times to dodge the recurring
  `OSError [Errno 66] Directory not empty` race between mackup's rmtree
  and iCloud's filesystem provider. Soft-fails so the rest of `ssr sync`
  still runs even if mackup never settles; logs actionable hints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 18:02:31 +02:00
Oliver Surke 539a8fc28f Initial ssr repository
Convert the legacy system_sync.sh and system_restore.sh into a modular
shareable repository:

- bin/ssr CLI dispatcher with install/sync/restore/schedule/config/status
- lib/ split: common, cloud, brew, mackup, macos
- Cloud provider abstraction (icloud, dropbox, googledrive, onedrive, custom)
- launchd template for scheduled daily sync (renderable via sed)
- ssr.conf.example with whitelisted KEY=VALUE config loader
- macos-defaults.sh extracted from inline block, overridable
- install.sh bootstrap symlinks CLI into ~/.local/bin
- README with usage, config table, migration map, security notes
- Original scripts archived under legacy/ for reference

Fixes vs originals: set -euo pipefail, quoted vars, find -print0,
spctl --global-disable (was --master-disable), MACOS=".macos" bug,
zero-width char before ln, Apple Silicon brew shellenv, config injection
hardening.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 15:05:17 +02:00