A lightweight macOS menu bar utility that intercepts every link you click and routes it to the right browser — or the right browser profile — based on rules you define.
Inspired by Velja.
- Universal Link Routing — registers as your Default Web Browser and intercepts all
http/httpsclicks system-wide - Three match modes — Wildcard (
*.zoom.us/*), Regex, or Contains - Browser Profile Support — route URLs to a specific Chromium profile (Chrome, Brave, Edge, Vivaldi) via
--profile-directory - Privacy Shield — strips
utm_*,fbclid,gclid, and 25+ other tracking parameters before opening - Global Fallback — choose which browser handles URLs that match no rule
- Drag-to-reorder rules — priority is evaluated top to bottom; first match wins
- macOS Handoff — URLs handed off from iPhone/iPad pass through the same routing engine
- Menu bar only — no Dock icon, lives quietly in your menu bar
- macOS 14.0 (Sonoma) or later
- Xcode 14.0 or later
git clone https://github.com/locnh/lync.git
cd Lync
open Lync.xcodeprojPress Cmd+R in Xcode, or from the terminal:
xcodebuild -project Lync.xcodeproj -scheme Lync -configuration Debug build
open ~/Library/Developer/Xcode/DerivedData/Lync-*/Build/Products/Debug/Lync.appGo to System Settings → Desktop & Dock → Default web browser → Lync.
Lync/
├── Lync.xcodeproj/
└── Lync/
├── LyncApp.swift # @main — MenuBarExtra + Settings scenes
├── AppDelegate.swift # Apple Event handler (kAEGetURL interception)
├── Info.plist # CFBundleURLTypes for http/https, LSUIElement
├── Lync.entitlements # App Sandbox disabled
├── Assets.xcassets/
├── Models/
│ ├── Rule.swift # Routing rule model (Codable)
│ └── Browser.swift # Installed browser model
├── Services/
│ ├── URLRouter.swift # Core routing engine + UserDefaults persistence
│ ├── BrowserDiscovery.swift # Finds browsers via NSWorkspace
│ └── URLCleaner.swift # Strips tracking query parameters
├── ViewModels/
│ └── RulesViewModel.swift
└── Views/
├── MenuBarView.swift # Popover with stats & quick toggles
├── SettingsView.swift # Tabbed settings window (Rules, General, Setup Guide, About)
├── RulesView.swift # Rule list with reorder & delete
├── RuleEditorView.swift # Inline add / edit rule editor
└── OnboardingView.swift # First-launch setup guide
- You click any link in any app on your Mac
- macOS sends a
kAEGetURLApple Event to Lync (the registered default browser) - Lync optionally strips tracking parameters
- Rules are evaluated top to bottom — the first matching rule wins
- The URL is opened in the rule's target browser (and profile, if specified)
- If no rule matches, the fallback browser opens the URL
| Field | Description |
|---|---|
| Name | Human-readable label for the rule |
| Match Type | Wildcard, Regex, or Contains |
| Pattern | The URL pattern to match against |
| Browser | Target browser (auto-discovered from your system) |
| Profile | Chromium profile directory name (e.g. Default, Profile 1) |
| Type | Pattern | Matches |
|---|---|---|
| Wildcard | *.github.com/* |
Any GitHub URL |
| Wildcard | meet.google.com/* |
Google Meet links |
| Regex | https://(www\.)?notion\.so/.* |
Notion pages |
| Contains | zoom.us/j/ |
Zoom meeting links |
For Chromium-based browsers (Chrome, Brave, Edge, Vivaldi), you can route URLs to a specific profile by entering the profile directory name — not the display name.
To find your profile directory name:
- Open Chrome and go to
chrome://version - Look at Profile Path — the last folder segment is the directory name (e.g.
Default,Profile 1,Work)
When enabled, Lync removes the following parameter families from every URL before opening it:
- UTM —
utm_source,utm_medium,utm_campaign,utm_content,utm_term, … - Facebook —
fbclid,fb_ref,fb_source, … - Google Ads —
gclid,gclsrc,gbraid,wbraid,dclid - Microsoft Ads —
msclkid - HubSpot —
hsa_* - Mailchimp —
mc_cid,mc_eid - TikTok / Pinterest / Twitter —
ttclid,epik,twclid - And more…
Lync follows MVVM:
| Layer | Responsibility |
|---|---|
| Models | Rule, Browser — pure data, Codable |
| Services | URLRouter, BrowserDiscovery, URLCleaner — business logic |
| ViewModels | RulesViewModel — bridges services to views |
| Views | SwiftUI views — purely declarative, no logic |
State is held in URLRouter.shared (an ObservableObject singleton) and persisted to UserDefaults as JSON.
- Prompt: Gemini
- Icon design: Grok
- Code and document: Claude Sonnet
- Publisher: locnh
MIT © 2026 locnh