Cairnquire macOS Sync
A macOS menubar application for syncing and uploading files to a Cairnquire server.
Features
- Tray Icon:
tray.circle.fillas the default menubar icon with upload state animations - Drop on Menubar: Drag files directly onto the menubar icon — it bounces, then uploads
- Upload Progress: Icon switches to
tray.circle(outline) while uploading - Menubar Popover: Click the icon to see a beautiful status panel with quick actions
- Auto Sync: Watch a local folder and automatically sync markdown files to the server
- Drag & Drop Upload: Drop files onto the upload zone to upload and copy the URL to clipboard
- Quick Upload: Upload files via the menubar menu or popover
- New Notes: Create notes from clipboard content or a terminal
$EDITORbuffer - Upload Index: View all uploaded files with timestamps
- Custom Icons: Choose from 11 different SF Symbols for the menubar icon
- CLI Tool: Command-line interface for one-off uploads and note creation
Requirements
- macOS 13.0+
- Xcode 15.0+ (for building)
- A running Cairnquire server
Building
Menubar App
cd apps/macos-sync
swift build
swift run CairnquireSync
For local development with Keychain access, sign the SwiftPM executable with a stable Apple Development identity and run the signed binary directly:
cd apps/macos-sync
scripts/sign-dev.sh CairnquireSync
.build/debug/CairnquireSync
The script uses the first valid Apple Development code-signing identity. To
choose a specific identity, set CAIRNQUIRE_CODESIGN_IDENTITY to the certificate
name or SHA-1 hash shown by security find-identity -v -p codesigning.
Or open in Xcode:
open Package.swift
CLI Tool
cd apps/macos-sync
swift build --product cairnquire-cli
swift run cairnquire-cli --help
You can run the built executable directly after building:
.build/debug/cairnquire-cli help
Setup
- Start your Cairnquire server
- Create an API token from the web UI at
/account/tokens/new - Open the app settings (click the menubar icon → Settings)
- Enter your server URL and API token
- Optionally configure a sync folder, default upload folder, and New Note behavior
Usage
Menubar App
Left-click the icon to open a beautiful status popover showing:
- Live sync status with color indicator
- Last sync time
- Quick action buttons (Sync, Upload, Note, Drop Zone)
- Recent uploads preview
- Settings and server links
Right-click the icon for the traditional menu with all options.
- Drop on Icon: Drag files directly onto the menubar icon — it bounces, then uploads
- Sync Now: Manually trigger a sync
- Upload File: Select files to upload
- New Note: Create a markdown note from clipboard text or open Terminal.app with
$EDITOR, depending on Settings - Drop Zone: Open a drag-and-drop upload window
- View Uploads: See all uploaded files with timestamps
- Change Icon: Pick from 11 SF Symbols in Settings (default:
tray.circle.fill)
CLI Tool
Configure the shared app and CLI settings first. Use the port where your server is actually listening:
cd apps/macos-sync
swift run cairnquire-cli config \
--server http://localhost:9000 \
--token dev \
--folder "$HOME/Documents/Cairnquire" \
--upload-folder Inbox \
--new-note editor
Run one bidirectional sync:
swift run cairnquire-cli sync
Start the menubar app to keep watching the configured folder when auto-sync is enabled:
swift run CairnquireSync
Other CLI commands:
# Upload a file
swift run cairnquire-cli upload ~/Documents/report.pdf
# Create a note from clipboard
swift run cairnquire-cli note --clipboard --title="Meeting Notes"
# Create a note from stdin
echo "Hello World" | swift run cairnquire-cli note -
# Create a note from arguments
swift run cairnquire-cli note "This is a note body"
# Show command-specific documentation
swift run cairnquire-cli help upload
swift run cairnquire-cli help sync
Readable uploads (.md, .markdown, .txt, .html, and .htm) are published as rendered documents. If the same inbox filename already exists, the app asks whether to keep both files, replace the existing document, or cancel. If identical attachment bytes were already uploaded, the app asks whether to copy the existing URL or cancel.
When New Note is set to Open Terminal $EDITOR, the menubar action opens a
temporary markdown buffer in Terminal.app. The app uploads the saved buffer
after the editor exits. It uses $EDITOR, then $VISUAL, and falls back to
vi. Configure GUI editor launchers to wait for the buffer to close, such as
EDITOR="code --wait".
Configuration
Configuration is stored in:
- Settings:
~/Library/Preferences/com.cairnquire.sync.plist - API Token: macOS Keychain
- Sync state:
~/Library/Application Support/CairnquireSync/
SwiftPM debug executables are ad-hoc signed. macOS may ask for Keychain access again after rebuilding because the replacement executable does not have a stable Developer ID identity. A packaged, consistently signed app avoids that development-time prompt. Updating settings preserves the existing Keychain item instead of recreating it.
Architecture
Sources/
├── CairnquireSync/ # Shared library
│ ├── API/
│ │ ├── Client.swift # HTTP client for Cairnquire API
│ │ └── Models.swift # API response models
│ ├── Sync/
│ │ ├── SyncEngine.swift # Bidirectional sync engine
│ │ └── FolderWatcher.swift # FSEvents-based folder watcher
│ ├── Upload/
│ │ └── UploadManager.swift # File upload handling
│ ├── Settings/
│ │ └── Config.swift # Configuration and keychain storage
│ └── UI/
│ ├── MenuBarController.swift # Main controller
│ ├── StatusPopoverView.swift # Menubar popover UI
│ ├── SettingsView.swift # Settings UI
│ ├── DropZoneView.swift # Drag & drop UI
│ └── UploadsListView.swift # Upload index UI
├── CairnquireSyncApp/ # Menubar app
│ ├── App.swift # App entry point
│ └── StatusItemView.swift # Custom status item view with drag & drop
└── cairnquire-cli/ # CLI tool
└── main.swift # CLI entry point
Dev Mode
When running the server locally with CAIRNQUIRE_DEV_MODE=1, you can use the hardcoded API key dev instead of generating a real API token.
Server
CAIRNQUIRE_DEV_MODE=1 mise run server-run
Or set in your config:
{
"devMode": true
}
macOS App
The app automatically detects localhost servers and defaults to the dev token. No configuration needed when running locally.
CLI
cairnquire-cli config --server http://localhost:8080 --token dev
cairnquire-cli upload ~/Documents/report.pdf
API Gaps
See .project/macos-app-api-gaps.md for documented API endpoints that need server-side implementation.
Readable uploads (.md, .markdown, .txt, .html, and .htm) are published as rendered documents. Other supported files remain attachments. The upload index returns the canonical URL for either kind.