v1.0.0 · macOS · MIT

One TOML file.
The right browser.
Always.

Eri is a one-shot macOS link router. Click a link, Eri picks the right browser from ~/.config/eri/config.toml, opens it, and exits — all in well under a second. No menu bar, no preferences pane, no analytics. ~600 lines of Swift around open(1).

Install Eri View on GitHub $ brew install novacore-cc/tap/eri
~/.config/eri/config.toml
1 # ~/.config/eri/config.toml
 
3 # Browsers — define once, reference by id
4 [browsers.safari]
5 browser = "com.apple.Safari"
 
7 [browsers.chrome-personal]
8 browser = "com.google.Chrome"
9 profile = "john@gmail.com"
 
11 [browsers.chrome-work]
12 browser = "com.google.Chrome"
13 profile = "Work"
 
15 # Rules — top to bottom, first match wins
16 [[rule]]
17 host = "github.com"
18 browser = "chrome-personal"
 
20 [[rule]]
21 domain = "work.example.com"
22 browser = "chrome-work"
 
24 [[rule]]
25 url_regex = "^https?://localhost(:\d+)?.*$"
26 browser = "org.mozilla.firefox"
 
28 [default]
29 browser = "safari"
Clicked link
waiting
Opens in
Safari
default profile
match  → …
resolve→ …
open(1)→ …
What it is

For people who keep everything in their dotfiles.

If your config lives in a git repo and rsyncs across machines, the existing macOS link routers tend to get in the way. Their state hides in plist files, GUI prefs, or embedded JavaScript engines. Eri is the opposite: a single text file you commit, review, and grep.

01

No UI, no preferences pane.

Every behavior change is an edit to one TOML file. No settings window with state hidden in ~/Library/Preferences that has to be re-clicked on every fresh machine.

02

Trivially version-controlled.

The config lives at ~/.config/eri/config.toml by default — drops straight into the same dotfiles repo you already manage. A new Mac is one stow away from your full setup.

03

Nothing resident, nothing phoning home.

One-shot. Eri wakes up, picks a browser, calls open(1), and exits in a fraction of a second. No analytics, no auto-update, no account, no daemon.

The whole surface area

One file. Four match types. First match wins.

Rules match by exactly one of host (glob), domain (subdomain-aware), host_regex, or url_regex. Define browsers once with profile + args, reference them by id from rules. That's it.

config.example.toml TOML · 36 lines
# Fallback when no rule matches.
[default]
browser = "safari"

[browsers.safari]
browser = "com.apple.Safari"

[browsers.chrome-personal]
browser = "com.google.Chrome"
profile = "john@gmail.com"   # your signed-in Google account works as a profile id

[browsers.chrome-work]
browser = "com.google.Chrome"
profile = "Work"

# Rules are evaluated top-to-bottom; first match wins.
[[rule]]
host    = "github.com"
browser = "chrome-personal"

[[rule]]
domain  = "work.example.com"
browser = "chrome-work"

[[rule]]
domain  = "notion.so"
browser = "chrome-personal"

# Inline form — bundle id directly, no [browsers] entry needed.
[[rule]]
url_regex = "^https?://localhost(:\d+)?(/.*)?$"
browser   = "org.mozilla.firefox"

Chrome profile names work too. profile = "Personal" or "you@gmail.com" both resolve against Chrome's Local State so you never have to write "Profile 7".

How it compares

If you want a popup picker, use something else.

Eri sits in a specific niche: declarative, file-based routing that survives a clean macOS install by git pull-ing your dotfiles. Here's where it differs from the alternatives.

Eri Velja / Choosy / Browserosaurus Finicky
UI surface none menu-bar app + prefs window none
Config format TOML file GUI (plist-backed) JavaScript file
Git-syncable across machines yes, single text file partial — GUI state yes
Runtime model one-shot, exits per click resident agent resident agent
External dependencies none (vendored toml++) embedded JS engine
Bundle size ~2 MB ~10–110 MB (Browserosaurus is Electron) ~30 MB

If you want a popup picker every time you click a link, Eri is the wrong tool — use Velja or Choosy. Eri is for declarative routing that survives a clean install.

Install

Two commands. Then pick Eri in System Settings.

Requires macOS 12 or newer. Eri must be a proper .app bundle registered with LaunchServices before macOS will list it as a default-browser candidate — both methods below handle that for you.

Recommended · Homebrew
$ brew install novacore-cc/tap/eri
Installs the signed .app, registers it with LaunchServices, and updates cleanly with brew upgrade.
From source · Make
$ git clone … && make install
Builds build/Eri.app, copies to /Applications, and registers with LaunchServices. Requires Swift 5.9+ and pngquant.
Eri (えり / 選) is a Japanese given name that also carries the meaning to select, to pick. Which is, more or less, the entire job description.