A Atlas
{{ g.title }}
Nothing matches “{{ globalQuery }}”.
{{ dateText }}
{{ timeText }}
{{ initials }} {{ userName }}
{{ statusLabel }}
Please wait. Data loading…

Which account is each statement for?

Atlas reads the last four digits out of each file name. Check these before importing — a statement filed against the wrong account is hard to untangle afterwards.

{{ cu.name }} {{ cu.badge }}
Atlas couldn't match every file — confirm those yourself.

{{ bulkCatTitle }}

{{ bulkCatBlurb }}

{{ bulkCatTruncNote }}

{{ br.dateText }} {{ br.merchant }} {{ br.category }} {{ br.amountText }}

Add from a card or text

Photograph a business card, or paste an email signature. Atlas reads it and shows you what it found before anything is saved.

{{ captureError }}

What Atlas read
{{ cf.label }} {{ cf.value }}
Atlas›{{ crumb }}

{{ headline }}

{{ jarvisTag }}
{{ subhead }}

Today's briefing

Refreshed {{ refreshed }}
{{ b.tag }} {{ b.text }}

Inbox

This mailbox isn't authorised on the backend yet.
{{ m.initials }}
{{ m.from }} {{ m.when }}
{{ m.subject }}
{{ m.snippet }}

Holdings

{{ pnlText }}
₹{{ current }} invested ₹{{ invested }}
Zerodha expired today's session. Numbers below are the last snapshot.
{{ h.symbol }} ×{{ h.qty }} {{ h.pnlText }} {{ h.dayText }}
{{ contactCount }}
{{ syncResult }}
{{ g.letter }}
{{ contactsEmptyText }}
No match

Nobody selected

{{ contactsEmptyText }}

{{ selected.initials }}

{{ selected.name }}

{{ selected.role }}
{{ selected.source }} {{ selected.group }}

Demo record — Save won't persist until the backend is connected in Settings.

Contact details

{{ f.label }} {{ f.value }}
{{ mv.plural }}
—
{{ r.display }} {{ r.display }}
Addresses
—
{{ ad.label }} {{ ad.display }}
Tags
{{ tg.name }} No tags yet
Notes

{{ contactNotes }}

Nothing noted yet

{{ writeNote }}

Tasks
{{ tk.title }} {{ tk.due }}

Nothing to do for this person

Recent activity

{{ a.date }} {{ a.text }}
{{ dupeCountText }}
Queue clear — nothing left to review.
{{ dupe.initials }}

{{ dupe.name }}

{{ dupe.reason }}
{{ dupe.confidence }} match

Field comparison

{{ dupe.mergeNote }}

{{ dupe.labelA }} {{ dupe.labelB }}
This pair came back without field-level records — the deployed Worker predates the field comparison. Redeploy the Worker and refresh.
{{ r.label }}
{{ dupe.pickSummary }}
All clear

Nothing to review

Every pair has been merged or kept. Atlas re-checks for duplicates after each contacts sync.

Nothing here yet

Set up your money

Atlas starts empty on purpose — no sample accounts, no invented transactions. Three steps and this screen fills itself.

{{ st.mark }} {{ st.title }} {{ st.body }}
Period {{ periodRange }}
{{ s.label }}
{{ s.value }}
{{ s.delta }}

Insights

Computed against the same days of the last three months.

{{ i.text }}

Advisory

{{ advisoryAt }}

Generated once a day, never on the request path.

{{ a.title }}
{{ t }}

Upcoming known debits

Anything charged on a steady day and amount for three months or more is picked up automatically.

{{ u.name }} Detected {{ u.due }} ₹{{ u.amount }}

Expense by category

{{ c.name }} ₹{{ c.amount }}{{ c.share }}

Income vs expense

Last 12 months.

{{ m.label }}
Income Expense

Top merchants

Ranked by average spend over the last three months, same days each month.

MerchantThis periodPrev3-mo avgTrend
{{ m.name }} ₹{{ m.now }} ₹{{ m.prev }} ₹{{ m.avg }}
{{ dupeTxnSummary }}
{{ dp.amountText }} {{ dp.note }}
{{ dr.dateText }} {{ dr.merchant }} {{ dr.source }}
{{ txnSummary }} {{ txnNote }}
{{ txnPickedLabel }}
Category Type Account
{{ t.date }} {{ t.merchant }} {{ t.account }} {{ t.amount }}
No transactions match these filters.
{{ txnRange }} {{ txnPageLabel }}

Public profile watch

Atlas only checks when you press Check now — ten contacts at a time, reading only what a person has made public (LinkedIn, Instagram, X, a company site) and proposing a change where it disagrees with your record. Nothing is saved without your accept.

{{ scanLabel }}
{{ scanMeta }} {{ scanNext }}
{{ u.initials }} {{ u.name }} {{ u.foundOn }} {{ u.confidence }} match
{{ c.label }} {{ c.from }} → {{ c.to }}

{{ u.evidence }}

Open source
All clear

Nothing to review

Every suggestion has been accepted or dismissed. Press Check now to look at the public profiles again.

These four are examples, not your accounts. Add your real ones — alert emails are matched to an account by its last four digits, so imported spending lands in the wrong place until they exist.

Find accounts in your mail

Atlas reads the last year of alert and statement mail across every connected mailbox and lists the cards and accounts it recognises but you haven't added.

{{ discoverNote }}

{{ sg.name }} {{ sg.meta }}
{{ a.mark }} {{ a.name }} {{ a.meta }}

{{ accountFormTitle }}

The last four digits are how Atlas routes alert emails to this account. Get them right and imports land correctly.

Type
{{ accountNote }}

Transaction / statement ingestion

Atlas never scans on its own — press Scan now when you want it to read transaction alert emails from your banks and cards. Statement PDFs are added manually below.

{{ ingestMeta }}
{{ connectMailboxNote }} {{ ingestNote }}
{{ tokenWarning }}
{{ m.account }}
{{ m.detail }}

Account statements

Statements are never pulled from email — add the ones you want. CSV exports are read directly, and PDFs are extracted in your browser, so a password-protected one just asks for its password. A real .xlsx needs saving as CSV first. Rows already in the ledger are skipped, so overlapping months are safe.

+ Add a statement {{ statementNote }}
FileAccountFormatStatusImported atRows
{{ st.file }} {{ st.account }} {{ st.format }} {{ st.status }} {{ st.whenText }} {{ st.counts }}
Nothing added yet.

Categories

Type controls whether a category's transactions count as income, expense, transfer or investment on the dashboard. Recategorising leaves anything you set by hand alone.

{{ catNote }}

{{ g.title }}
locked

Categorization rules

Changing a system rule's category creates your own override at a higher priority — the original stays in the list, but yours wins.

PrioPatternMatchCategoryDirection
{{ r.priority }} {{ r.pattern }} {{ r.match }} {{ r.category }} {{ r.direction }}

{{ budgetMonth }}

CategoryBudgetSpentProjectedStatus
{{ b.name }} {{ b.budget }} {{ b.spent }} {{ b.projected }} {{ b.state }}

Matched pairs ({{ matchedCount }})

PaidAmountStatementPeriodTotal dueDiff
{{ m.date }} {{ m.paid }} {{ m.file }} {{ m.period }} {{ m.due }} {{ m.diff }}

Unmatched bill payments ({{ unmatchedPaymentsCount }})

No card statement within ₹1 of the payment, dated before it.

{{ u.date }} {{ u.amount }}

Unmatched card statements ({{ unmatchedStatementsCount }})

These have a total due, but no bill payment claimed them.

{{ u.file }} {{ u.amount }}

Statement total discrepancies ({{ flaggedCount }})

Opening balance plus parsed lines against the statement's own printed total, off by more than ₹1 — usually a missed or misparsed line item.

{{ d.file }} {{ d.detail }}

Not verifiable

Statements the parser couldn't read a total from — re-upload once the format is supported.

{{ u.file }} {{ u.reason }}

Atlas

The app itself — where it reads from, and how it looks on this device.

Sign-in

Status: {{ apiTag }} · last sync {{ lastSyncText }}.

Stored on this device only. Deploy steps are in DEPLOY.md.

Appearance

Remembered on this device.

Assistant

Jarvis mode arms the wake word and speaks replies aloud. Turn it off on shared machines.

{{ g.title }}

{{ g.blurb }}

{{ c.initials }}
{{ c.name }}
{{ c.detail }}
{{ toast }}