v0.2.11 · Technical Architecture

How MonoClip
Watches Everything

Tauri 2 + Rust backend, Svelte 5 frontend. A native macOS clipboard manager that runs silently at 8 MB, polls at 300 ms, and exposes your history to AI via MCP.

~8MBBinary Size
~30MBRAM Idle
<200msStartup
300msPoll Interval
500Default History
9MCP Tools

Architecture

System Overview

Tauri bridges a Rust backend (clipboard, DB, shortcuts) with a Svelte 5 frontend via typed commands and event emission.

macOS SystemClipboard · Shortcuts · TrayRUST BACKEND (src-tauri)main.rsApp Bootstrapperstate.rsArc<Mutex<DB>>clipboard/watcher + detectorshortcuts/manager.rscommands/4 filesdb/ (rusqlite · WAL · mmap · migrations)~/.monoclip/monoclip.dbSVELTE 5 FRONTEND (src/)Storesclips · folders · settingsComponents12+ Svelte fileslib/api/typed invoke()mclip (CLI binary)828 lines · standalonelist · add · pin · mcpMCP Server (JSON-RPC)Claude · Cursor · Windsurf← Tauri invoke() / emit() →

Rust Backend

8 Backend Modules

Pure Rust — no npm deps. Each module owns a single responsibility.

🗄

Database Layer

db/

SQLite via rusqlite with WAL mode, memory temp store, and 256 MB mmap. Single migration (v001) creates all tables. Singleton connection wrapped in Arc<Mutex> for thread-safe access.

rusqliteWAL modemigrationsArc<Mutex>
📋

Clipboard Watcher

clipboard/watcher.rs

Background thread polls system clipboard every 300ms via hash comparison. Handles text, images (saved as PNG), and file lists. Deduplicates by touching updated_at on identical content instead of creating new rows.

300ms pollhash dedupimage PNGfile paths
🔍

Content Detector

clipboard/detector.rs

Regex-based classifier assigns content_type (url, email, color, code, image, file, text) and generates 200-char previews. URL, email, and color patterns are exact-match; code detected by multi-line + symbol density.

urlemailcolorcodeimagefile
⌨️

Shortcut Manager

shortcuts/manager.rs

Registers/deregisters global hotkeys via tauri-plugin-global-shortcut. Master shortcut (Cmd+Shift+V) shows window; per-folder shortcuts capture selected text via osascript + sentinel detection then save directly to that folder.

global hotkeysosascriptsentinel detectfolder routing
🖥

Window Manager

window/manager.rs

Controls the frameless always-on-top floating panel. ActivationPolicy::Accessory hides from Dock and Cmd+Tab. Window is pre-rendered and shown/hidden instantly via visibility toggle — no reload cost.

framelessalways-on-topAccessory policyspring anim
📟

System Tray

tray/setup.rs

Builds macOS menu bar icon with Open / Update / Quit context menu. Tray click shows/hides window. Listens for update events to add version badge and notification. No Dock presence.

menu barcontext menuupdate badgeno Dock

Tauri Commands

commands/

Four command files expose the backend to Svelte: folders.rs (CRUD + reorder), clips.rs (get, pin, delete, move, copy, export), settings.rs (update with side effects), utility.rs (stats, cleanup, CLI install, update check).

folders.rsclips.rssettings.rsutility.rs
💻

CLI + MCP Server

bin/mclip.rs

Standalone 828-line Rust binary with subcommands: list, add, remove, pin, get, folder, context, mcp. The mcp subcommand launches a JSON-RPC 2.0 stdio server exposing 9 clipboard tools to Claude Desktop, Cursor, and Windsurf.

828 linesJSON-RPC 2.0stdio9 MCP tools

Svelte 5 Frontend

Frontend Architecture

Svelte 5 runes for zero-runtime reactivity. Class-based stores with $state. Typed invoke() wrappers eliminate runtime errors.

lib/api/tauri.ts

Typed wrappers around Tauri invoke() for all backend commands. Type definitions for Folder, ClipItem, Settings, AppStats.

lib/stores/clips.svelte.ts

Svelte 5 rune-based store — items, isLoading, searchQuery, activeFolder, flashingId. Methods: load(), prependItem(), removeItem(), updateItem().

lib/stores/folders.svelte.ts

Folder list and active folder tracking with $state runes. Synced with backend via Tauri events.

App.svelte

Root shell. Registers Tauri event listeners (clip:new, folder:saved, cleanup:done, update:progress). Handles search debounce and window focus/blur logic.

ClipCard.svelte

Individual clip: preview text, type icon, timestamp, source app, pin badge. Hover reveals copy/pin/delete actions. Click triggers 150ms accent flash + copy command.

FolderModal.svelte

Create/edit folder with emoji picker, hex color picker, and global shortcut recorder with conflict detection.

SettingsPanel.svelte

Slide-in panel with sections: General, Clipboard, Shortcuts, Auto-cleanup, About. Setting changes trigger backend side effects (re-register shortcut, reschedule cleanup).

SearchBar.svelte

Full-width search with 150ms debounce. Cmd+F or / to focus. Empty/Escape to return to folder view. Searches across ALL folders.

Data Flow

End-to-End System Flow

From startup to clipboard copy — every step in sequence.

1

App Startup

