Sats Stack
A local-first, Bitcoin-native personal finance app built with Flutter. No cloud. No accounts. No tracking.
Track your fiat spending and your Bitcoin stack in the same place — understand what you're spending, what you're saving, and how much you're losing to inflation.
Features
Transactions
- Manual transaction entry with categories and notes
- CSV import with automatic bank format detection and auto-categorisation
- Bitcoin wallet import from an xpub, ypub or zpub (BIP44/49/84, mainnet and testnet) — syncs via Mempool.space Esplora or your own server
- Bank statement import from CSV, PDF or a photo
- Edit and delete transactions
- Recurring transactions (weekly / monthly / yearly)
- Transaction search and filter (by keyword, category, source)
- Historical BTC price recorded per transaction at time of import
Dashboard
- Monthly income / spending / surplus overview
- Fiat "leak rate" and inflation cost metrics
- Spending breakdown by category (bar chart)
- Per-wallet breakdown (when multiple wallets are active)
- AI monthly insight — automatic with a private model, on request with a hosted one
- Month selector for historical browsing
Budgets
- Per-category monthly budgets with progress bars
- Sats opportunity cost display ("this category cost you X sats")
- Overspend notifications (≥ 80% warning, > 100% alert)
Bitcoin Stack
- All-time cumulative sats chart with time filters (3M / 6M / 1Y / All)
- DCA simulator — model future stack growth
- Stack goal with progress bar, projected completion date, and average sats/month
- Goal-reached notification
Analytics
- Spending pie chart by category
- 6-month income vs spending trend chart
- Year-to-date summary
- CSV export of monthly spending vs budget
Settings
- Dark / Light / System theme
- Currency: USD, GBP, EUR, CAD, AUD
- Custom Mempool/Esplora server (for privacy — routes all wallet sync and price data through your own node)
- AI provider — on device, your own server, or hosted (see below)
- SQLite database export and import
- Custom spending categories with colour and icon picker
- Data routing banner showing exactly which servers are contacted
Privacy
There is no Sats Stack account and no Sats Stack server. Your records are
stored on your device in a SQLite database via
Drift. The app does not encrypt that database
itself; it relies on your device's storage encryption (on by default on iOS and
Android, FileVault on a Mac).
What leaves the device, and when:
- Wallet sync and BTC prices go to mempool.space by default, with
CoinGecko as a price fallback. A wallet sync sends your wallet's
addresses. Point Settings → Servers at your own Mempool/Esplora server and
everything goes there instead; the routing banner in Settings shows which
servers are contacted.
- AI depends on the provider you choose — see below. A hosted provider is
sent your figures only when you ask: a question, an insight you tap for, or
a statement import you have agreed to. The import asks first, the preview
says when a file was sent, and Settings → Servers can withdraw the
permission.
AI Features
Pick one provider in Settings or during onboarding:
- On this device — Apple Intelligence or Gemini Nano, where the device
has one. Nothing leaves the device.
- Your own server — Ollama or LM Studio, on this
machine or your network. A server on the internet is shown as such.
- Hosted, needs your API key — Claude, ChatGPT, Gemini, Grok or Maple. Your
figures go to that company to answer.
Tech Stack
No state management library (Provider/Riverpod/Bloc) — services are plain Dart singletons initialized at startup, with ValueNotifier for reactive UI updates.
Getting Started
Prerequisites
- Flutter 3.47.2 (the version CI builds with)
- For macOS: Xcode
- For iOS and macOS: Xcode. Every plugin builds through Swift Package Manager, so CocoaPods is not needed
- For Android: JDK 21 (not 25 — see
.github/workflows/ci.yml)
Run
# macOS
flutter run -d macos
# iOS simulator
flutter run -d "iPhone 16e"
# List available devices
flutter devices
After changing the database schema
dart run build_runner build --delete-conflicting-outputs
iOS note
The minimum is iOS 15, set in the Xcode project — the lowest the current
Xcode supports.
A checkout from before CocoaPods was removed may still have ios/Pods or
macos/Pods folders; they are ignored and can be deleted.
Moving macOS data from before the bundle id change
On 2026-10-20 the macOS bundle id changed from the template's
com.satsstack.satsStack to app.satsstack.SatsStack, matching iOS. The app
is sandboxed, so a build with the new id opens a new, empty container: your
existing data is still there, under the old id, untouched. To bring it across:
- In a build from before the change, open Settings → Data → Export
database and save the file somewhere you can find.
- Open the new build. It starts at onboarding — skip through it.
- Settings → Data → Import database, choose the export, then quit and
reopen.
- Re-enter any hosted-AI API keys in Settings → Servers. They are kept in the
keychain against the app's identity, so they do not come across.
If you no longer have an old build, quit the app and copy the file by hand:
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