Skip to content

Repository files navigation

Gancho — Smart Clipboard

Your clipboard, everywhere — private by design. Gancho is a local-first clipboard history and curated snippet library for Mac, iPhone, iPad, and the rest of the Apple platform family, built so future non-Apple clients can join without rewriting the core.

Gancho means “hook” in Spanish: it is where you hang everything you copy. And when something tiene gancho, it hooks you.

gancho.app · Releases · Changelog

CI Latest release License: MIT Platforms Swift 6.2

Status: public v0.8.3, in active development toward 1.0. The capture engine, local GRDB/SQLite storage with FTS5 search, the Liquid Glass history panel, paste-back, pins and boards, the retention engine, the on-device intelligence stack, the iPhone/iPad app and its extensions, iCloud sync via CKSyncEngine, and StoreKit purchase plumbing are implemented and covered by tests. Serialized purchase and restore automation verifies entitlement changes end to end. The release/versioning lane ships a signed, notarized, stapled direct-download DMG, a signed Sparkle appcast, version-sync guards, artifact QA, and the website. The published v0.8.3 DMG is signed, notarized, stapled, and Gatekeeper-accepted. The 0.8 series is the first direct release built against an embedded production CloudKit and Push provisioning profile, so the artifact is sync-capable and its signed entitlements are validated against the profile at package and QA time. The v0.8.3 direct download can buy, activate, revalidate, and deactivate a Pro license through Lemon Squeezy without embedding a payments secret. Pro unlocks encrypted iCloud sync after the production schema and signed two-Mac candidate matrix have been verified. What remains before 1.0 is App Store submission and the account-gated launch pieces (App Store products and TestFlight).

Contents

What's new in 0.8

  • Bring an existing history with you. A guided Mac import previews Maccy archives or CSV files before writing, rejects protected and malformed rows, deduplicates atomically, supports cancellation, and finishes with an exact imported/skipped summary. Raycast is not currently an import source: its documented clipboard API exposes only six recent entries, while its encrypted .rayconfig backup has no documented third-party decoding schema. Gancho does not inspect private encrypted app storage.
  • Give each local AI client only the context it needs. MCP access now uses expiring, revocable per-client grants with an explicit board/time context, independent read/write policy, fail-closed SQL filtering, and a content-free access ledger. No process can fall back to ambient history.
  • Make first value visible without pre-consent tracking. Onboarding records only closed, content-free activation milestones locally; optional diagnostics receive one coarse aggregate only after explicit consent.
  • See private reuse without creating another history. The Privacy Center on Mac, iPhone, and iPad shows bounded per-app capture, reuse, protected/ignored, and sensitive-expiry totals. The receipt stays on that device for 13 rolling months, never syncs or exports, and has an independent clear action.
  • Make the Mac panel yours. Resize the history window freely or jump to a Compact, Standard, or Large preset; Gancho remembers the geometry and a Small, Standard, or Large semantic text preference across relaunches.
  • Trust the failure paths, not just the happy one. In 0.8.3, clips shared into Gancho on iPhone and iPad wait sealed instead of as plaintext, a delete that fails locally is no longer sent to your other devices, sensitive clips on iPhone expire when you leave the app, and failed exports, purchases, and privacy settings on the Mac say so instead of looking like they worked.

Gancho v0.8.3 direct-download Pro activation

Real macOS v0.8.3 build captured by XCUITest with synthetic fixtures. No user clipboard content or license key appears in the image.

Product goal

Gancho should become the private memory layer for everything people copy and reuse. Its launch wedge can target developers and power users first, while the product language remains broad enough for anyone who repeatedly copies work between devices:

  • Capture safely. Automatic on macOS, intentional on iOS/iPadOS/visionOS, with sensitive pasteboard markers vetoed before any content read.
  • Retrieve instantly. Exact, fuzzy, and regex history search first; local semantic retrieval then grounds Q&A and smart organization.
  • Reuse anywhere. Paste-back, snippets, templates, pins, and App Intents make captured work reusable without changing context.
  • Sync without servers by default. Apple-platform sync uses the user's iCloud account through a SyncEngine boundary; future transports plug into the same boundary.
  • Earn trust visibly. No clipboard content in logs, telemetry, diagnostics, or error reports — ever.

