A dedicated, always-findable home for the browser tabs you can't afford to lose. macOS only.
Not a general browser: a minimal app (Tauri v2) that renders a curated, declarative set
of "keeper" tabs from a config.toml config, and refuses to let new-tab navigation
pollute that set — handing every such intent off to your macOS default browser instead.
Important tabs (mail, calendar, dashboards) get buried in a sea of browser windows. Firefox pinned tabs are the closest workaround, but the pinned window itself gets lost and keeping it clean is constant manual work. curator gives keeper tabs a distinct, stable home that lives outside the window-pile and never accumulates cruft — curation is file-driven, everything else is ephemeral.
config.tomlis the source of truth — each[[window]]block opens one window, containing[[window.group]]and[[window.group.tab]]entries. No in-app pin/unpin; you curate by editing the file (hot-reloaded on save).- Multiple windows — each
[[window]]opens its own window with its own tab list. All open at launch; ⌘W closes any non-last window and the Window menu reopens it. - Keeper tabs are home bases — wander within a session, then snap any tab back to its canonical URL with the sidebar's ⌂ home button (or by re-clicking the active tab); every tab also resets on restart.
- New-tab intents escape —
target="_blank",window.open, cmd/middle-click all shell out toopen, routing to your macOS default browser instead of opening in curator. - Sessions persist, and are shareable — log into a site once in-app and it stays. By
default every tab shares one login store, so signing into a provider covers its related
services (Gmail, Calendar, …). Set a tab's (or a window's)
session = "name"to give it a separate account; reuse the same name elsewhere to share that login. Logins follow thesessionname, so renaming a window or editing a URL never signs you out. - Page-first chrome — the active page fills the window edge-to-edge, painting under an overlay title bar; the native title bar (with traffic lights, draggable) is exposed only as a strip above the sidebar tab list.
always_loadkeeps a tab live — mark a chat/servicealways_loadand it loads at launch, stays live in the background, fires native banners, and rolls its unread count up to the dock badge. Tabs without it are lazy and stay quiet until you open them. That one per-tab flag is the only knob — no per-window modes.- Dock badge aggregates across windows — the badge total sums unread across every window's loaded tabs.
- Window menu — close a non-last window (⌘W); reopen any closed window from the Window menu.
In Claude Code, run /curator:install — it checks prerequisites (offering to install
any that are missing), builds curator from source into ~/.curator, installs curator.app
to /Applications, and seeds your config.
Or install from a terminal:
curl -fsSL https://raw.githubusercontent.com/Lockyc/curator/main/install.sh | bashRe-running either path updates curator (git pull + rebuild). The steps below describe the
manual / contributor flow.
-
Copy the sample config into place:
mkdir -p ~/.config/curator cp examples/config.toml ~/.config/curator/config.toml
It lives under
~/.config/so it slots into a dotfiles workflow — your curated tab set becomes versioned, portable config. -
Run it (requires Rust + Node):
just dev # or: npm run tauri devjust devloads the repo'sexamples/config.toml(via theCURATOR_CONFIGenv var) so iterating never touches your real~/.config/curator/config.toml. PointCURATOR_CONFIGat any file to test another config.just buildproduces a.appbundle;just deploybuilds and installs/updates it in/Applications(quitting the running copy and relaunching).just testruns the Rust tests. The app icon source issrc-tauri/icons/icon.svg— re-runnpx tauri icon src-tauri/icons/icon.svgafter editing it. -
Edit
~/.config/curator/config.tomland save — the sidebar hot-reloads, no restart. A malformed file keeps the last-good config running and shows an error banner instead of crashing. The Config menu has Edit Config / Reveal Config in Finder so you needn't memorise the path; the Tabs menu has Reload Tab (⌘R) and Reset All Tabs to snap every open tab back to its canonical URL.
curator opens one window per [[window]] block. Each window inlines its groups and tabs:
# App-global options
# dark_mode = true # force dark appearance; omit = follow system
# allow_insecure = ["192.168.1.1"] # accept self-signed TLS for these hosts
[[window]]
title = "Keepers" # required; must be unique across windows
# width = 1500 # optional; default 1500 × 1000
# height = 1000
# open_on_launch = "Grafana" # true/false/"Tab Title"
[[window.group]]
name = "Dashboards"
[[window.group.tab]]
title = "Grafana"
url = "https://play.grafana.org/"
always_load = true # load at launch + keep live
reload_every = 5 # auto-refresh every 5 minutes
[[window]]
title = "Comms"
[[window.group]]
name = "Chat"
[[window.group.tab]]
title = "Mattermost"
url = "https://community.mattermost.com/"
always_load = true # kept live → fires banners + unread in the background| Field | Type | Default | Meaning |
|---|---|---|---|
title |
string | required | Window title; must be unique across all windows. |
width/height |
int | 1500/1000 |
Initial window size in logical pixels. Applied at launch (restart to change). |
open_on_launch |
bool | tab title string | false |
true opens the first tab; a string opens the named tab; false = blank screen. |
session |
string | none | Default login store for this window's tabs (overridden per tab). See sessions below. |
Each [[window.group.tab]] requires title and url. Optional:
| Field | Type | Default | Meaning |
|---|---|---|---|
always_load |
bool | false |
Load at launch and keep the tab live in the background, so it fires native banners and reports unread even when it isn't the active tab. |
reload_every |
positive int | none | Auto-refresh the canonical URL every N minutes. |
session |
string | none | Login store for this tab. Tabs sharing a value share a login (even across windows); distinct values are isolated accounts. Falls back to the window's session, then a shared app-wide store. A blank or whitespace-only value is treated as unset and falls through the chain. |
| Field | Type | Default | Meaning |
|---|---|---|---|
dark_mode |
bool | false |
Force dark appearance so sites honouring prefers-color-scheme render dark. |
allow_insecure |
list of hosts | [] |
Accept self-signed/invalid TLS certs for these hosts. Applied at launch (restart to change). |
Tabs are lazy by default: a webview is created on first activation and kept warm for the session. Each row shows a green dot when its tab is loaded — click it to unload (free that webview's memory); the tab reloads on next click. A navigation pill at the top of the sidebar drives the active tab: ◀ back and ▶ forward through in-page history, and ⌂ home to snap back to its canonical URL.
See examples/config.toml for a two-window starting-point example.
