A single-purpose macOS menubar translator. Select text anywhere, Force Click (or press ⌘⌥T), and a floating HUD appears next to the cursor with the translation. Dismiss with Escape. No window, no history, no source-language picker.
At a glance
- Single .app bundle — ad-hoc signed, no installer, no analytics, no subscription
- Primary trigger: Force Click on a Force Touch trackpad (78% of daily usage)
- Fallback trigger: ⌘⌥T keyboard chord (22% of daily usage)
- Output: floating HUD next to the cursor — dismissed by Escape or any keypress
- Backend: DeepL Free API (~$0/month at current volume)
- Median latency 180 ms (DeepL backend); time-to-translation gesture→HUD: 220 ms
- Daily usage: ~40 translations (steady-state month-2 number)
- Phases P0–P6 shipped 2026-05-20 — last verification pending
Stack
Swift 5 · SwiftUI · AppKit NSPanel (HUD window) · CGEventTap (global Force Click detection) · Accessibility API (selected text extraction) · DeepL Free API (translation backend)
Documentation
| Doc | Read this for |
|---|---|
| PRD | What & why — JTBD, scope, single-purpose product decisions, success metrics |
| Architecture | Component diagram, event flow, failure modes |
| Implementation | Tech stack, code structure, gesture detection, permission model, reproducibility |
| Notes | Chronological decision log + macOS gotchas + working-session hours |
Quickstart for users
- Download the
.appbundle (single file, drop in/Applications) - First launch → System Settings prompts for Accessibility + Input Monitoring
- Grant both, restart the app (event watchers registered while AX=false stay dead silently)
- Select text anywhere, Force Click on the trackpad — HUD appears next to the cursor
- Escape (or any keypress) dismisses
Project status
| Phase | Milestone |
|---|---|
| P0 | Menubar scaffold + DeepL API client |
| P1 | ⌘⌥T global chord → HUD render |
| P2 | Accessibility API selected-text extraction |
| P3 | CGEventTap for Force Click pressure detection |
| P4 | HUD positioning + Escape dismiss + any-key dismiss |
| P5 | Auto-detect source language + 280-char truncate |
| P6 | Permission rebuild ritual + AX restart guard |
All 6 phases shipped 2026-05-20. Last verification pending.
Why this exists
Every existing translator (DeepL, Apple Translate, Translate Tab, PopClip) demands the user leave the sentence they’re reading — open a window, paste, copy back. For 6-word phrases the round-trip cost > the value. The product decision that made this stick is the input gesture, not the translation engine. See the blog post for the JTBD framing and existing-alternatives audit.