Integrations
Links don't only arrive from clicks. This page covers sign-in popups, other URL schemes, scripts and browser add-ons, and shortened links.
Sign-in popups
Apps that sign in with ASWebAuthenticationSession send their
URLs through AuthenticationServices rather than ordinary URL delivery.
Grinch routes these requests with the same rules as other links, and opens
the sign-in page in the selected browser as a normal tab. It does not move
the authentication session into that browser or watch what the page does
next. Since the requesting app isn't available to Grinch, rules see
com.apple.AuthenticationServices as the opener and no modifier
keys for these requests.
Requests that arrive while Grinch is starting wait for the first config load. If no config is available, a rule suppresses the URL, or the browser can't be opened, Grinch ends the sign-in request with an error. Requests cancelled during startup don't open a browser.
Ordinary links received during startup also wait for the first config load.
If that load fails, Grinch drops those queued links and records their count
in the diagnostic log.
For a Universal Link delivered as a web activity, Grinch cannot identify the
originating app, so ctx.opener is null.
Finishing the sign-in is best effort. The
callback has to come back to Grinch to complete the pending session. Grinch
matches incoming callback URLs against pending requests and returns matching
ones to the app that asked. If a callback matches more than one pending
request, Grinch cancels those requests so it doesn't deliver the response to
the wrong app. Registering a callback with
ASWebAuthenticationSession doesn't make Chrome send it to
Grinch, so apps that rely only on the session callback can keep waiting
after the sign-in page has done its job.
On macOS 13 through 14.3, callbacks are matched with the older custom-scheme API. HTTPS host-and-path callbacks need macOS 14.4 or later.
Startup timing and private sessions
Grinch installs its sign-in handler before it starts accepting events, so
a request made while Grinch is still launching doesn't fall through to
Safari. Grinch also declares CallbackURLMatchingIsSupported,
because some apps, notably Slack, only use browsers that advertise it.
Grinch declares IsSupported but not
EphemeralBrowserSessionIsSupported. It opens your regular
browser tab, with your existing cookies and profile, so it can't provide
the isolation a private (ephemeral) session asks for. macOS may handle
those requests in Safari instead, and they bypass your rules.
Other URL schemes
Grinch can also route local .html files and Universal Links
delivered as web activities. Delivery depends on your macOS file and link
associations.
Grinch declares support for tel:, webcal:, and
feed:, but macOS may send those links to another app. When a
link is delivered to Grinch, it goes through the same rules; match it with
a scheme pattern such as "webcal:*". You can also use the
grinch: prefix to send an
individual link through Grinch.
The grinch: scheme
Put grinch: in front of any URL to route it through your rules,
even when Grinch isn't the default browser. This works from Shortcuts,
AppleScript, and open in a shell:
open grinch:https://example.com/path
open 'grinch:tel:+15551234567'
Grinch removes the grinch: prefix first, so your rules match
the inner URL. Grinch --test grinch:… tests the same way.
Browser add-ons
Grinch also accepts grinch://open/<base64-url>, where
the inner URL is encoded with btoa(). This is the format
Finicky's Chrome and Firefox add-ons send. Point those add-ons at
grinch://open/… instead of finicky://open/… and
their "Open with Finicky" menu item routes through Grinch, whether or not it
is the default browser. Standard (+, /) and
URL-safe (-, _) base64 both work, with or without
= padding.
URL shorteners
Grinch decides synchronously, so a rule can't follow a short link's
redirects; await fetch() doesn't run. For hosts such as
bit.ly, t.co, lnkd.in, and
ow.ly, choose one of two approaches.
Send them to your usual browser
Your rules won't see the final host, but the browser opens normally with no added delay:
{
match: domain("bit.ly", "t.co", "lnkd.in", "ow.ly", "buff.ly", "tinyurl.com"),
open: browsers.personal,
}
Expand them before Grinch
examples/expand-shortener.sh
follows redirects from bit.ly, t.co, goo.gl, lnkd.in, ow.ly, buff.ly, and
tinyurl.com, including their www. forms, making at most ten
requests in five seconds. It opens the first destination outside those
hosts with open, leaving login redirects and cookies to your
browser, and Grinch routes that destination normally. Other hosts pass
through, and if expansion fails the original URL opens.
chmod +x examples/expand-shortener.sh
examples/expand-shortener.sh "https://bit.ly/3GyNJpL"
Run it from a launcher you already use:
- Raycast or Alfred: bind it to a hotkey that passes the URL on the clipboard.
- Hammerspoon: register an
hs.urleventhandler that calls the script with the URL. - Shortcuts: wrap it in a Quick Action that takes URLs
from the share sheet and runs
expand-shortener.sh "$1". - Terminal: copy the link, then run
examples/expand-shortener.sh "$(pbpaste)".
Shortened links then wait for a network round trip, typically 50 to 500 ms, but that happens outside Grinch, so every other link still routes without it.