A read-only command-line reader for Spark Desktop's local mail cache on macOS. Lists, reads, and searches the mail that Spark has already synced to your machine — without touching the Spark app, IMAP, or the network.
Read-only. Every database handle is opened with
readonly: true. This tool never writes to Spark's data.
Spark Desktop stores your mail unencrypted in a handful of SQLite databases
under ~/Library/Application Support/Spark Desktop/core-data/. When Spark is
already running and has synced your inbox, you don't need IMAP credentials or
OAuth to read that mail — you just need to query those databases. This CLI
does exactly that.
- macOS with Spark Desktop installed and signed in at least once (so the local cache exists).
- Node.js 20+ (developed against Node 24).
git clone https://github.com/Legoless/spark-cli.git
cd spark-cli
npm install
npm run build
# Optional: put `spark` on your PATH
npm linkspark list [-n <count>] [-u] [-a <accountPk>]
spark read <pk> [--html | --raw | -H]
spark search <query> [-n <count>]
spark accounts
spark list -n 10
# pk date from subject
# ● 6238 2026-04-19 12:55 App Store Connect <no_reply@ema… Version 1.0 (2) …
# 6230 2026-04-19 11:02 Google Search Console Team <sc-… Congrats on 90K …● marks unread. -u filters to unread only, -a <pk> filters by account
(see spark accounts for pks).
spark read 6238 # rendered plain text (HTML → text)
spark read 6238 --html # raw HTML body
spark read 6238 --raw # raw RFC822 source, if cached
spark read 6238 -H # headers onlySimple LIKE search across subject, sender, and the short-body preview:
spark search "iOS Dev Weekly"
spark search invoice -n 5spark accounts
# 1 Personal Dal
# 2 Work Dal RupnikSpark's local cache is a handful of SQLite files:
| File | Tables used | What's in it |
|---|---|---|
messages.sqlite |
messages, accounts |
Per-message metadata: from/to/subject/date/flags/shortBody |
cache.sqlite |
messageBodyHtml, messageImapData |
HTML body (plain BLOB) and raw RFC822 source |
Join key: messages.pk = messageBodyHtml.messagePk = messageImapData.messagePk.
No decryption, decompression, or reverse engineering — the BLOBs are plain
UTF-8. All queries go through better-sqlite3 with readonly: true, and the
CLI never calls writefile, PRAGMA writable_schema, or any statement that
could mutate state.
- Only the mail Spark has synced locally is readable. Messages beyond Spark's sync window still live on your IMAP server.
cache.sqliteis LRU — old bodies can be evicted even while metadata inmessages.sqliteremains. In that casespark read <pk>will say(no body cached locally).- Schema names come from Spark's own code and may change in future versions. If a Spark update breaks this tool, the fix is usually a one-liner.
- macOS-only. Spark stores data in the same shape on other platforms, but the default paths differ and aren't hardcoded here.
npm install
npm run build # tsc → dist/
node dist/index.js listSingle-file CLI in src/index.ts. Keep it that way.
MIT