A lightweight macOS menubar app that adds trackpad gestures for Chrome and Safari.
| Gesture | Chrome | Safari |
|---|---|---|
| 3-finger swipe right | Next tab (Ctrl+Tab) |
Next tab (Cmd+Option+Right) |
| 3-finger swipe left | Previous tab (Ctrl+Shift+Tab) |
Previous tab (Cmd+Option+Left) |
| 3-finger tap | Open link in new tab (Cmd+Click) |
Open link in new tab (Cmd+Click) |
Each binding is scoped to its browser, so the right keystroke fires depending on whichever app is frontmost when you swipe.
GestureFlow lives in the menubar — no Dock icon, no window. Edit ~/Library/Application Support/GestureFlow/config.json to add or change bindings (see Config below).
A quick 3-finger swipe still changes a single tab — same as you'd expect. But if you keep your fingers down and keep dragging, the recognizer fires additional tab-changes for every chunk of trackpad travel, so a slow sustained drag scrolls through multiple tabs continuously. Reverse direction mid-drag and the tabs scroll the other way. The "Tab scrub spacing" slider in Preferences controls how much travel maps to one tab change — see below.
Open Preferences… from the menubar icon for sliders that tune how gestures get recognized. Changes apply live — drag a slider and the new value takes effect immediately, no relaunch needed.
| Slider | What it does |
|---|---|
| Swipe threshold | Minimum trackpad travel before a swipe fires the first time. Lower = more sensitive. |
| Tab scrub spacing | Travel between tab changes during a sustained drag. Lower = more tabs per cm of finger motion. |
| Swipe axis ratio | How straight along its primary axis a swipe has to be. Higher = stricter. |
| Swipe min contact | Min contact time before swipe detection kicks in. Protects quick taps from being misread as swipes. |
| Tap max travel | How much fingers can drift during a tap before it's no longer read as a tap. |
| Tap max duration | How long fingers can rest before a tap is read as a hold instead. |
"Reset to defaults" puts everything back if you tune yourself into a corner. "Open config.json" reveals the JSON config (see Config below) for advanced bindings beyond what the sliders cover.
- Download the latest
GestureFlow.app.zipfrom the Releases page and unzip it. - Drag
GestureFlow.appinto your/Applicationsfolder. - First launch: right-click (or Control-click) the app and choose Open, then confirm in the dialog. macOS will warn that the app is from an unidentified developer because GestureFlow isn't notarized — this is expected. You only need to do this once.
- Grant Accessibility permission. Open System Settings → Privacy & Security → Accessibility, click +, and add
GestureFlow.app(or just flip its toggle on if it's already listed). This is required so the app can read trackpad input and synthesize keystrokes and clicks. On some macOS versions you may also need to enable GestureFlow under Input Monitoring in the same pane. - Quit and relaunch GestureFlow once after granting permissions so they take effect.
That's it — try a 3-finger swipe in Chrome or Safari.
~/Library/Application Support/GestureFlow/config.json is watched, so edits reload live.
{
"enabled": true,
"bindings": [
{
"gesture": "3-swipe-right",
"action": { "type": "keystroke", "key": "tab", "modifiers": ["control"] },
"appBundleID": "com.google.Chrome"
},
{
"gesture": "3-swipe-right",
"action": { "type": "keystroke", "key": "right", "modifiers": ["command", "option"] },
"appBundleID": "com.apple.Safari"
},
{
"gesture": "3-tap",
"action": { "type": "modifierClick", "modifiers": ["command"], "button": "left" },
"appBundleID": "com.google.Chrome"
}
]
}{fingerCount}-tap or {fingerCount}-swipe-{left|right|up|down} — e.g. 4-swipe-up, 2-tap. Recognized finger counts are 2, 3, and 4.
| type | fields |
|---|---|
keystroke |
key, modifiers[] |
modifierClick |
modifiers[], button (left/right/middle) |
openURL |
url |
shell |
command |
Omit appBundleID for a global binding. App-specific bindings win over global ones.
GestureFlow uses Apple's private MultitouchSupport.framework to receive raw finger frames from the trackpad (~60 Hz), runs a small state machine to recognize taps and swipes, and synthesizes the corresponding keystrokes or modifier-clicks via CGEvent. Because it uses a private framework and posts synthetic input events, it can't be sandboxed or distributed through the Mac App Store — the same trade-off BetterTouchTool, Jitouch, and MiddleClick make.
If you'd rather build it yourself instead of downloading the release:
brew install xcodegen # one-time
cd GestureFlow
./build.shbuild.sh generates the Xcode project, builds Release, ad-hoc code-signs, and copies the .app to /Applications. Or run xcodegen generate and open GestureFlow.xcodeproj in Xcode and hit ⌘R.
- macOS updates occasionally shuffle symbols inside
MultitouchSupport.framework. If gestures stop working after an OS update, the framework bridge may need a fix. Ctrl+Tabworks in Chrome but not Safari (which usesCmd+Option+Right/Cmd+Option+Left). The defaults already account for this; if you're adding bindings for other browsers, check what shortcut they actually use for tab switching.- 3-finger tap can occasionally double-fire if you push the trackpad down hard enough to register a hardware click — the hardware click and GestureFlow's synthesized Cmd+Click both reach the browser. Either tap lightly (no audible click), increase the click force in System Settings → Trackpad → Point & Click, or rebind the gesture to a 4-finger tap.