Platform plan

Platform Role Capture model
macOS Primary creation surface Automatic pasteboard monitoring with adaptive polling
iOS Companion and capture surface Share Extension, UIPasteControl, foreground actions, App Intents
iPadOS Power companion iPad-native navigation and keyboard workflows
visionOS Apple ecosystem coverage iPad-compatible build first; native spatial UI only if usage justifies it
watchOS Lightweight viewer Pins/recent items only; watchOS has no pasteboard API
Android / Windows / Linux Future analysis only Capability matrix and portable data envelope research; no implementation commitment yet

The engineering rule is simple: platform-specific capture/UI code stays at the edges; models, privacy policy, storage/search contracts, sync, and intelligence stay in reusable modules.

Current capabilities

Capture & privacy

  • macOS pasteboard monitor: adaptive low-power polling, screen-lock and private-mode pause, own-write suppression, Universal Clipboard badge, rich payloads (text, RTF, HTML, image, file URLs), lossless bursts, off-main reads.
  • Sensitive org.nspasteboard types (ConcealedType, TransientType, AutoGeneratedType) veto capture before any content read; preloaded password-manager / banking denylist; "ignore next copy".
  • On-device sensitive-data detector (cards via Luhn; AWS/Stripe/GitHub/Slack keys; PEM keys; probable passwords) with masked previews and short expiry.
  • Retention engine: global and per-kind expiry, sensitive auto-expire, pins exempt, background purge.

Storage & search

  • GRDB/SQLite store with content-addressed disk blobs, lazy thumbnails, paged metadata-only lists, versioned migrations, device-aware dedup, and always-available JSON/CSV export.
  • FTS5 full-text search (exact / fuzzy / regex; filters by kind, source app, date) with dedicated short-prefix indexes so fuzzy recall stays responsive while typing. The 100k-item performance harness measures cold startup and reproducible warm rounds separately.
  • A 512-dimension on-device embedding index used by Ask your clipboard and auto-board suggestions. Main history search remains FTS5 exact/fuzzy/regex.

macOS app

  • Menu-bar agent and resizable Liquid Glass floating panel (⇧⌘V): keyboard-first, type-to-search, composable source/kind/board/date filters, editable titles and explicit Save/Cancel text refinement, per-kind previews, a privacy-safe read-only full-content preview (⌘Y), paste-back via synthetic ⌘V (layout-aware keycodes, plain-text paste, restore-previous), onboarding, Settings, and the Privacy Center. Compact/Standard/Large geometry shortcuts and semantic text-size controls persist across relaunches.
  • Pins and boards (multi-membership collections) and a unified Library for boards and snippets. Boards can use a fixed accessible color and an optional emoji identity that persists and syncs across Mac, iPhone, and iPad. A local, one-time suggestion offers to promote a clip to a snippet after its third successful reuse.
  • Multi-selection via Shift or Command-click, with batch add-to-stack, add-to-board, and delete-with-Undo actions. Selected file clips drag together as independent file URLs when the whole selection is file-safe.
  • Curated snippets and pins can be donated to Spotlight with structural redaction and a Settings switch that removes Gancho's system index immediately.
  • Guided Maccy/CSV history import uses a read-only preview, source validation, atomic deduplication, cancellation, and a content-free final summary.

iPhone & iPad app

  • Intentional capture only: Save button, UIPasteControl, Share Extension, and App Intents / Shortcuts. Keyboard extension with history, widgets, iPad split view, source-app filtering, editable clip titles and text, and on-device enrichment of clips captured on the device.

