Warning
Personal, local-only tool. Scraping financial institutions may violate their Terms of Service. Use only for your own accounts on your own machine. Do not deploy as a hosted service.
Israeli banks have terrible exports, YNAB doesn't speak ILS gracefully, and every "cloud finance" app wants you to hand over your bank password. Spent is the answer for people who'd rather just run something on their own laptop.
Your transactions get pulled directly from your bank with israeli-bank-scrapers, stored in a local SQLite file you can cp and back up like any other file, and categorized by an AI provider you choose: paid Claude, free local Ollama, or nothing at all.
The trade-off is honest: you self-host, you trust the scraper, and you accept that banks may not love automation. In return you get a fast, beautiful, fully offline dashboard that never phones home.
|
Isracard, Bank Hapoalim, and Max work out of the box. Visa Cal and Bank Leumi are on the roadmap. |
Choose Claude (Anthropic) for best accuracy, Ollama for fully local LLMs, or skip and categorize manually. |
Credentials encrypted with AES-256-GCM. Server binds to |
|
Hierarchical categories, monthly targets, "ahead of pace" hero card, and per-category drilldown. |
Polished buttercream-and-sage palette in light mode, warm charcoal in dark. System-aware by default. |
Native companion in your menu bar (macOS) or notification area (Windows). Status indicator, one-click open dashboard, sync, and start/stop/restart the service. |
|
Credit card payments and inter-account moves are recognized and excluded from spending totals. |
Pull up to 3 months of transactions per sync (configurable). Most banks support 12 months total. |
Once you correct an AI categorization, Spent remembers β same merchant goes to the right category next time. |
| Dashboard β light | Dashboard β dark |
![]() |
![]() |
| Transactions | Setup wizard |
![]() |
![]() |
| Categories | AI provider |
![]() |
![]() |
| Bank accounts | |
![]() |
|
flowchart LR
Bank["π¦ Israeli bank<br/>(Isracard / Hapoalim / Max)"]
Scraper["Puppeteer scraper<br/>(israeli-bank-scrapers)"]
DB[("π¦ SQLite<br/>data/spent.db<br/>(WAL mode)")]
AI{"π€ AI provider<br/>Claude Β· Ollama Β· None"}
UI["π₯ Dashboard<br/>http://spent.local:41234"]
Bank -->|HTTPS<br/>credentials encrypted| Scraper
Scraper -->|new transactions| DB
DB -->|uncategorized batch| AI
AI -->|category proposals| DB
DB --> UI
subgraph local["π Your machine β 127.0.0.1 only"]
Scraper
DB
UI
end
Everything inside the dashed box stays on your laptop. The only outbound traffic is to your bank (for scraping) and optionally api.anthropic.com (if you chose Claude) or localhost:11434 (if you chose Ollama).
| Bank | Type | Status |
|---|---|---|
| Isracard | Credit card | β Supported |
| Bank Hapoalim (incl. Poalim wallets) | Bank | β Supported |
| Max (formerly Leumi Card) | Credit card | β Supported |
| Visa Cal | Credit card | π§ Planned |
| Bank Leumi | Bank | π§ Planned |
Don't see your bank? Adding a scraper is a small wrapper around israeli-bank-scrapers β see Contributing.
| Claude (Anthropic) | Ollama (local) | None | |
|---|---|---|---|
| Cost | ~βͺ0.004 per sync | Free | Free |
| Accuracy | Best | Good (depends on model) | Manual |
| Network | api.anthropic.com |
localhost:11434 |
Offline |
| Setup | API key | Install Ollama + pull a model | Nothing |
Default model when Claude is selected: claude-haiku-4-5 (cheap, fast, accurate for categorization). For Ollama, llama3.2:3b is the recommended default.
You can change providers any time from Settings β AI provider. Existing categorizations are kept.
- Node.js 22+
- macOS 13+, Ubuntu 22+ (with systemd), or Windows 11
- Build tools for the menubar (only if you want the tray;
npm run setupwill offer to install these for you if they're missing):- macOS: Xcode Command Line Tools (
xcode-select --install) - Windows: .NET 8 SDK (
winget install Microsoft.DotNet.SDK.8)
- macOS: Xcode Command Line Tools (
- A bank account with 2FA disabled (most Israeli banks require this for automation β OneZero is the exception)
Prefer a screenshot-by-screenshot walkthrough? The step-by-step install guides on the docs site cover macOS and Windows separately, with build-tool setup and tray-app gotchas spelled out.
git clone https://github.com/Shaya16/Spent.git
cd spent
npm install
npm run setupnpm run setup does everything: builds the Next.js app, installs the always-on service (LaunchAgent on macOS / systemd on Linux / Task Scheduler on Windows), adds 127.0.0.1 spent.local to your hosts file, builds the platform menubar from source, installs it to the standard location, registers it to auto-start at login, and opens the dashboard. The hosts edit is the only step that asks for sudo / Administrator.
On Linux there is no native menubar. npm run setup installs the service and opens the browser. Control the service with npm run service:* (see below).
First launch of the menubar on macOS/Windows shows an unsigned-binary warning (Gatekeeper / SmartScreen). That's expected: you built it locally and didn't pay for a code-signing certificate. Right-click β Open (macOS) or "More info" β "Run anyway" (Windows). One-time.
Open http://spent.local:41234 and bookmark it.
In the browser:
- Connect your bank β credentials are AES-256-GCM encrypted before they touch disk.
- Choose an AI provider β Claude (default), Ollama, or none.
- Set your monthly ceiling β total spend you want to stay under each month.
- Set per-category budgets β type an amount on any category to budget it; leave blank to track without a limit.
- Done. Sync starts automatically: 3 months of transactions, then AI categorization.
| What you want | Run |
|---|---|
| Just use the app (no coding) | Open http://spent.local:41234 |
| Code and see changes instantly | npm run dev β http://127.0.0.1:3000 |
| Update the always-on app after editing | npm run service:reload |
Rare cases:
- Changed the menu bar app source β
npm run menubar:install:mac(or:windows) to rebuild and reinstall. - Changed install scripts or hostname β
npm run service:uninstall && npm run service:install.
| Command | What it does |
|---|---|
npm run service:status |
Running? Bound to loopback? |
npm run service:start / :stop |
Start/stop now |
npm run service:reload |
Rebuild and restart |
npm run service:logs |
Tail server logs |
npm run service:open |
Open the app in your browser |
npm run service:uninstall |
Remove auto-start and hosts entry. data/ is untouched. |
npm run uninstallReverses everything npm run setup installed:
- Stops the background service and removes the LaunchAgent / Task Scheduler entry / systemd unit.
- Removes the
127.0.0.1 spent.localline from your hosts file (asks forsudo/ Administrator). - Quits the menubar, removes the installed app, and removes it from Login Items / Startup.
Kept on purpose:
data/: your transactions, budgets, and encryption key. To wipe your data:rm -rf data/.- The repo itself. To remove Spent entirely:
rm -rf data/ && cd .. && rm -rf spent/.
If you only want to remove the menubar but keep the always-on web app:
- macOS:
rm -rf ~/Applications/Spent.appand remove "Spent" from System Settings β General β Login Items. - Windows: delete
%LOCALAPPDATA%\Programs\Spent\and removeSpent.lnkfromshell:startup.
If you only want to remove the always-on service but keep the menubar (so it's there if you reinstall later): npm run service:uninstall.
| Concern | Defense |
|---|---|
| Credentials at rest | AES-256-GCM, encryption key file mode 0600 (server refuses to start otherwise) |
| Network exposure | Bound to 127.0.0.1 only β not reachable from your LAN or the internet |
| Browser CSRF | Origin / Referer validation on every mutation |
| Bot detection | Chromium sandbox on by default (SPENT_DISABLE_CHROMIUM_SANDBOX=1 to opt out) |
| Bundle integrity | israeli-bank-scrapers, better-sqlite3, and @anthropic-ai/sdk pinned to exact versions |
| Browser hardening | Strict CSP, X-Frame-Options: DENY, Permissions-Policy locks down camera/mic/geo/payment |
Turn on full-disk encryption (FileVault / BitLocker / LUKS). The encryption key file sits next to the database, so disk-level protection is your last line of defense if the laptop is lost.
Full threat model and responsible-disclosure policy β SECURITY.md.
data/spent.dbβ transactions, categories, budgets, settingsdata/.encryption-keyβ 32-byte AES key, mode0600~/Library/Logs/Spent/(macOS) /~/.local/state/spent/log/(Linux) β service logs
Back up data/ like any other folder. To migrate to a new machine, copy data/ over and run npm run service:install.
spent/
βββ src/
β βββ app/ Next.js App Router (routes + API)
β β βββ (dashboard)/ Dashboard, transactions, settings pages
β β βββ api/ Sync (SSE), summary, transactions, setup
β β βββ setup/ First-run wizard
β βββ components/
β β βββ dashboard/ Hero card, category grid, budget drawer
β β βββ setup/ Bank, AI, target, budgets steps
β β βββ settings/ Per-tab settings panels
β βββ lib/ Shared client-side types and helpers
β βββ server/
β βββ ai/ Claude + Ollama provider implementations
β βββ db/ SQLite singleton, migrations, query helpers
β βββ lib/ Encryption, dedup, transfer detection, pace
β βββ scrapers/ Wrapper around israeli-bank-scrapers
βββ menubar/ Tray companions (built locally by `npm run setup`)
β βββ mac/ Swift MenuBarExtra app
β βββ windows/ C# WinForms NotifyIcon app
βββ scripts/service/ LaunchAgent / systemd / Task Scheduler installer
βββ website/ Astro + Starlight docs site (auto-deploys to GitHub Pages)
βββ .github/workflows/ CI β docs site deploy
βββ Spent.sln Visual Studio solution for the Windows menubar project
βββ data/ SQLite + encryption key (gitignored)
The Troubleshooting docs cover Defender, Gatekeeper, Cloudflare bot challenges, and bank-specific quirks in more depth.
- Port 41234 in use β
lsof -nP -iTCP:41234 -sTCP:LISTEN(Unix) ornetstat -ano | findstr :41234(Windows). Kill the offender and re-run install. - Gatekeeper blocks
Spent.appβ right-click β Open β Open. One-time. - Linux: "systemd user instance not available" β
loginctl enable-linger $USER. - Windows: hosts edit fails /
spent.localdoesn't resolve β re-run install from an elevated PowerShell (Win+X β "Terminal (Admin)") so it can editC:\Windows\System32\drivers\etc\hosts. After the edit, the installer flushes the DNS cache automatically; if you edited hosts manually, runipconfig /flushdns.http://127.0.0.1:41234always works as a fallback. - Bank scrape fails with "Cloudflare" β temporarily run with
SPENT_DISABLE_CHROMIUM_SANDBOX=1to let Puppeteer use a real Chrome profile.
- Visa Cal scraper
- Bank Leumi scraper
- CSV / OFX export
- Custom user-defined categories
- Hebrew UI
- Mobile companion (Phase 2)
- Multiple workspaces in the menu bar / tray app
Spent is built for personal use first, open-source second. PRs welcome for:
- New bank integrations β add to
BANK_PROVIDERSin src/lib/types.ts, map toCompanyTypesin src/server/scrapers/index.ts, flipenabled: true. - New AI providers β implement the
AIProviderinterface from src/server/ai/types.ts, register in src/server/ai/factory.ts, and add an option to the setup wizard. - UI polish, bug fixes, documentation.
Conventions:
- TypeScript strict mode. No
anywithout a comment. - Conventional commits:
feat:,fix:,chore:,docs:,refactor:. - Comments only where the "why" isn't obvious. No em dashes in code, commits, or docs.
MIT
Built on the shoulders of:
israeli-bank-scrapersβ the heart of every bank integration- Next.js 16 and React 19
shadcn/uion top ofbase-uibetter-sqlite3- Anthropic Claude and the local-LLM crew at Ollama