Tauri initializes, opens SQLite at ~/.monoclip/monoclip.db, runs migrations, creates AppState. Sets ActivationPolicy::Accessory (menu bar only). Initializes plugins, builds tray, registers global shortcuts, starts clipboard watcher thread, runs auto-cleanup if enabled.

2

Clipboard Poll (every 300ms)

Background thread reads system clipboard. Tries: file list → image → plain text. Hashes content; skips if identical to last. Runs content-type detector (regex). Deduplication: identical in Inbox → touch updated_at. New: INSERT into clip_items, enforce max_history_items (delete oldest unpinned), emit clip:new event.

watcher.rs → detector.rs → db/queries.rs → emit('clip:new', item)
3

Frontend Receives Clip

App.svelte listener fires on clip:new. If no search active and viewing Inbox: clipsStore.prependItem(item) with spring entrance animation. No full reload — single prepend keeps scroll position.

4

User Opens Window (Cmd+Shift+V)

Global shortcut fires; window.show() + window.setFocus(). Pre-rendered Svelte UI instantly visible (no load time). Spring animation from 0.96→1.0 scale in 180ms. Content already populated from background sync.

5

User Copies a Clip

Click on ClipCard → invoke copy_to_clipboard(id). Backend fetches content, writes to system clipboard via tauri-plugin-clipboard-manager. If paste_on_click=true: spawns async task to simulate Cmd+V after 150ms delay. Frontend shows 150ms color flash on the card.

6

Per-Folder Shortcut

User presses Cmd+Opt+1 (assigned to Work folder). shortcuts/manager fires: runs osascript to capture selected text (Cmd+C with sentinel). If selection found → save to folder. If not → read current clipboard. Emits folder:saved event. Toast: 'Work ← selection'.

osascript → sentinel detect → folder save → emit('folder:saved')
7

Search

User types in SearchBar. 150ms debounce fires clipsStore.load(undefined, query). Backend runs LIKE pattern on content + preview across ALL folders, returns ≤50 results. Frontend replaces list. Escape → reload current folder.

8

Auto-Cleanup

Triggers on startup + daily background timer. Deletes non-pinned, non-deleted clips older than auto_clean_days (default 30). Exceptions: always keeps 10 most recent Inbox items; pinned items never deleted. Emits cleanup:done. Toast: 'Auto-cleaned 42 old clips'.

Storage

SQLite Schema

Single file at ~/.monoclip/monoclip.db with 4 tables. WAL mode + mmap for concurrent read/write.

folders

  • id (PK, Inbox=1)
  • name, icon (emoji), color (hex)
  • global_shortcut (nullable)
  • position (sidebar order)
  • created_at, updated_at

clip_items

  • id (PK, AUTOINCREMENT)
  • content (full text)
  • content_type (text|url|email|color|code|image|file)
  • preview (≤200 chars)
  • folder_id → folders.id
  • is_pinned, is_deleted (soft delete)
  • source_app (bundle ID)
  • created_at, updated_at

settings

  • id = 1 (singleton)
  • master_shortcut (default: Cmd+Shift+V)
  • auto_clean_enabled, auto_clean_days (1–365)
  • max_history_items (50–2000, default 500)
  • paste_on_click, theme, launch_at_login
  • ignored_apps (JSON array)

schema_version

  • version: 1 (tracks migrations)

SQLite Performance Pragmas

journal_mode=WAL

Concurrent read/write

synchronous=NORMAL

Fast writes, still safe

temp_store=MEMORY

In-memory temp tables

mmap_size=256MB

Memory-mapped I/O

AI Integration

MCP Server

mclip mcp starts a JSON-RPC 2.0 stdio server exposing 9 clipboard tools to Claude Desktop, Cursor, and Windsurf.

list_clips

List clips with optional folder, search query, and pagination limit

add_clip

Insert new text clip into specified folder

get_clip

Fetch full raw content by clip ID

remove_clip

Delete clip by ID (soft delete)

pin_clip

Mark clip as pinned — skips auto-cleanup

unpin_clip

Remove pin status from clip

list_folders

Get all folders with emoji, color, shortcut

create_folder

Create new folder with emoji and hex color

delete_folder

Delete folder — clips moved to Inbox

Configuration

// ~/.config/claude/claude_desktop_config.json
{
  "mcpServers": {
    "mclip": {
      "command": "mclip",
      "args": ["mcp"]
    }
  }
}

Performance

Speed Benchmarks

Tauri + Rust deliver native performance. Every metric is measured on macOS with SSD storage.

OperationSpeedNotes
Binary size
~8 MB
vs Electron ~150 MB
RAM idle
~30 MB
vs Electron ~300 MB
Startup to tray ready
<200 ms
No splash screen
Window reveal
<50 ms
Pre-rendered, just toggle visibility
Clipboard poll cycle
<1 ms
Hash check only if unchanged
Search (10K clips)
<50 ms
LIKE + LIMIT + indexed columns
DB queries
<10 ms
WAL mode + mmap + indexes
Image save to PNG
<30 ms
~/.monoclip/images/

vs Electron Alternatives

Binary size~8 MB~150 MB
RAM idle~30 MB~300 MB
Startup<200 ms1–3 s

Storage Limits

Max clipboard content50,000 chars
Max preview200 chars
Default history500 items
Max history (configurable)2,000 items
DB size soft warn100 MB