Skip to content

Repository files navigation

Ptions+

A native macOS menu bar app that maps extra mouse buttons to keyboard shortcuts — per app.

Replaces bloated vendor software with a fast, focused, open-source alternative. Built with SwiftUI.

macOS 13+ Swift 5.9 License: MIT


Ptions+ Settings — Profile Editor


The Problem

You have a mouse with extra buttons. The vendor's companion app is 200 MB, phones home, requires an account, and breaks after every macOS update. You just want Back to trigger Cmd+[ in Safari and Mission Control on the thumb button everywhere else.

Ptions+ does exactly that. Configure button mappings per-app, set system actions, and forget about it. Runs in the menu bar, uses ~8 MB of RAM, zero network calls.

Features

Per-app profiles — Different mappings for every app. Safari gets browser navigation, Xcode gets build shortcuts, everything else gets your defaults.

System actions — Mission Control, App Expose, Show Desktop, and Launchpad use a dynamically detected CoreDock integration with graceful fallback when unavailable.

Shortcut recorder — Click "Assign", press your key combo. Supports all modifier combinations.

16 preset actions — Spotlight, Screenshot Tool, Notification Center, Lock Screen, and more. Logical shortcuts adapt to the active keyboard layout.

Supported mouse models — Manually select MX Master 4/3/3S/2S, MX Anywhere 3, MX Ergo, MX Vertical, G502, G604, or a generic 3/5-button model.

Launch at login — Native SMAppService integration.

Debug monitor — Live view of raw mouse events for troubleshooting.

Supported Mice

Logitech MX Logitech G Generic
MX Master 4 G502 Generic (5 buttons)
MX Master 3 G604 Generic (3 buttons)
MX Master 3S
MX Master 2S
MX Anywhere 3
MX Ergo
MX Vertical

Any mouse that sends otherMouseDown events via HID will work. Pick the closest model or use Generic.

Getting Started

Prerequisites

  • macOS 13 Ventura or later
  • Xcode 15+
  • The vendor's companion software must be uninstalled — it captures mouse events before Ptions+ can

Build from source

git clone https://github.com/trsdn/PtionsPlus.git && cd PtionsPlus
xcodebuild -project PtionsPlus.xcodeproj -scheme "Ptions+" -configuration Release build

Copy the built app to /Applications:

cp -R ~/Library/Developer/Xcode/DerivedData/PtionsPlus-*/Build/Products/Release/Ptions+.app /Applications/
xattr -cr /Applications/Ptions+.app
open /Applications/Ptions+.app

Signed Release Build

The release flow is three commands: bump version, sign, notarize.

First create your local release config:

scripts/setup-notarization.sh --gui
./scripts/bump-version.sh patch   # or: minor, major
bash scripts/sign-release.sh
xcrun notarytool store-credentials "PtionsPlus" \
     --apple-id "your@email.com" \
     --team-id "YOUR_TEAM_ID" \
     --password "app-specific-password"
bash scripts/notarize.sh

If you already have a working notarytool keychain profile from another project, set it in .release.env or inline:

TEAM_ID="YOUR_TEAM_ID"
CODE_SIGN_IDENTITY="Developer ID Application: Your Name"
NOTARY_PROFILE="your-notary-profile"

The release scripts produce four outputs:

  • build/PtionsPlus.xcarchive/Products/Applications/Ptions+.app
  • dist/Ptions+.zip
  • dist/Ptions+.dmg
  • dist/Ptions+.dmg.sha256

The final ZIP and DMG are rebuilt from the stapled app and verified before upload. Verify a downloaded DMG with:

shasum -a 256 -c Ptions+.dmg.sha256

The GitHub release workflow builds signed, notarized artifacts on v* tags. Configure these repository secrets first: MACOS_CERTIFICATE, MACOS_CERTIFICATE_PWD, APPLE_ID, APPLE_TEAM_ID, and APPLE_APP_PASSWORD.

Grant Accessibility Access

On first launch, Ptions+ will prompt for Accessibility permissions. This is required to intercept mouse events system-wide.

System SettingsPrivacy & SecurityAccessibility → enable Ptions+

How It Works

Mouse Button Press
       │
       ▼
  CGEventTap (EventTapService)
       │
       ▼
  Active App Lookup (ActiveAppMonitor)
       │
       ▼
  Profile Match (MappingStore)
       │
       ├── Has mapping? → Coordinated input / available system action → Suppress event pair
       │
       └── No mapping?  → Pass through

A session-level CGEventTap intercepts otherMouseDown / otherMouseUp events. A deterministic state machine keeps each down/up suppression decision paired, coordinates held shortcuts, and passes unsupported model buttons through. Mapped buttons either simulate a keyboard shortcut via CGEvent posting or trigger an available system action.

Configuration

All configuration lives in a single JSON file:

~/Library/Application Support/Ptions+/config.json

Reset to defaults:

rm ~/Library/Application\ Support/Ptions+/config.json

The app regenerates default config on next launch.

Configuration writes are validated and atomic. If the file is corrupt or semantically invalid, Ptions+ preserves it, blocks interception, and offers an explicit backed-up repair or reset.

Testing

xcodebuild -project PtionsPlus.xcodeproj -scheme "Ptions+" \
  -configuration Debug -destination "platform=macOS" \
  CODE_SIGNING_ALLOWED=NO test -only-testing:PtionsPlusTests

xcodebuild -project PtionsPlus.xcodeproj -scheme "Ptions+" \
  -configuration Debug -destination "platform=macOS" \
  test -only-testing:PtionsPlusUITests

Project Structure

PtionsPlus/
├── PtionsApp.swift              # Entry point, AppDelegate, lifecycle
├── Model/
│   ├── ButtonMapping.swift      # Data models: profiles, mappings, mice
│   ├── MappingStore.swift       # Transactional state and profile lookup
│   └── ConfigurationPersistence.swift
├── Services/
│   ├── EventTapService.swift    # CGEventTap lifecycle and diagnostics
│   ├── EventStateMachine.swift  # Paired mouse-event decisions
│   ├── KeySimulator.swift       # Coordinated CGEvent and preset execution
│   ├── RuntimeServiceCoordinator.swift
│   ├── LaunchAtLoginService.swift
│   ├── ApplicationDiscoveryService.swift
│   ├── ActiveAppMonitor.swift   # Tracks frontmost app bundle ID
│   └── AccessibilityChecker.swift
├── Views/
│   ├── MenuBarView.swift        # Menu bar dropdown
│   ├── SettingsView.swift       # Settings window (tabbed)
│   ├── ProfileListView.swift    # Sidebar profile list
│   ├── ProfileEditorView.swift  # Button mapping editor
│   ├── ShortcutRecorderView.swift
│   ├── AppPickerView.swift
│   ├── PermissionGuideView.swift
│   └── DebugMonitorView.swift
└── Utilities/
    ├── KeyCodeMap.swift
    └── Constants.swift

Disclaimer

Ptions+ is an independent, open-source project. It is not affiliated with, endorsed by, or associated with Logitech, Logi, or any of their subsidiaries or products. All product names, trademarks, and registered trademarks mentioned in this project are the property of their respective owners. Mouse model names are used solely for compatibility identification purposes.

License

MIT


Built because life's too short for bad companion software.

About

A native macOS menu bar app that maps extra mouse buttons to keyboard shortcuts — per app. Open-source replacement for bloated vendor software.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages