| name | superme-sources |
| description | Use when pulling state into superme from Mail, Calendar, Reminders, git repositories, WhatsApp or Slack — checking what is new, turning messages or events into threads and todos, or diagnosing a source that is unavailable or stale. |
superme-sources
Six sources feed superme. They differ enormously in reliability, and the design
assumes any of them can be down without stopping the day.
| Source | Route | Reliability |
|---|
| Mail | AppleScript, 5 accounts | good |
| Calendar | AppleScript, 13 calendars | good |
| Reminders | AppleScript, 4 lists | good |
| Repos | git + gh | excellent |
| WhatsApp | Chrome MCP only | fragile |
| Slack | Chrome MCP, or an app token | fragile / good |
Fetching a file superme cannot see
A record's file: outlives the file's location: things get renamed, moved into
a project folder, re-downloaded with a (1), or never saved out of Mail at all.
superme fetch goes and looks rather than reporting a count.
superme fetch
superme fetch "Contrato.pdf"
superme fetch "Contrato.pdf" --mail --into ~/Desktop/SUPERME/inbox
Channels, tried in this order, cheapest first:
| Channel | What it does | Cost |
|---|
local | Walks ~/Downloads, ~/Desktop, ~/Documents. Exact filename first, then a normalised one — so Invoice (1).pdf answers for Invoice.pdf | milliseconds |
chrome | Chrome's own download history: the file may simply have been moved | one SQLite read |
browser | Same history, file genuinely gone — returns the URL it came from | free; a human opens it |
mail | Saves the attachment out of Apple Mail | ~1s per message — opt-in via --mail |
Mail is opt-in for a reason: Mail's scripting interface walks messages one at a
time, and enumerating 25 of them took over two minutes on the machine this was
built against. fetch_from_mail is in smlib.NEVER_AUTO beside signing — it
reads correspondence, so it is asked for or it does not happen.
Nothing here moves or deletes an original; every channel ends in a copy. What
stays unresolved is written to .superme/fetch/needed.json — rows carrying a
URL are the browser's job, and that is the handoff point where you open the page
in Chrome rather than the CLI guessing.
superme vault runs the two fast channels automatically, so a record whose file
has merely moved is repointed instead of being reported as missing forever.
Permissions
Two are needed, both on the terminal; superme doctor verifies them:
- Automation — drives Mail, Calendar and Reminders, and opens a browser to
fill forms. Fix a failure at System Settings → Privacy & Security → Automation.
- Full Disk Access — required to read the on-disk stores and browser profile
data. Without it
~/Library/Mail, Contacts and the Chrome profile all return
Operation not permitted. Fix at System Settings → Privacy & Security → Full
Disk Access, then restart the terminal.
Prefer the AppleScript route over reading ~/Library/Mail by hand even with FDA
granted — it is version-stable and returns structured results. FDA is what makes
the fallback and the browser-profile reads possible, not the primary path.
A quit app is not an unavailable source
AppleScript answers -600 "Application isn't running" when the target app is
merely closed. superme used to report that as the source being down, so a scan
run on a morning when Calendar happened to be quit silently lost every calendar
deadline — the data was there the whole time.
smlib.osascript_app now starts the app and retries. Two details are load-bearing:
- The launch goes through
open -gj -a <App>, not AppleScript's launch
verb. Asking a quit app to launch itself answers -600 — the very error being
recovered from — so the obvious route does nothing at all. -g keeps it
behind whatever the user is doing, -j starts it hidden.
- Only -600 is retried. -1743 (Automation refused) is a permission the user
has to grant, and masking it behind a relaunch would hide the one thing they
need to act on.
So superme status showing a source DEGRADED now means something real. Read the
error code before assuming it is a permission.
Credentials. superme never reads a password from a file. It fills forms by
driving the real Chrome session through Chrome MCP, where Apple Passwords
autofill and existing logins already are — the browser supplies the secret,
superme never touches it. For its own service tokens, use the login keychain via
security add-generic-password / find-generic-password (verified read/write).
Apple Passwords / iCloud Keychain items stay unreadable from the CLI —
security list-keychains shows only login, openvpn, System. That is fine:
use them in the browser, do not try to extract them.
Writing emails: superme drafts, you click Send
The whole point of superme on email is that it does the writing. When a todo
needs an email sent, superme composes it and puts it in Mail's Drafts — the user
opens Mail, reads it, and clicks Send. superme never sends; smlib.NEVER_AUTO
blocks send_email at the gate, and the draft mechanism only ever calls
AppleScript save (to Drafts), never send.
Composition is your job; delivery is the CLI's. Write the actual email text
into the todo's draft_body (with the recipient's register and the thread
context in mind — see the voice model once it exists), plus email_to,
optionally email_cc and email_subject. Then:
superme draft <todo-id> --dry-run
superme draft <todo-id>
If a todo has no draft_body, superme draft emits a clearly-marked STUB and
warns — never let a stub reach a real recipient. Compose first.
Keep drafts short. The measured failure mode of the prior system is drafts
3.6× longer than the user writes himself (email/README.md). Terse and in his
voice beats complete and machine-sounding.
Match the learned voice. superme voice reads pre-2026 sent mail — the
genuine, pre-AI style — into .superme/voice.md and .superme/voice.json. It
learned that length is per recipient: in this corpus work mail ran ~186 words
and personal mail ~1449, so there is no single global target. When composing a
draft_body, match the recipient's own row: the median length for their domain,
their language, and the opening and sign-off the
model shows. superme draft prints the recipient's word budget and warns when a
draft blows past their ceiling — treat that warning as a hard stop and cut.
Re-run superme voice occasionally; it is slow (reads mail bodies) but rarely
needed.
The user's Mail Drafts already holds hundreds of drafts from the prior email
system — check for an existing draft on the same thread before adding another.
Browser tasks: open, fill, finish
This is the capability Full Disk Access and the browser channel exist for —
superme opening a browser, filling a form, and finishing a task, using
credentials it never sees.
The loop:
mcp__claude-in-chrome__tabs_context_mcp (once per session), then
tabs_create_mcp — a fresh tab, never a reused one.
navigate to the form. It runs in the user's real Chrome profile, so they are
already logged in and Apple Passwords autofill is available.
- Read the page (
read_page / get_page_text) before acting. Never fill from
memory of what the form "usually" looks like — selectors and fields drift.
- Fill non-credential fields with
form_input. For a username/password field,
trigger the browser's own autofill rather than typing a secret — the
credential comes from Apple Passwords, and superme never handles the value.
Handling a password in plain text, or typing one, is prohibited.
- Stop before the irreversible control. Submit, Confirm, Pay, Send, Accept
terms — these are the user's click, every time. Fill everything, screenshot the
completed form, and hand it to him to submit.
smlib.NEVER_AUTO covers
submit_form structurally.
FDA is what lets step 3's page reads and any profile-backed autofill work, and
what lets the follow-up (step: collect the resulting PDF/receipt from disk)
succeed instead of returning Operation not permitted. Confirm it with
superme doctor before starting a browser task that ends in a disk read.
Collecting from disk
With FDA granted, superme scan reaches the on-disk stores and browser profile
that are otherwise blocked. Without it the scan sees only the open filesystem and
superme doctor reports full disk access FAIL. A browser task that downloads a
document is only half-finished until the document is scanned in and registered as
a document entity — that second half needs FDA.
AppleScript gotchas
Calendar and Reminders return duplicated names across accounts — 18 calendar
entries for 13 real calendars. Dedupe before reporting a count.
Wrap every tell in a timeout. A stalled Exchange account will otherwise hang
the run; smlib.osascript returns (ok, out, err) and never raises, so a denied
permission degrades to a STATUS.md line instead of a crash.
WhatsApp
Read ~/Desktop/whatsapp/CLAUDE.md first, every time. It documents the
routes that do not work and why, and it was expensive to learn. Summary of what
it says: use mcp__claude-in-chrome__* and nothing else; activate the tab before
reading or the virtualised list renders zero rows; selectors drift, so try
several; rows come back duplicated, so dedupe by name; cross-check unread counts
against document.title.
Never send a WhatsApp or Slack message automatically. smlib.NEVER_AUTO blocks
it structurally — draft it and let the user send.
Repos
superme scan --quick
Two states worth raising unprompted:
- No commits at all. The live scan found a repo with 392 staged files and
zero commits on its only branch. There is no history to recover from.
- Not under version control. 21 directories under the repo root have no
.git at all — years of work with no way back to yesterday.
Staleness
Every source snapshot carries as_of. The cycle refuses to resolve items from
stale data rather than guessing. superme status shows which source is stale;
say so in one line before reporting anything derived from it.