# Open project
cd ~/dev/ClipQueue
open ClipQueue.xcodeproj
# Build in Xcode (Cmd+B)
# Then deploy to stable location:
./rebuild_stable.shProblem: Every time Xcode rebuilds, the app gets a new signature. macOS treats it as a "different" app and revokes Accessibility permissions.
Solution: Copy the build to ~/Applications/ClipQueue.app after each rebuild. This location stays stable, so permissions persist.
- Make changes in Xcode
- Build with
Cmd+B(don't useCmd+R- it runs from DerivedData) - Deploy with
./rebuild_stable.sh - Test - the app launches from
~/Applications/
Copies latest Xcode build to ~/Applications/ClipQueue.app and launches it.
./rebuild_stable.shRemoves old DerivedData builds to prevent confusion in Accessibility settings.
./cleanup_old_builds.sh- Build and run
./rebuild_stable.sh - Open System Settings → Privacy & Security → Accessibility
- Click
+button - Navigate to:
/Users/YOUR_USERNAME/Applications/ClipQueue.app - Add it and toggle ON
If you used ./rebuild_stable.sh, permissions should persist. If not:
- Remove ALL ClipQueue entries from Accessibility settings
- Close and reopen System Settings
- Add the one from
~/Applications/ClipQueue.app(look for today's date) - Toggle ON
This happens when:
- Old DerivedData builds still exist
- You added the wrong location
Fix: Run ./cleanup_old_builds.sh and re-add from ~/Applications/
Check console for: ⚠️ Accessibility permissions not granted!
Fix: Follow Accessibility setup steps above
When adding to Accessibility, you might see multiple ClipQueue apps. Choose the one:
- From
/Users/YOUR_USERNAME/Applications/ - With today's date
- NOT from DerivedData
ClipQueue/
├── Sources/
│ ├── ClipQueue/
│ │ ├── ClipQueueApp.swift # Main entry point
│ │ ├── AppDelegate.swift # Window/menu bar management
│ │ └── Assets.xcassets/ # App icons
│ ├── Models/
│ │ ├── ClipboardItem.swift # Queue item model
│ │ └── Preferences.swift # Settings model
│ ├── Services/
│ │ ├── ClipboardMonitor.swift # Polls NSPasteboard
│ │ ├── QueueManager.swift # FIFO queue logic
│ │ └── KeyboardShortcutManager.swift # Carbon hotkeys + paste simulation
│ └── Views/
│ ├── QueueView.swift # Main window UI
│ └── PreferencesView.swift # Settings UI
├── ClipQueue.xcodeproj/
├── Info.plist # LSUIElement = true (menu bar only)
├── rebuild_stable.sh # Deploy script
├── cleanup_old_builds.sh # Cleanup script
└── README.md
- Polls
NSPasteboard.generalevery 0.5 seconds - Compares
changeCountto detect new copies - Only captures text (images not yet supported)
- New items:
items.append(item)(added to end) - Paste:
items.removeFirst()(remove from front) - Display: Index 0 (oldest) shown at top
- Uses Carbon API (
RegisterEventHotKey) - Requires Accessibility permissions for key simulation
- Simulates
Cmd+CandCmd+VusingCGEvent
- AppKit
NSWindowwith.floatinglevel (always on top) - SwiftUI content via
NSHostingView - Position/size persisted in
UserDefaults
- ⌃Q - Copy and record (simulates Cmd+C)
- ⌃⌥⌘C - Toggle window show/hide
- ⌃W - Paste next item (oldest)
- ⌃E - Paste all items
- ⌃X - Clear all items
- Menu bar icon toggles window
- Window stays on top
- Window position/size remembered
- Queue count in title
- Individual item delete (X button)
- Clear button empties queue
- Preferences window opens (gear icon)
- Drag & Drop Reordering - Items have dashed borders but not functional yet
- Shortcut Customization - Preferences shows shortcuts but can't change them
- Preferences Wiring - Toggles exist but don't do anything yet:
- Launch at login
- Keep window on top
- Show in menu bar
- Queue size limit
Good:
✅ ClipQueue started
✅ Accessibility permissions granted
⌨️ Keyboard shortcuts registered
Bad:
⚠️ Accessibility permissions not granted!
⚠️ Failed to register hotkey
The app checks on startup and prints a detailed message if permissions are missing.
# Watch logs in real-time
log stream --predicate 'process == "ClipQueue"' --level debug
# Or use Console.app and filter for "ClipQueue"For distributing to users:
- Code signing - Need Apple Developer account ($99/year)
- Notarization - Required for Gatekeeper
- DMG creation - For easy installation
- GitHub releases - Distribute via releases page
Currently: Development builds only (not signed/notarized)