· 4 min read · Apps Apple

Finicky: the right browser, every time

For years, every link I clicked opened in the wrong browser. Work links landed in Safari, personal stuff ended up in Chrome, and I just lived with it. ⌘C, switch browsers, ⌘V, Enter. Dozens of times a day.

Then I found Finicky.

What it does

Finicky is a free, open-source Mac app that sets itself as your default browser — but doesn’t actually browse anything. Instead, it reads a JavaScript config file and routes every URL to the right browser based on rules you define. Click a link anywhere on your Mac, and Finicky decides where it should open.

The config lives at ~/.finicky.js. Plain JavaScript, version-controllable, easy to read.

My setup

I use two browsers: Safari for personal browsing, Chrome for work. Finicky makes the split automatic.

Browser profiles

At the top of the config, I define the two browsers:

1const personalBrowser = { name: "Safari", profile: "Personal" };
2const workBrowser = { name: "Google Chrome", profile: "Work" };
1const personalBrowser = { name: "Safari", profile: "Personal" };
2const workBrowser = { name: "Google Chrome", profile: "Work" };

Every rule below references one of these two variables.

App-specific routing

Some URLs don’t belong in a browser at all. Spotify links should open in Spotify:

1{
2 match: "*.open.spotify.com/*",
3 browser: "Spotify",
4}
1{
2 match: "*.open.spotify.com/*",
3 browser: "Spotify",
4}

Short, obvious, done.

The Zoom rewrite

This one I wrote myself. Zoom meeting links come in as regular https://zoom.us/j/123456 URLs, but what you actually want is for them to open directly in the Zoom app. Finicky can rewrite URLs before passing them on:

1{
2 match: (url) =>
3 url.host.includes("zoom.us") && url.pathname.includes("/j/"),
4 url: (url) => {
5 const pwd = url.searchParams.get("pwd");
6 const confNo = url.pathname.match(/\/j\/(\d+)/)[1];
7 
8 const newUrl = new URL(url.href);
9 newUrl.protocol = "zoommtg";
10 newUrl.pathname = "/join";
11 newUrl.search =
12 `confno=${confNo}` + (pwd ? `&pwd=${pwd}` : "");
13 
14 return newUrl;
15 },
16}
1{
2 match: (url) =>
3 url.host.includes("zoom.us") && url.pathname.includes("/j/"),
4 url: (url) => {
5 const pwd = url.searchParams.get("pwd");
6 const confNo = url.pathname.match(/\/j\/(\d+)/)[1];
7 
8 const newUrl = new URL(url.href);
9 newUrl.protocol = "zoommtg";
10 newUrl.pathname = "/join";
11 newUrl.search =
12 `confno=${confNo}` + (pwd ? `&pwd=${pwd}` : "");
13 
14 return newUrl;
15 },
16}

It rewrites the URL to use the zoommtg:// protocol, which launches Zoom directly into the meeting. No browser tab, no “Open Zoom?” dialog. Just click and join.

Work domains

The most important rule routes work-related domains to Chrome:

1{
2 match: (url) =>
3 /(?:work-tool|project-tracker|company-gitlab)/.test(url.host),
4 browser: workBrowser,
5}
1{
2 match: (url) =>
3 /(?:work-tool|project-tracker|company-gitlab)/.test(url.host),
4 browser: workBrowser,
5}

The real config has about a dozen domains in that regex — project management tools, internal GitLab, time tracking, that sort of thing. Every work-related link opens in Chrome automatically. Everything else falls through to the catch-all.

The catch-all

At the bottom, a simple fallback:

1{
2 match: () => true,
3 browser: personalBrowser,
4}
1{
2 match: () => true,
3 browser: personalBrowser,
4}

Anything that doesn’t match a specific rule opens in Safari. Personal browsing stays personal.

What works well

Honestly? Almost everything. The work/personal split alone was worth the install. I don’t think about which browser to use anymore — links just go where they belong.

The Zoom rewrite saves me a small annoyance every day. No more “this meeting is about to start in your browser” nonsense.

I’ve been using Finicky since late 2024 and can’t remember the last time it misbehaved.

Worth a look

If you use more than one browser on your Mac — and especially if you keep work and personal browsing separate — Finicky is one of those tools that quietly removes a daily irritation. Free, open-source, actively maintained.