On-device intelligence (zero network — every tier runs on the device)

  • Deterministic tier-0 classifier — 17 kinds (URL, email, phone, address, date, color, JWT, JSON, UUID, code + language, credit card, tracking number, …) in under 5 ms.
  • Apple Intelligence titles (fallback-safe), screenshot OCR, and semantic indexing for grounded Q&A and board suggestions — each behind a per-stage toggle on the Intelligence screen.
  • Dev Actions (JWT decode, JSON pretty/minify, Base64, URL parse, color conversion, UUID formats), also exposed as App Intents.
  • Smart Paste — rewrite a clip before pasting (summarize, fix grammar, change tone, key points), translate, and redact PII — all on-device and secret-safe.
  • Ask your clipboard — grounded Q&A over history (semantic retrieval + the on-device model), with sensitive clips filtered out.
  • Auto-board — suggest the board a clip belongs to from its semantic neighbors.

Sync & integrations

  • CKSyncEngine over the user's private iCloud database behind the SyncEngine boundary (clips, board membership, deletions) with a visible sync status. A real-device cross-device pass has completed; the matrix is repeated for each release candidate.
  • gancho CLI and a local, opt-in MCP server with expiring, revocable per-client grants, explicit board/time context, independent read/write permission, and a metadata-only access log, plus a VS Code "Save Selection" command — see docs/INTEGRATIONS.md.

Monetization & operations

  • StoreKit 2 purchase / restore / entitlement plumbing with a contextual paywall and free-tier limits (the App Store products are owner-gated).
  • Optional anonymous diagnostics, disabled until explicit consent and limited by type to metadata buckets; crash and support bundles remain content-free.
  • Content-free activation milestones remain local before consent, and the independent private activity receipt exposes bounded per-app totals without syncing, exporting, or retaining clipboard content.

Engineering

  • XcodeGen project; Swift 6 strict concurrency (app targets @MainActor, engine-room targets nonisolated + Sendable); a bilingual (English + Spanish) String Catalog gate; accessibility (VoiceOver, Dynamic Type, reduce-transparency); and shared platform-neutral coordinators in GanchoAppCore behind durable store and transport-neutral sync boundaries.
  • CI covers build/test/lint, an enforced production-source coverage floor, serialized StoreKit purchase/restore automation, and scale performance.

Setup (< 10 min)

Prerequisites: macOS 15.4+ to run, Xcode 26+ to build, and XcodeGen (brew install xcodegen).

git clone https://github.com/johnny4young/gancho.git
cd gancho
make hooks   # install the pre-commit lint hook once per clone
make test    # package unit tests (Swift Testing)
make open    # generate Gancho.xcodeproj and open Xcode
Target What it does
make project Regenerate Gancho.xcodeproj from project.yml
make build Build the macOS app (unsigned Debug)
make build-ios Build the iOS app (unsigned Debug, generic device)
make install-ios Build the iOS app team-signed and install it on the connected iPhone/iPad
make test Run package unit tests
make coverage Run package tests with coverage and enforce the production-source floor
make test-storekit Run serialized StoreKit purchase/restore entitlement automation
make test-ui / make test-ui-ios Run the macOS / iOS XCUITest suites
make release-check Verify project.yml, CHANGELOG.md, and release templates are in sync
make package-macos Build dist/Gancho-<version>.zip for release QA
make qa-release QA the newest release ZIP, or ARTIFACT=/path/to/Gancho.app
make site-check Verify the static website and its product-truth contract under site/
make format / make lint Format / verify Swift sources
make hooks Install the versioned pre-commit lint hook
make clean Remove generated project and build artifacts
make open Generate and open the Xcode project

Run on a real device

The keyboard, widgets, and the "ready to paste" Live Activity only come alive on hardware. Plug in an iPhone/iPad, trust the Mac, then:

make install-ios                      # auto-detects the connected device
make install-ios IOS_DEVICE=<uuid>    # or target one explicitly
make install-ios DEVELOPMENT_TEAM=<team-id>

make install-ios team-signs the build (Xcode-managed provisioning, so the app and its extensions get profiles on first run) and installs it with devicectl. The Makefile defaults to the maintainer's development team, but forks and CI can override DEVELOPMENT_TEAM without editing the file. Open Gancho on the device from the Home Screen. List devices and their UUIDs with xcrun devicectl list devices. After installing, enable the keyboard in Settings → General → Keyboard → Keyboards → Gancho (turn on Full Access for clip history), and Live Activities under the Gancho app's settings.

