This is the full, honest list — if it's not below, this tool doesn't do it. It files and answers; it doesn't plan your day or make decisions for you. Each trigger is something you'd already type without thinking about which tool handles it — your assistant recognizes the shape of the message and quietly does the right thing with it.
One rule: start a message with "Dori" and it steps in. Links and files just work on their own.
Built for someone whose day is already full — the point isn't a new habit, it's zero new habits.
Someone shares a talk on the walk in. You paste the link and say "grab this" — by the time you're at your desk, it's a searchable transcript.
Out of a client call. Instead of writing notes, you say "turn this into minutes" — pasting the transcript, or letting a connected Fathom account supply it — and keep moving to the next thing.
Cab receipt lands in your gallery. You drop the photo in and say "add this to the trip" — no spreadsheet, no separate app.
Can't remember what you agreed to two weeks ago. You ask "Dori, what did we decide with the design team?" instead of scrolling through old docs.
You ask "Dori, give me a summary of the day" — nothing was filed by hand, it's all just where it should be because you talked, not because you organized.
"Dori, start a new project for me" (with the relevant files attached)
Creates projects/<name>/ with folders that fit what you gave it — docs/notes/references for general work, or invoices/meetings/deliverables for client work, and a few other presets. Additive only — it only ever creates folders, never moves, deletes, or overwrites anything already there.
$ apply-template.mjs acme-nonprofit engine.client { "created": ["invoices", "meetings", "deliverables", "docs"] }
"Grab this — youtube.com/watch?v=…"
Pulls captions and the uploader's own chapters via yt-dlp — chapter titles are used verbatim as headings, never invented. No video download unless you ask for one.
chapters: 6
00:00 Cold open
02:14 The core argument
09:40 Where it breaks down
upload_date: 20260812 | duration: 34:02 | channel: Acme Talks
It also builds a small local HTML page (serve-site.mjs) you can click
open and browse your captures in — stored on your machine, nothing uploaded anywhere.
"Here are the board minutes from Tuesday" (.docx attached)
Converts locally via markitdown into Markdown — plain text with light structure, the format an agent can read at the lowest token cost — then figures out where it belongs — an existing project if one matches, otherwise your inbox. It asks before filing anywhere new.
$ route-destination.mjs document acme-nonprofit { "relPath": "projects/acme-nonprofit/2026-08-24-ec-minutes.md" }
"Turn this into minutes" (pasted alongside a transcript — reacts on its own)
"Dori, pull my meeting with the design team from Fathom" (no transcript in hand — this needs the prefix)
Long transcripts get compressed by a cheap model first (facts, decisions, and action items kept verbatim), then extracted into Attendees · Topics · Decisions Log · Action Items. Fathom sync dedups automatically — never re-files the same call twice.
## Decisions Log - Ship the v2 pricing page before the Q3 review [owner: Priya] - Hold off on the annual-plan discount until Q4 [owner: Sam]
"Dori, start a trip for the Denver conference" (no attachment yet — needs the prefix)
"Here's the airport taxi receipt" (photo attached — reacts on its own)
Reads each bill, proposes a row (date · vendor · amount · tax), and appends it to a running ledger. Before you submit a claim, it checks for gaps — no date, no amount, no attachment — so nothing gets rejected downstream.
| Date | Description | Category | Amount | Tax | |------------|------------------------|-----------|---------|-------| | 2026-08-21 | Airport taxi | Transport | 1350.00 | 0.00 | | 2026-08-24 | Return airport taxi | Transport | 1936.78 | 80.88 |
$ check-reimbursement-gaps.mjs "Denver conference" { "gaps": [], "complete": true }
"Dori, what did we decide with the design team last time?"
"Dori, find anything about the annual-plan discount"
"Dori, tell me about Priya"
"Dori, what's the NDA status with Northwind?"
Exact-phrase recall hits a local full-text index instantly; a looser, paraphrased question falls back to local semantic search — embeddings run entirely on your machine, no API call. This is also how you get info about someone already in your vault — different from Person research below, which is for someone new.
last-meeting --person "design team"
→ 2026-08-19 · Decisions Log · Action Items (3 open)
"Dori, who's Priya Menon from Acme? — she just joined a meeting"
Searches the open web for the right person — always confirms before filing, since common names collide. Nothing gets written until you say yes. This is only for someone new — if they're already in your vault, that's recall (above), not research.
"Dori, anything waiting on me?"
"Dori, what do I need to resolve?"
The inbox exists because filing something wrong is worse than not filing it at all: when a capture could belong to more than one project — or none — it's held here as a pending decision instead of guessed at. These survive across sessions, so nothing quietly falls through, and nothing gets surprise-filed somewhere you didn't expect.
2 unfiled captures 1 pending clarification — "Denver notes.pdf" could match: acme-nonprofit, acme-events
"Dori, what are my pending tasks?"
Reads straight from the real task store, not something reconstructed from meeting notes — actual tracked to-dos, separate from the inbox above (which is about unfiled captures and ambiguous routing, not tasks).
$ list-tasks.mjs open - [t_412] Send the v2 pricing page draft to legal (due 2026-08-28)
You can also add one directly — "Dori, add a task: send the pricing draft by Friday" — or let it fill in on its own from a meeting's Action Items once minutes exist.
A real folder on your machine — Downloads, a scanner's save spot, wherever things already land
Point it at a folder during install (or any time after) and it notices new files once they've actually stopped changing — no half-downloaded PDF gets grabbed mid-write. Nothing files itself: ask "Dori, anything new in my inbox folder?" to see what's arrived and where it likely goes, same "never guess" discipline as everything else here. Moving a file around inside the folder is recognized as the same item, not a duplicate; a real delete waits two minutes before it's treated as gone, so a slow move never gets misread.
A link, a photo, a note — or a real question — to a dedicated WhatsApp number
Everything above needs you inside a chat with Claude or Codex. This is the exception — text a spare WhatsApp number (never your real one) and it files what you send exactly like a pasted link would, and can answer questions read-only from what's already in your vault, with nobody at the keyboard. Groups are rejected outright; a bare link never spends an AI call, only an actual question does.
What it needs, and why it's safe →
The design choice that matters most: most of what happens costs no model tokens at all.
Deciding which folder a capture belongs in is deterministic code — route-destination.mjs, not an LLM reasoning about it from scratch every time. The model only gets involved for the parts that actually need judgment.
A recall question hits a local full-text index before anything else — most searches never touch a model. Semantic search (for paraphrased questions) also runs its embeddings locally, no API round-trip.
A meeting transcript over ~1,500 tokens is compressed by a small, fast model first — filler and repetition cut, every decision and action item kept verbatim — before the larger model does the actual extraction. You pay the expensive model for judgment, not for reading filler.
query-vault.mjs returns metadata and named sections by default — not full document bodies — so asking "what did we decide" doesn't mean re-loading every meeting you've ever had.
This is the short version. The full technical breakdown → covers the SQLite/FTS5 index, the local embedding model, RRF re-ranking, and a traced example of a real capture end to end.
The install wires it into whichever of these you already use — no separate setup per tool, and no separate UI of its own.
It's plain, inspectable scripts, not a plugin tied to one product — any of these tools recognizes the same trigger phrases and does the same thing. Switch tools tomorrow and nothing here needs reconfiguring. There's no dashboard or website to check — you interact with it entirely inside whichever chat you already have open, and it uses that tool's own subscription. No new account, no added cost.
Your Markdown files are the source of truth. Search indexes and caches are disposable — delete them and they rebuild from the vault itself.
An ambiguous destination goes to your inbox, not a best guess. You confirm new people, new projects, and new trips before anything's filed.
Every capture type is a small Node script your agent already knows when to run — inspectable, editable, nothing hidden behind an API.
Stop using it tomorrow and every file it ever wrote is still a plain Markdown file on your disk — openable, searchable, portable, with or without this tool installed.
Runs on the Claude/Codex/etc. subscription you already have. There's no separate product bill to sign up for.