@mfittko/tabularasa
v0.2.0
Published
Archive, close and refocus Safari tabs. Every tab lands in a local SQLite inventory; the relevant ones come back, judged by Jev against your calendar and GitHub.
Maintainers
Readme
tabularasa
Archive, close and refocus Safari tabs. Every open tab lands in a local SQLite inventory. The relevant ones come back in a new window, judged by Jev against your calendar, GitHub activity, and whatever context you hand it. Nothing is lost: every tab you ever closed stays searchable.
macOS only. Node 22.13+ (uses node:sqlite), no npm dependencies. Optional CLIs: gws for
Google Calendar, gh for GitHub, claude for free-text requests.
Install
npm install -g @mfittko/tabularasa # or: npm install -g github:mfittko/tabularasa
tabularasa archive # first run: macOS asks whether Node may control Safari; allow it
tabularasa install # daily 06:00 LaunchAgent, archive only, plus the Claude Code skill
tabularasa install --close --reopen # once you trust it: archive, close everything, reopen what's relevantFor development: git clone https://github.com/mfittko/tabularasa && cd tabularasa && npm link.
Jev key: export TYPESAFE_API_KEY=... in ~/.config/typesafe (or the env var).
Use
tabularasa # archive + close all tabs, reopen the relevant ones in a new window
tabularasa archive # archive only, never closes
tabularasa close # archive + close, reopen nothing
tabularasa focus # dry run: what would be reopened, with probability and reason
tabularasa focus --open --limit 25 --threshold 0.75
tabularasa focus --open --group # one Safari window per topic cluster (singletons share one window)
tabularasa topic "knowledge graph" # archive + close everything, open tabs about a topic (90 days) in a new window
tabularasa topic "knowledge graph" --new # same, but keep the current windows open
tabularasa why "Knowledge Graph" # explain: candidate? linked? Jev score vs threshold, context lines that share words
tabularasa runs # recent archive runs: id, time, tabs, windows, closed?
tabularasa restore # pick a run, reopen all its tabs, one window per original window
tabularasa restore 25 --pick # a specific run, choose which tabs come back
tabularasa search playwright # find archived tabs by title or url
tabularasa forget dependabot # delete archived tabs matching a term
tabularasa pin "Team dashboard" # always reopen (own window when grouping); unpin to stop
tabularasa mute youtube # never reopen, cleanup leaves it alone; unmute to stop; `pins` lists both
tabularasa "drop closed github issues and PRs" # anything else: Claude Code runs the tab-focus skillIn a Claude Code session the installed tab-focus skill answers "close everything and open only
what's relevant today" or "open recent history items on topic X in a new window". There, Claude
first gathers Slack messages and recent artifacts into ~/.tab-archive/context.txt, which focus
picks up automatically.
How picking works
- Context: calendar events yesterday through tomorrow (
gws, declined and recurring-noise filtered), PRs and issues involving you from the last 7 days (gh), an optional--topic, and~/.tab-archive/context.txtif present. Open PRs awaiting your review are ingested into the archive so they compete as candidates. - Candidates: archive links seen in the last
--days(7) days, at most 400. - A tab whose URL appears in the context is
linked(1.0). Every other candidate is one yes/no question to Jev, "is this tab relevant to the state?", 40 per request. When a page was ingested (tabularasa ingest, orinstall --ingestfor 30 new pages every morning), its description and first 300 characters ride along in the question, which helps with generic titles. Keep those at or above--threshold(0.6), at most--limit(15). - Pairwise pass over the picks, two questions per pair: "same underlying content?" drops the lower-scored duplicate (threshold 0.4, measured against control pairs at or below 0.19), and "same piece of work?" orders the tabs as a nearest-neighbour chain so related tabs sit together.
--opencreates one new Safari window via AppleScript with the picks as tabs. With--groupthe chain is cut where neighbour similarity drops below 0.5 and each cluster gets its own window; clusters of one tab share a trailing window.tabularasa install --close --reopen --groupdoes this every morning.
About 12 seconds and 3 Jev requests for 130 candidates.
Archive
~/.tab-archive/tabs.db:
linksone row per URL:title,first_seen,last_seen,times_seen(runs it was open in)tabsone row per tab per run:window_id,window_index,tab_index,is_current,title,sourcerunsone row per run:ran_at,tabs_found,new_links,closed
sqlite3 -column ~/.tab-archive/tabs.db "SELECT last_seen, title, url FROM links ORDER BY last_seen DESC LIMIT 30;"Guarantees
- Safari is never launched to archive. If it isn't running, the run records zero tabs.
- Windows close only after the archive transaction committed. A failed write leaves everything open.
- Only http(s) URLs are stored. No secrets in files or logs; the Jev key stays in
~/.config/typesafe. - Only Jev (tab titles and URLs plus the context text), Google and GitHub are contacted.
Uninstall
tabularasa uninstall # LaunchAgent + skill; keeps ~/.tab-archive
npm unlink -g @mfittko/tabularasaTest
npm test