Release and website workflow

Release metadata is intentionally boring and synchronized:

  • project.yml owns MARKETING_VERSION and CURRENT_PROJECT_VERSION.
  • CHANGELOG.md keeps [Unreleased] plus the newest released ## [x.y.z] entry matching MARKETING_VERSION.
  • docs/releases/vX.Y.Z.md contains the curated, outcome-led GitHub Release body for the current version, including install/update instructions, availability limits, and verified artifact evidence.
  • .github/workflows/release.yml gates tagged v* releases with make release-check, lint, tests, macOS build, iOS build, packaging, and artifact QA before publishing the signed DMG, checksum, curated release note, Homebrew cask update, and signed appcast.
  • .github/workflows/pages.yml deploys the landing from site/ to Cloudflare Pages (https://gancho.app) and keeps the signed Sparkle appcast on GitHub Pages (https://johnny4young.github.io/gancho/appcast.xml, the app's feed URL).

See CHANGELOG.md and docs/RELEASING.md for the full release runbook, signing/notarization secrets, and manual QA checklist.

Layout

Apps/GanchoMac          macOS menu-bar agent + Liquid Glass panel
Apps/GanchoiOS          iPhone/iPad app (+ Share, keyboard, widgets)
site/                   Cloudflare landing source + signed appcast source
CHANGELOG.md            Release notes that must match MARKETING_VERSION
docs/releases/          Curated GitHub Release notes, one file per version
docs/RELEASING.md       Release/versioning, signing, QA, and Pages runbook
docs/PRODUCT-TRUTH.md   Tested matrix tying public claims to source evidence
Packages/GanchoKit      One SwiftPM package — eight library products + a CLI:
  GanchoKit               models, GRDB store, retention, snippets, sync boundary
  ClipboardCore           pasteboard adapters, capture + intelligence policy
  GanchoAI                on-device classifiers, annotation, embeddings, QA
  GanchoDesign            shared design tokens and components
  GanchoSync              CKSyncEngine adapter (the only module importing CloudKit)
  GanchoTelemetry         metadata-only analytics transport (network-isolated)
  GanchoAppCore           shared platform-neutral application coordinators
  GanchoMCP               local MCP tools over the store boundary
  gancho                  CLI + stdio MCP server
docs/ARCHITECTURE.md    Engineering decisions and invariants
project.yml             XcodeGen source of truth for Gancho.xcodeproj

Gancho.xcodeproj is generated and git-ignored. Change project.yml, then run make project.

Privacy invariants

  • Never store content tagged with org.nspasteboard.ConcealedType, org.nspasteboard.TransientType, or org.nspasteboard.AutoGeneratedType.
  • Never put clipboard content in logs, telemetry, crash reports, analytics, issue templates, or support bundles.
  • The Privacy Center's activity receipt stores only per-day integer totals and validated, bounded app identifiers on that device, retains 13 rolling months, never syncs or exports, and can be cleared without deleting history.
  • iOS, iPadOS, and visionOS use intentional capture only. No background pasteboard polling on those platforms.
  • Any external model or transport must be opt-in per action and show exactly what would leave the device.

See docs/ARCHITECTURE.md for the full architecture and platform strategy.

Contributing

Contributions are welcome — see CONTRIBUTING.md for the full guide. In short: branch off main, keep the change coherent, open a PR against main, and get CI green (macOS + iOS builds, package tests with an 80% coverage floor, swift-format + SwiftLint, and the metadata/site/product-truth gates). PRs squash-merge and their branch is deleted automatically on merge. Please read the Code of Conduct; report security issues per the Security Policy.

Acknowledgements

Gancho is built on excellent open-source work, including GRDB.swift and SQLCipher for encrypted local storage, KeyboardShortcuts for the global hotkey, Sauce for keyboard-layout handling, and TelemetryDeck for optional, explicitly enabled, content-free metrics.

License

MIT © 2026 Johnny Young.

About

Gancho — Smart Clipboard. Clipboard history + snippet library for Mac, iPhone & iPad. Private by design.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages