Tally — Local-first finance
A local-first finance app that treats messy imports as something to review, not as the truth.
Bank CSVs, receipts, and pasted text never agree. Most finance apps import them as if they already do.
Tally treats import as a claim to check. It normalizes the input, fingerprints duplicates, and holds anything uncertain in a review queue before that data can change the picture.
The phone is the source of truth. Writes land in SQLite first. An outbox syncs a sanitized copy. The account stack is that model in your hand.
Scope
Imports, review queue, finance tools, on-device SQLite, sync outbox, and privacy boundaries. Active development, no public launch claims.
Local writes first
SQLite is the source of truth on the phone. A write lands locally, then an outbox pushes a sanitized copy. Remote changes come back by updatedAt.
- 1.Write to SQLite
- 2.Queue the outbox
- 3.Push a sanitized change
- 4.Resolve conflict
- 5.Pull by updatedAt
- 6.Apply locally
Interaction details
- Writes land in SQLite first, then enter an outbox before sync.
- Uncertain categories wait in a review queue.
- Raw receipt content and OAuth tokens stay out of sync payloads.
- Screens use fictional accounts and transactions.
Stack
React Native, Expo 54, Expo Router, TypeScript, SQLite, Zustand, Convex, Uniwind.
How it works
Input you can review
The hard part is not parsing a CSV. It is refusing to treat a messy import as already true.
- Text, CSV, PDF, optional Gmail receipts, and Apple Wallet shortcuts.
- Normalize, fingerprint, and drop duplicates across formats.
- Category rules, confidence gates, and a review queue.
- Accounts, budgets, subscriptions, debts, reminders, wishlist, tax, and insights.
What does not leave the phone
Raw receipt content and OAuth tokens stay out of sync payloads. Screens here use fictional accounts and transactions.
Current state
Tally is in active development. There is no public launch, and this page does not invent customer counts or savings.