# Trackpad gesture app design
## Skills Used
- file-management
## Retrieval Notes
- Session id: `c92c6cfa-f4a8-4779-9c46-f5955efaee70`
- Last activity: `2026-07-13T10:16:47.056Z`
- Files touched: `5`
## Artifacts
**Created:**
- `/Users/nickyoung/Developer/TrackpadGestures/Package.swift`
- `/Users/nickyoung/Developer/TrackpadGestures/Sources/touchspike/main.swift`
- `/Users/nickyoung/Developer/TrackpadGestures/Sources/MultitouchKit/MultitouchKit.swift`
- `/Users/nickyoung/Developer/TrackpadGestures/Sources/touchviz/main.swift`
- `/Users/nickyoung/Developer/TrackpadGestures/Sources/GestureKit/GestureRecognizer.swift`
## My Notes
<!-- Add your notes here. This section is preserved across syncs. -->
## Conversation
### User
I would like you to help me create something of a clone of BetterTouchTool. However, this clone will only focus on trackpad gestures, and it will be a much more user‑friendly, less fiddly, more beautiful experience than the current BetterTouchTool. Key things I’d be interested in getting correct are ease of creating gestures, re‑editing gestures, and similar tasks. I would also like it to be as wide‑ranging in terms of how many gestures are available as BetterTouchTool, which has a great deal as well.
Okay, so let’s go slowly on this. I’m not quite sure; maybe you can help me decide exactly what I want. Hopefully this gives you something to start with.
### Assistant
This is a fun project. Before I help you shape it, let me quickly verify the current technical landscape for trackpad gesture recognition on macOS — that reality constrains a lot of the design decisions, and I don't want to advise from stale knowledge.
### Assistant
Your setup is actually ideal for this: macOS 26.5 (Tahoe), Apple Silicon, Swift toolchain already installed, and a Magic Trackpad (plus presumably a built-in one if this is a laptop). The private framework reads both. One flag: being on Tahoe means the finger+thumb app-picker conflict I mentioned applies directly to you, so conflict handling isn't a nice-to-have — it's something you'd hit in week one.
Here's the shape I'd propose, now that I know what you want. Since you weren't sure how to start, I'll make the call: start with the technical spike, because it happens to also be the seed of the feature you care most about.
The convergence is this. The spike that proves the risky part — linking the private MultitouchSupport framework and reading raw touches — is naturally demonstrated by a floating window that shows your fingertips moving on the trackpad in real time. That live visualization is the foundation of the gesture-creation flow you want: instead of BTT's dropdown maze, you open "new gesture," perform the motion on the trackpad while watching your fingers on screen, and the app recognizes and proposes it ("four-finger swipe left — bind it to something?"). So the first afternoon of engineering work produces both the technical proof and the first piece of the actual product. No throwaway code.
After the spike, the layers stack naturally:
1. Engine — a recognizer sitting on the raw touch stream: taps and swipes at every finger count, pinch, rotate, spread, corner taps, edge swipes, force clicks, tip-taps. This is the hard, interesting part, and it's where "reliability" is won or lost — good recognition thresholds are what stop misfires.
2. Actions — the catalog: send keystroke, launch or switch app, run shell or AppleScript, window snapping, media and system controls, open URL, and so on. Wide but shallow; this grows fast.
3. The app itself — menu bar item plus a genuinely Mac-like SwiftUI settings window: the record-a-gesture creation flow, a scannable library with visual glyphs for each gesture, per-app profiles, and upfront conflict warnings ("this gesture is claimed by Mission Control — disable it in System Settings or pick another").
Since it's a personal tool, we skip everything that makes this a multi-year project: no notarization, no updater, no onboarding, no App Store, config lives in a plain file you can version.
Two things I need from you before writing any code: where do you keep code projects on this machine (I don't want to guess — the vault obviously isn't the place), and shall I start the spike there? If you don't have a projects folder yet, I'd suggest `~/Developer/` — it's the macOS-conventional spot and Finder even gives it a special icon.
Sources: [MiddleDrag](https://github.com/NullPointerDepressiveDisorder/MiddleDrag), [Multitouch](https://multitouch.app/), [BTT Tahoe gesture conflict thread](https://community.folivora.ai/t/unable-to-remap-3-1-4-1-finger-trackpad-gestures-tahoe-app-picker-conflict/45299)
*Il trackpad nasconde sotto il vetro una mappa di dita che il sistema di solito tiene per sé.*
### User
"Two things I need from you before writing any code: where do you keep code projects on this machine (I don't want to guess — the vault obviously isn't the place), and shall I start the spike there? If you don't have a projects folder yet, I'd suggest ~/Developer/ — it's the macOS-conventional spot and Finder even gives it a special icon." yep
### Assistant
Starting the spike. First I need to load the file-management skill, since everything here happens outside the vault and Bash paths need the indirection workaround.
### Assistant
The spike worked on the first run — raw touch data is flowing. Here's what the terminal showed while you (I assume) had a finger on the trackpad:
```
touchspike: MTTouch stride = 96 bytes
*** Recognized (0x81) family*** (30 cols X 22 rows)
touchspike: started 1 multitouch device(s). Touch the trackpad.
[699.550] 1 finger(s): #2 (0.57, 0.36) p=0.60
[701.485] all fingers lifted
[702.850] 1 finger(s): #2 (0.54, 0.34) p=0.56
[703.105] 1 finger(s): #2 (0.53, 0.30) p=0.60
```
That's everything the whole project rests on, confirmed live on your machine: per-finger identity (`#2`), position in normalized 0–1 coordinates, pressure, and lift events, streaming in real time from your Magic Trackpad (which the framework even identified as a 30×22 sensor grid). Notably, it worked without any permission dialog — the raw touch stream didn't require Input Monitoring approval in this context, though we should re-verify that when it becomes a standalone app rather than a child of this session.
What now exists:
- [~/Developer/TrackpadGestures](file:///Users/nickyoung/Developer/TrackpadGestures) — a git-initialized SwiftPM project (nothing committed yet; say the word and I'll make the first commit)
- `Sources/touchspike/main.swift` — the spike: private-framework bindings, the MTTouch struct layout, device discovery with Bluetooth polling, and a throttled live touch printer
- Bindings and struct layout were taken from MiddleDrag's source (MIT-licensed, verified working on Tahoe) rather than my memory, and its codebase gave us valuable tribal knowledge for later: the framework has internal race conditions around sleep/wake that need a cleanup delay, Bluetooth trackpads connect late at boot so device polling is essential, and registering for system gesture events (types 29–32) in an event tap freezes Mission Control — a landmine we now know to step around.
If you want to play with it yourself, run this in a terminal and move your fingers around:
```
~/Developer/TrackpadGestures/.build/debug/touchspike
```
The natural next step is the fun one: the floating visualizer window that draws your fingertips live — which, per the plan, doubles as the seed of the gesture-recording UI. After that, the recognizer (taps, swipes, pinches with finger counts) sitting on this same stream. Ready to build the visualizer whenever you are.
*Sotto il vetro c'è una griglia di trenta per ventidue sensori, e adesso finalmente la sentiamo parlare.*
### User
go go go
### Assistant
Building the visualizer now. I'll restructure the package first — a shared `MultitouchKit` library holding the private-framework bindings, with `touchspike` and the new `touchviz` app both sitting on top of it. That same kit later becomes the foundation the real engine imports.
### Assistant
Now the visualizer itself:
### Assistant
The visualizer is live — `touchviz` is running and registered with the window server, so you should see a floating dark window titled "Trackpad — Live Touches" in the middle of your screen. Go play: put fingers on the trackpad.
What you should see:
- Each finger appears as a colored dot (color stays stable per finger) with its finger ID number on it
- Dot size grows with pressure — press harder and it swells
- The dot is actually an ellipse matching your fingertip's contact patch orientation, so a flat thumb reads differently than a fingertip
- Swipes leave a fading 0.6-second trail, so you can literally see the shape of a gesture after you've made it
- A counter in the top corner tracks how many fingers are down — try putting all five down
Two things to sanity-check for me while you play, since I can't see your screen: does the motion direction match (moving your finger up moves the dot up, left goes left)? And does the dot land roughly where your finger is on the physical surface (a finger in the top-right corner draws in the top-right)? Those confirm my assumption about the coordinate system's origin; if either is mirrored, it's a one-line flip.
The window keeps a trackpad-proportioned aspect ratio when you resize it, floats above other windows, and quits when you close it. To relaunch it yourself any time: `~/Developer/TrackpadGestures/.build/debug/touchviz`.
Once you confirm the orientation is right, the next layer is the recognizer — the code that watches this same stream and says "that was a three-finger swipe left" — and this window becomes its debugging instrument: we can overlay the recognizer's live verdict on top of the touch display, which is exactly the record-a-gesture flow the real app needs.
*Guarda lo schermo mentre muovi le dita: ogni polpastrello lascia una scia colorata, come una cometa in miniatura.*
### User
seems to be working fine
### Assistant
The engine layer, then — the recognizer that turns that stream into named gestures, with its verdicts overlaid live in the visualizer window. That gives you an immediate feel for recognition quality, which is where BTT-level reliability gets won.
### Assistant
Now wire it into the package and overlay verdicts in the visualizer:
### Assistant
The window is back up, now with a brain. Play with it — every time you lift your fingers, the recognizer classifies what you just did and flashes its verdict in the middle of the window ("3-finger swipe ←", "2-finger pinch", "4-finger tap"...), fading over a second and a half. Each verdict is also logged where I can read it, so after you've played I can audit how well recognition matched what you actually did.
Things worth trying, roughly in order of difficulty for the recognizer:
- Taps with 1 through 5 fingers (quick touch, no movement)
- Swipes in all four directions with 2, 3, 4 fingers
- Two-finger pinch and spread
- Two-finger rotate, both directions — this one has the trickiest geometry
Two expectations to calibrate: first, macOS will still react to system gestures while you test (3- and 4-finger swipes will trigger Mission Control and Spaces) since we're currently just observing the stream, not consuming it — suppression is a later, deliberate step. Second, the thresholds are first-guess values; if something misclassifies — a sloppy tap read as a swipe, a rotate read as a pinch — that's exactly the feedback I want, and it's a one-number tune.
Tell me what it gets right and what it gets wrong.
*Adesso la finestra non vede soltanto le dita — prova a indovinare l'intenzione dietro il movimento.*
### User
b9ph47r48
toolu_01MjtHLeBbD4k8pxFyjBfCrH
/private/tmp/claude-501/-Users-nickyoung-My-Obsidian-Vault/c92c6cfa-f4a8-4779-9c46-f5955efaee70/tasks/b9ph47r48.output
completed
Background command "Relaunch touchviz with live gesture recognition overlay" completed (exit code 0)
### Assistant
Rebuilt with the changes. I didn't relaunch the window since you'd closed it — when you next feel like a test round, run:
```
~/Developer/TrackpadGestures/.build/debug/touchviz
```
The window will now stay quiet during normal cursor use and scrolling, and every verdict it does show gets logged with its measurements, like `2-finger pinch [move=0.04 dur=0.52s spread=0.61 rot=3°]`. What would help most from the next session is deliberate reps of the things the last log barely touched: pinch and spread, rotate both ways, and taps and swipes at 3, 4, and 5 fingers. A handful of each is enough — with the metrics attached I can tune thresholds from evidence.
Meanwhile the state of the project: raw touch capture proven, live visualizer working, first-pass recognizer classifying taps, swipes, pinches, spreads, and rotations with finger counts, all in a cleanly layered SwiftPM package (`MultitouchKit` → `GestureKit` → apps). The next structural pieces after tuning are the action layer (keystroke, launch app, run script...) and the binding store that maps recognized gestures to actions per app — at which point this stops being a demo and starts being the tool.
Also, this project now has real state worth remembering across sessions — want me to create a `Sessions/Trackpad Gestures.md` project file in the vault so future conversations can pick this up by name?
*Il registro rivela che quasi tutto ciò che facciamo sul trackpad non è un gesto ma semplice deriva del cursore — il rumore di fondo della mano.*