Skip to content

asiminnesli/pile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pile App Icon

Pile

A privacy-first clipboard manager for Mac — with seamless iPhone sync.

Platform Swift License No Dependencies

No cloud. No subscription. No tracking. Just your clipboard, organized.


✨ Features

Feature
📋 Auto-capture — monitors your clipboard and instantly saves text, URLs, and images
🗂️ Collections — organize clips into named, emoji-tagged groups
Paste & Delete — customizable hotkey that pastes the top item and removes it from the pile
🔍 Full-text search — find anything across all collections instantly
📱 iPhone companion — a native iOS app that stays in sync with your Mac
🔄 LWW-CRDT sync — conflict-free, serverless sync over your local Wi-Fi via Bonjour
🖼️ Image support — capture and paste screenshots, photos, and image files
🔗 URL enrichment — automatically fetches page title and metadata for web links
🗄️ Archive — keep old collections out of the way without deleting them
🔒 100% local — your data never leaves your devices

📸 Screenshots

Coming soon — build the project and see for yourself.


🏗️ Architecture

Pile is intentionally simple. Zero third-party dependencies — only Apple frameworks.

clipboardVault/
├── ClipboardVault/          # macOS app (MenuBar + main window)
│   └── pileMac/
│       ├── PileApp.swift        # App entry, hotkey & paste logic
│       ├── ClipboardMonitor.swift  # NSPasteboard polling (0.8s)
│       ├── Database/
│       │   └── PileDatabase.swift  # Raw SQLite3 — no ORM
│       ├── Store/
│       │   └── PileStore.swift     # Observable state + LWW merge
│       ├── Services/
│       │   ├── SyncServer.swift    # Bonjour TCP server (NWListener)
│       │   ├── HotkeyManager.swift # Global hotkey via CGEvent
│       │   ├── ImageStorage.swift  # Disk-based image cache
│       │   └── URLMetadataFetcher.swift
│       └── Views/               # SwiftUI views
│
└── PileMobile/              # iOS companion app
    ├── PileMobile/
    │   ├── MobileStore.swift    # App Group JSON persistence
    │   └── SyncClient.swift     # Bonjour TCP client (NWBrowser)
    └── PileShare/               # Share Extension

Sync Protocol

Pile uses a serverless LWW-CRDT (Last-Write-Wins Conflict-free Replicated Data Type) sync over Bonjour/mDNS — the same technology used by AirDrop and AirPlay.

Mac (NWListener on port 8765)  ←──Bonjour──→  iPhone (NWBrowser)
         │                                            │
    fullState ──────────────────────────────────────► merge
    merge ◄──────────────────────────────────── fullState
         │                                            │
    itemAdded / itemDeleted / collectionUpdated  (delta)
  • No internet required — works entirely on your local network
  • Tombstones ensure deletions propagate correctly across devices
  • updatedAt timestamps determine which version wins on conflict

🚀 Getting Started

Requirements

Minimum
macOS 14.0 Sonoma
iOS 17.0
Xcode 15.0
Swift 5.9

Installation

1. Clone the repository

git clone https://github.com/YOUR_USERNAME/pile.git
cd pile

2. Open the macOS project

open ClipboardVault/ClipboardVault.xcodeproj

3. Open the iOS project (separate Xcode window)

open PileMobile/PileMobile.xcodeproj

4. Configure signing

In Xcode, for each target:

  • Select your Team under Signing & Capabilities
  • Update the Bundle Identifier to something unique (e.g. com.yourname.pile)

⚠️ The iOS app and Share Extension must share the same App Group ID. Update PileAppGroup.id in both targets to match your own group identifier (e.g. group.com.yourname.pile).

5. Build & Run

  • macOS: Select pileMac scheme → Run (⌘R)
  • iOS: Select PileMobile scheme, choose your device → Run (⌘R)

Both apps must be on the same Wi-Fi network for sync to work.


🔐 Permissions

Pile requires the following permissions:

Permission Why
Accessibility Required to simulate ⌘V for the Paste & Delete feature
Local Network Required for Bonjour discovery between Mac and iPhone

Pile never requests internet access, location, contacts, or any other sensitive permission.


🛠️ How It Works

Clipboard Monitoring

ClipboardMonitor polls NSPasteboard.changeCount every 0.8 seconds. When a change is detected, it classifies the content as image, URL, or text and fires a callback. Internal copies (e.g. during Paste & Delete) are suppressed to avoid circular captures.

Paste & Delete

When the hotkey fires:

  1. The target app's PID is captured before Pile's window gains focus
  2. The top item's content is written to NSPasteboard
  3. The target app is activated
  4. A CGEvent simulates ⌘V keyboard input (requires Accessibility permission)
  5. The original clipboard contents are restored after 500ms
  6. The item is deleted from the collection (if the setting is enabled)

LWW-CRDT Sync

Every item and collection carries a updatedAt timestamp. On connection:

  1. Both devices exchange their full state (including soft-deleted tombstones)
  2. For each record, the version with the later updatedAt wins
  3. Subsequent changes are broadcast as delta messages in real time

🤝 Contributing

Contributions are welcome! Feel free to:

  • 🐛 Open an issue for bugs or unexpected behaviour
  • 💡 Suggest a feature via GitHub Discussions
  • 🔧 Submit a pull request

Please keep PRs focused — one feature or fix per PR.


📄 License

Pile is released under the MIT License. See LICENSE for details.


Built with ❤️ using SwiftUI, SQLite3, and Network framework — no dependencies, no cloud.

About

Privacy-first macOS clipboard manager with local-only iPhone sync over Bonjour. No cloud, subscription, or tracking.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages