Paste fix: - Switch from std::process::Command to tokio::process::Command to avoid blocking the async runtime (was stalling the paste action) - Use explicit AppleScript that activates the frontmost app before sending Cmd+V keystroke, making paste more reliable - Increase delay to 300ms for macOS app refocus - Add tokio "process" feature Settings highlight fix: - SettingsPanel now uses local useState for immediate optimistic updates when clicking position/history buttons, instead of waiting for the parent prop round-trip - Buttons highlight instantly on click, then sync with backend Config fix: - titleBarStyle must be PascalCase "Overlay" in Tauri 2 config (was lowercase "overlay" which caused a startup error) Co-authored-by: Cursor <cursoragent@cursor.com>
maCopy
A fast, native macOS clipboard manager that lives in your menu bar. Built with Tauri 2, React, TypeScript, and SQLite.
Features
- Menu bar app — no dock icon, stays out of your way
- Global hotkey —
Cmd+Shift+Vopens the window from anywhere - Clipboard monitoring — polls every 500ms for text, images, and file paths
- Full-text search — instant filtering via SQLite FTS5
- Quick paste —
Cmd+1throughCmd+9to paste the Nth item directly into the previous app - Paste & return — clicking an entry copies it to clipboard, hides the window, and auto-pastes into the previously-focused app
- Multi-select —
Cmd+Clickto toggle,Shift+ArroworShift+Clickto range-select,Cmd+Afor all,Enterto paste selected - Pin entries — pinned items stay at the top and are never auto-deleted
- Context menu — right-click for Paste, Pin/Unpin, Delete (with multi-select support)
- Resizable window — drag edges to resize; size is remembered between sessions
- Window positioning — choose where the window appears: near cursor, center, or any corner (configurable in Settings)
- Auto-trim — keeps up to 50K entries (configurable: 1K/5K/10K/50K)
- Dark/light mode — follows macOS system appearance
- Privacy — whitespace-only entries are ignored; pause monitoring from the tray
Prerequisites
- macOS 10.15+
- Rust 1.77+ — install via rustup
- Node.js 18+ and npm
- Xcode Command Line Tools —
xcode-select --install - Accessibility permission — required for auto-paste (System Settings → Privacy & Security → Accessibility → add maCopy)
Quick Start
git clone gitea@10.0.30.169:ilia/maCopy.git
cd maCopy
npm install
npm run tauri dev
The app will compile the Rust backend, start the Vite dev server, and launch the menu bar app.
Usage
| Action | How |
|---|---|
| Open/close window | Click tray icon or press Cmd+Shift+V |
| Paste an entry | Click it, or press Enter |
| Quick paste | Cmd+1 through Cmd+9 |
| Search | Just start typing |
| Select multiple | Cmd+Click or Shift+Arrow |
| Select all | Cmd+A |
| Delete | Backspace or Delete (on selected items) |
| Pin/unpin | Right-click → Pin/Unpin |
| Settings | Tray icon → Settings… |
| Dismiss | Escape or click outside |
Development
Project Structure
maCopy/
├── src/ # React + TypeScript frontend
│ ├── main.tsx # Entry point
│ ├── App.tsx # Main app: state, keyboard nav, multi-select
│ ├── App.test.tsx # App integration tests
│ ├── index.css # Tailwind v4 + custom theme tokens
│ ├── types.ts # Shared TypeScript interfaces
│ ├── test/ # Test setup and factories
│ │ ├── setup.ts # Tauri API mocks for jsdom
│ │ └── factories.ts # makeEntry(), makeSettings()
│ └── components/
│ ├── SearchBar.tsx
│ ├── ClipboardList.tsx # Entry list with multi-select, type badges
│ ├── ContextMenu.tsx # Right-click menu with multi-select labels
│ └── SettingsPanel.tsx # Toggles, max history, window position
├── src-tauri/ # Rust backend
│ ├── Cargo.toml
│ ├── tauri.conf.json # Tauri config, permissions, window
│ └── src/
│ ├── main.rs # Binary entry point
│ ├── lib.rs # App setup: tray, hotkey, window management
│ ├── clipboard.rs # Background polling thread (500ms, SHA-256 dedup)
│ ├── db.rs # SQLite CRUD + FTS5 + settings + auto-trim
│ └── commands.rs # Tauri IPC commands
├── .cursor/rules/ # Cursor AI rules for this project
├── package.json
├── vite.config.ts
├── vitest.config.ts
└── tsconfig.json
Scripts
| Command | Description |
|---|---|
npm run tauri dev |
Run in development mode with hot reload |
npm run tauri build |
Build a release .app bundle |
npm test |
Run frontend tests (Vitest, 47 tests) |
npm run test:rust |
Run Rust backend tests (27 tests) |
npm run test:all |
Run all tests (frontend + backend) |
npm run lint |
TypeScript type-check |
npm run check |
Lint + all tests |
Tech Stack
| Layer | Technology |
|---|---|
| Framework | Tauri 2 |
| Frontend | React 18, TypeScript, Tailwind CSS v4 |
| Backend | Rust, rusqlite (bundled SQLite) |
| Clipboard | arboard for system clipboard access |
| Mouse position | core-graphics for global cursor coordinates |
| Search | SQLite FTS5 with content-sync triggers |
| Hotkey | tauri-plugin-global-shortcut |
| Autostart | tauri-plugin-autostart |
| Testing | Vitest + @testing-library/react (frontend), cargo test (backend) |
Architecture
Clipboard Polling
A dedicated Rust thread polls the system clipboard every 500ms using the arboard crate. Each new clipboard value is hashed (SHA-256) and compared against the last known hash to avoid duplicates. Text, images (stored as base64 PNG data URIs), and file paths are all captured.
Paste & Return
When you select an entry, maCopy writes it to the system clipboard, hides its window, waits 250ms for macOS to refocus the previous app, then simulates Cmd+V via AppleScript. This requires Accessibility permission.
SQLite + FTS5
The database uses a content-synced FTS5 virtual table with triggers that automatically keep the full-text index in sync with the clipboard_entries table. This enables instant prefix search as you type.
Window Behavior
The window uses titleBarStyle: "overlay" for native resize handles while keeping the frameless aesthetic. It's always-on-top and hides on blur. Position is determined by the user's setting (near cursor via CoreGraphics, center, or a screen corner).
Data Storage
The SQLite database is stored at:
~/Library/Application Support/maCopy/clipboard.db
Testing
Frontend (47 tests)
npm test
Tests cover App integration, SearchBar, ClipboardList (including multi-select), ContextMenu, and SettingsPanel. Tauri APIs are mocked in src/test/setup.ts.
Backend (27 tests)
npm run test:rust
Tests use in-memory SQLite databases and cover: CRUD operations, FTS5 search, auto-trim with pin preservation, settings persistence, SHA-256 hashing, and PNG encoding.
All tests
npm run test:all # 74 total tests
npm run check # lint + all tests
Building for Release
npm run tauri build
The built .app bundle will be in src-tauri/target/release/bundle/macos/.
License
MIT