Architecture
ClipKit is built with SwiftUI and uses JSON-based persistence.
Dependencies
| Package | Version | Purpose |
|---|---|---|
| HotKey | 0.2.0+ | Global keyboard shortcut registration |
Core Components
| Component | Purpose |
|---|---|
| ClipKitApp | App entry point. Creates ClipboardManager as @StateObject and injects via @EnvironmentObject. Provides a Help menu item. |
| ClipboardManager | Central state management. Polls the system clipboard, maintains ephemeral and pinned lists, handles persistence. |
| SettingsManager | App preferences via @AppStorage. Persists UI state (sort mode, filter, grouping) across launches. Publishes polling interval changes via PassthroughSubject. |
| GlobalShortcutManager | Registers the global hotkey using the HotKey library. |
| ClipboardContent | Enum with .text(String) and .image(Data) cases. Implements Codable for JSON persistence. |
| ContentView | Main UI with toolbar controls and two list sections (pinned + ephemeral). |
| LaunchAtLoginHelper | Wraps SMAppService (macOS 13+) for launch-at-login functionality. |
| AccessibilityHelper | Checks accessibility permissions and can prompt/deep-link to System Settings. |
| HelpView | In-app help dialog with feature overview and shortcut reference. |
Data Flow
System Clipboard
|
v
Timer (0.5s polling)
|
v
ClipboardManager
/ \
v v
Ephemeral Pinned
Items Items
| |
v v
ephemeral pinnedItems
Items.json .json
- A timer polls
NSPasteboard.generalevery 0.5 seconds for new content - New content is inserted at the front of
ephemeralItems - Duplicate detection: if content already exists, it's moved to the top instead of duplicated
- Users can pin items, moving them from ephemeral to pinned storage
- Clicking an item calls
restoreToPasteboard()to copy it back to the system clipboard - Pinned items can be reordered via drag-and-drop (in "Most Recent" sort mode)
Data Storage
User data is stored in ~/Library/Application Support/, separate from the app bundle:
~/Library/Application Support/
├── pinnedItems.json # Persistent across reboots
└── ephemeralItems.json # Cleared on reboot
This separation means:
- Updating or reinstalling the app preserves all user data
- Ephemeral items are tied to boot time and discarded on reboot
- Pinned items persist indefinitely
Boot Time Detection
ClipKit uses sysctl with KERN_BOOTTIME to read the system's last boot timestamp. On launch, if the stored boot time differs from the current one, all ephemeral items are cleared. This ensures session-based items don't survive a reboot without requiring a background daemon.
Data Format Migration
When changing the JSON format, ClipKit uses a forward-compatible migration pattern:
- Try decoding the new format first
- Fall back to the old format and migrate if needed
- Save in the new format after successful migration
This ensures users never lose data during app updates.