this repo has no description

Add claude file

+178
+178
CLAUDE.md
··· 1 + # CLAUDE.md 2 + 3 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 + 5 + ## Project Overview 6 + 7 + AtProtoBackup is a multi-platform (iOS, macOS) SwiftUI application for backing up AT Protocol (Bluesky) accounts. It downloads repository snapshots (CAR files) and associated blobs (images, videos, etc.) from AT Protocol Personal Data Servers (PDS), storing them in the user's Documents/backups/ directory for safekeeping and portability. 8 + 9 + ## Build Commands 10 + 11 + This project uses `just` (justfile) for build automation. The Justfile is located at the project root. 12 + 13 + ### Common Commands 14 + 15 + ```bash 16 + # List all available commands 17 + just 18 + 19 + # Build for iOS Simulator (iPhone 16 Pro, iOS 18.6) 20 + just build-ios-simulator 21 + 22 + # Build for macOS 23 + just build-mac 24 + 25 + # Build for all platforms 26 + just build-all 27 + 28 + # Run tests on iOS Simulator 29 + just test-ios 30 + 31 + # Run tests on macOS 32 + just test-mac 33 + 34 + # Run all tests 35 + just test-all 36 + 37 + # Clean build artifacts 38 + just clean 39 + 40 + # Open project in Xcode 41 + just xcode 42 + ``` 43 + 44 + ### Direct xcodebuild Commands 45 + 46 + If you need to customize build commands: 47 + 48 + ```bash 49 + # Build for iOS Simulator 50 + xcodebuild build \ 51 + -project AtProtoBackup.xcodeproj \ 52 + -scheme AtProtoBackup \ 53 + -destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.6' \ 54 + -configuration Debug 55 + 56 + # Build for macOS 57 + xcodebuild build \ 58 + -project AtProtoBackup.xcodeproj \ 59 + -scheme AtProtoBackup \ 60 + -destination 'platform=macOS' \ 61 + -configuration Debug 62 + 63 + # Run tests 64 + xcodebuild test \ 65 + -project AtProtoBackup.xcodeproj \ 66 + -scheme AtProtoBackup \ 67 + -destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.6' 68 + ``` 69 + 70 + ## Architecture Overview 71 + 72 + ### Data Flow 73 + 74 + 1. **Account Discovery**: Users add accounts by handle → `ATProtocolService` resolves DID → `Account` model created 75 + 2. **Backup Discovery**: On launch, `BackupDiscovery` scans Documents/backups/ for existing backups and auto-adds them to the account list 76 + 3. **Download Process**: 77 + - `DownloadManager` orchestrates the backup 78 + - `BlobDownloader` handles HTTP downloads using background URLSession 79 + - Downloads CAR file first (repository snapshot) 80 + - Lists all blob CIDs via `listBlobs` API 81 + - Downloads blobs concurrently with background-safe URLSession 82 + - `BackupMetadata` tracks completion and device info 83 + 4. **Progress Tracking** (iOS only): Live Activities show real-time download progress via `BackgroundDownloadTracker` 84 + 85 + ### Core Components 86 + 87 + #### Data Layer 88 + - **Account.swift**: SwiftData model for account storage (DID, handle, PDS URL) 89 + - **BackupMetadata.swift**: Codable struct tracking backup completion time, blob counts, device info, duration 90 + - **BackupDiscovery.swift**: Discovers existing backups in Documents/backups/{did}/ directories 91 + 92 + #### Service Layer 93 + - **ATProtocolService.swift**: Resolves handles to DIDs via slingshot.microcosm.blue API 94 + - **BlobDownloader.swift**: Actor-based concurrent blob downloader using background URLSession for app suspension resilience. Implements retry logic, semaphore-based concurrency control, and skip-if-exists optimization. 95 + - **DownloadManager.swift**: Orchestrates full backup process (CAR download → list blobs → download blobs → save metadata). Manages Live Activities on iOS. 96 + 97 + #### UI Layer 98 + - **ContentView.swift**: Main account list with master-detail navigation 99 + - **AccountDetailView.swift**: Shows account info and backup controls 100 + - **AccountListItemView.swift**: Individual account row in list 101 + - **DownloadSection.swift**: Download button and progress UI 102 + 103 + #### Platform-Specific (iOS only) 104 + - **LiveActivityManager.swift**: Checks Live Activity permissions 105 + - **BackgroundDownloadTracker.swift**: MainActor class that batches Live Activity updates (every 10 blobs) to reduce overhead 106 + - **DownloadActivityAttributes.swift**: Defines Live Activity state and attributes 107 + - **AppDelegate.swift**: Handles background URL session events 108 + - **WidgetExtension/**: iOS Live Activity widget implementation 109 + 110 + ### Multi-Platform Considerations 111 + 112 + The app uses `#if os(iOS)` preprocessor directives to conditionally compile iOS-specific features: 113 + - Live Activities and ActivityKit 114 + - UIKit-based device info (battery, device model) 115 + - Background download event handling via AppDelegate 116 + 117 + macOS builds exclude these features but share the core download and backup logic. 118 + 119 + ### Dependencies 120 + 121 + Swift Package Manager dependencies (in Xcode project): 122 + - **ATProtoKit**: AT Protocol Swift SDK for API interactions (repo syncing, blob listing) 123 + - **ZIPFoundation**: (Currently unused but available for future archive compression) 124 + 125 + ### File Storage Structure 126 + 127 + ``` 128 + ~/Documents/backups/ 129 + └── {did}/ 130 + ├── backup-metadata.json # Backup completion info 131 + ├── {handle}-{timestamp}.car # Repository snapshot 132 + └── {cid}.{ext} # Individual blobs (images, videos, etc.) 133 + ``` 134 + 135 + ### Background Download Strategy 136 + 137 + `BlobDownloader` uses `URLSession.background` with identifier `com.app.atproto.backup.downloader`. This allows: 138 + - Downloads continue when app is suspended/backgrounded 139 + - App wakes when downloads complete 140 + - Automatic reconnection to in-progress downloads after app restart 141 + 142 + Progress updates are batched (every 10 blobs) to minimize main thread overhead and Live Activity update frequency. 143 + 144 + ### Error Handling 145 + 146 + - **ATProtocolError**: API and network errors (invalidURL, invalidResponse, decodingError) 147 + - **BlobDownloadError**: HTTP errors, network failures, retry exhaustion 148 + - **BackupError**: File system errors (documentsDirectoryNotFound) 149 + - **GenericIntentError**: General error wrapper with custom messages 150 + 151 + Blob downloads implement exponential backoff retry (up to 3 attempts by default) for transient network failures. 152 + 153 + ## Key Implementation Details 154 + 155 + ### Concurrency Model 156 + - `BlobDownloader` is an `actor` for thread-safe concurrent downloads 157 + - Uses async/await throughout for asynchronous operations 158 + - `BackgroundDownloadTracker` is `@MainActor` to safely update Live Activities 159 + - TaskGroup pattern for managing concurrent blob downloads 160 + 161 + ### SwiftData Usage 162 + - `Account` is a `@Model` for persistent storage 163 + - `modelContainer` configured with in-memory storage (Note: This means accounts don't persist between app launches!) 164 + - SwiftUI `@Query` used in ContentView for reactive account list 165 + 166 + ### Security-Scoped Resources 167 + - Uses bookmark data to maintain access to user-selected save locations 168 + - Properly calls `startAccessingSecurityScopedResource()` / `stopAccessingSecurityScopedResource()` 169 + 170 + ### Download Skipping 171 + - Before downloading each blob, checks if file with matching CID basename already exists 172 + - Returns `wasNewDownload: Bool` to track incremental vs full backups 173 + 174 + ## Testing Notes 175 + 176 + - Unit tests: AtProtoBackupTests/ 177 + - UI tests: AtProtoBackupUITests/ 178 + - Tests currently minimal; expand coverage when modifying core download/backup logic