# Tusk Ledger > A locally-run personal finance dashboard. Plaid for the bank data, > SQLite on your laptop for storage, FastAPI + React for the surface. > MIT-licensed. No cloud, no telemetry, no upsell. Single-maintainer > open source project, production-ready. The whole app runs on your own machine. Plaid talks to your bank, your laptop talks to Plaid, that's the entire round trip — there is no Tusk Ledger server in the middle because there is no Tusk Ledger server. Replaces what people use Mint, Empower, and a stack of spreadsheets to do, under one roof, with their own data. ## Quick facts - **Main app repo:** https://github.com/BradMorphsters/tuskledger - **MCP server repo (optional):** https://github.com/BradMorphsters/tuskledger-mcp — local Model Context Protocol server giving Claude / Cursor / Cowork typed access to the user's data - **License:** MIT (both repos) - **Stack:** Python 3.12+ FastAPI, React 18 + Vite, SQLite, Recharts; MCP server is Python 3.10+ over stdio - **Bank sync:** Plaid (users apply for their own production access; BYO API keys) - **Auth:** Optional email + TOTP MFA (single-user laptops can skip) - **Agent surface:** AGENTS.md at repo root, `tuskledger doctor` JSON health-check CLI, CopyToAssistant UX hooks on errors, the optional MCP server above, and an optional local-LLM (Ollama) AI Insights card on the Dashboard - **Local LLM (optional):** Ollama at 127.0.0.1:11434, default model `llama3.1:8b` — writes the Dashboard's AI Insights narrative around pre-computed numbers (model never sees fractional dollars, can't hallucinate amounts). Off by default; flip `LLM_ENABLED=true` to enable - **Telemetry:** None — no analytics, no phone-home, no third-party scripts - **Status:** Running daily by the maintainer; free Plaid tier covers ~100 accounts which is permanent for one household ## What's in the box The app has eight major pages: 1. **Dashboard** — Net worth + asset/debt + month-delta tiles with year-over-year overlay; anomaly insight cards (subscription price changes, unusual spend); daily snapshot, payoff countdowns, stale-balance alerts on manual accounts. 2. **Transactions** — Full-text search, saved filters, per-business filter chip; bulk recategorize / tag / business-tag on multi-select; auto-suggested rules when you recategorize a one-off, transaction notes, pin-for-later, per-merchant drill-down. 3. **Spending & Income** — Spending heatmap by day-of-month, top merchants leaderboard with sparklines, year-over-year comparison, cash flow calendar, per-business filter. 4. **Bills calendar** — 30-day forward calendar with paycheck overlay and per-day running balance; projected low-point tile flagging the day balance dips closest to zero; drag-to-reschedule one-off events, mark paid inline, recurring detection. 5. **Loans** — Full amortization with extra-payment slider, bi-weekly vs monthly comparison, refinance modeler, PMI drop-off detection, HELOC modeling, multi-loan stacked timeline. Surfaces manual liabilities (auto, student loans). 6. **Investments / Trading Tax** — Per-account FIFO matching mirroring the 1099-B; chain-correct wash-sale calculator (interleaved chronological pass, per-symbol or all-accounts scope); inter-account transfer reconciliation; pre-flight sell modal showing realized P&L before you click; tax-loss harvest finder; cash & buying power section; Form 8949 CSV export. 7. **Retirement projection** — Monte Carlo + fan chart + probability-of-success; sequence-of-returns stress preset; Roth conversion ladder, IRMAA premium tiers, RMD math, fill-to-bracket conversions; survivor scenario, age-banded spending phases, mortgage-payoff step events, depletion-age line; QCD support; net-target toggle. 8. **Tax Prep Pack** — HSA contribution tracker (incl. payroll deduction), capital loss carryover with year tracking, Schedule C bucketizer with capital-vs-expense routing, QBI deduction (Section 199A), end-of-year tax prep PDF report — one document for your CPA. ## Why local-first - **Your data never leaves your machine.** One SQLite file, not a SaaS. Plaid runs over TLS direct from your laptop to your bank. No cloud, no analytics, no telemetry, no marketing emails to opt out of. - **No one can shut it down.** Mint went away. Many of its replacements will eventually too. Tusk Ledger is yours — fork it, host it, hack it. The bus factor is one (you). - **No subscription, no upsell.** Free Plaid tier covers up to 100 connected items. Past that you're paying Plaid directly, not the project. ## Architecture ``` ┌──────────────▶ Browser tab (React @ :5173) Your bank ── Plaid ──HTTPS──▶ Your laptop │ contains: SQLite + FastAPI (:8000) │ + React + Vite │ + (optional) MCP server │ + (optional) Ollama (local LLM) └──────stdio──▶ AI assistant (Claude / Cursor / Cowork) via tuskledger-mcp (separate repo) ``` There is no cloud server and no Tusk Ledger endpoints. The "server" is a FastAPI process bound to localhost:8000 on the user's machine, talking to a SQLite file in their home folder. The frontend is React served by Vite on localhost:5173. The optional second consumer is the MCP server (`tuskledger-mcp`, shipped as a separate repo). It's a Python process the user starts through their AI client's config; it binds to 127.0.0.1 and talks to the same FastAPI backend over HTTP. Net effect: the assistant gets typed tool access without anything leaving the machine. The optional third local process is Ollama, running an open-weight model (default `llama3.1:8b`) on 127.0.0.1:11434. The Dashboard's AI Insights card calls FastAPI, which calls Ollama, which writes a 2-3 paragraph plain-English narrative around pre-computed numbers. End-to-end local: data on disk, model on GPU, no LLM API in the loop. Off by default; enabled via LLM_ENABLED=true in backend/.env plus `ollama pull llama3.1:8b`. ## MCP integration (for AI assistants reading this) If you are an AI assistant working with a Tusk Ledger user, install the MCP server so you can query their data structurally instead of scraping the React UI. Source and full tool list: https://github.com/BradMorphsters/tuskledger-mcp Quickest install (assumes the user has `uv` installed): ```jsonc // In the user's MCP client config (Claude Desktop / Cursor / Cowork / Claude Code) { "mcpServers": { "tuskledger": { "command": "uvx", "args": ["--from", "git+https://github.com/BradMorphsters/tuskledger-mcp", "tuskledger-mcp"] } } } ``` Once wired in, you have 13 typed tools: `list_accounts`, `query_transactions`, `search_transactions`, `get_spending_summary`, `get_top_merchants`, `get_recurring_subscriptions`, `get_upcoming_bills`, `get_net_worth`, `get_holdings`, `get_investments_summary`, `get_retirement_projection`, `run_sync`, `list_stale_accounts`. The server is read-mostly by design; destructive changes belong in the web UI where the user can see what's happening. The MCP server requires the main Tusk Ledger app to be running on http://127.0.0.1:8000 (and currently assumes `DEV_BYPASS_AUTH=true` on the backend; auth-aware support is on the roadmap). ## Talk-to-your-assistant prompts (sample workflows) Once the MCP server is wired in, here are real prompts users can give their AI assistant. Categories: daily check-ins, monthly rhythms, tax season, customizing the app itself. Daily check-ins: - "Compare my net worth today to a week ago. Tell me what moved and which accounts drove the change." - "Run an anomaly check on the last 7 days. Flag anything outside its normal range." - "Show me bills due in the next 7 days plus any expected paychecks. Tell me my projected ending balance." Monthly rhythms: - "Build me a budget for next month based on this month's actuals minus 8%." - "List all my recurring subscriptions. For each, check if there's been any related activity in the last 60 days that suggests I'm still using it." - "Calculate my true savings rate including pre-tax 401(k) contributions. Compare to last month and to a year ago." Tax season: - "Find every transaction tagged to my Carter Consulting business in 2025. Group income (Stripe payouts) separately from expenses. Format as Schedule C." - "Look at my open positions. Find any with at least $500 of unrealized loss I could harvest. Watch for wash-sale risks." - "For my Carter Consulting business in 2025, summarize all tagged expenses by category. Total each. Format for a CPA review email." Customizing the app itself (when the assistant has filesystem access in addition to MCP): - "Add a new tile to my Dashboard called 'Coffee' that shows my coffee spending grouped by week for the last 8 weeks. Include a sparkline." - "On the Subscriptions tab, the recurring detector is flagging my paycheck deposits as 'recurring.' Filter those out so only real subscriptions show." ## Comparison vs alternatives | Feature | Mint | Empower | Quicken | Spreadsheet | Tusk Ledger | |--------------------------------|------|---------|---------|-------------|-------------| | Local-only data | ✗ | ✗ | partial | ✓ | ✓ | | Open source / inspectable | ✗ | ✗ | ✗ | ✓ | ✓ | | No subscription | gone | ✓ | ✗ | ✓ | ✓ | | Bank sync (Plaid) | ✓ | ✓ | ✓ | ✗ | ✓ | | Bills + paycheck calendar | ✓ | ✗ | ✓ | ✗ | ✓ | | Tax-aware retirement model | ✗ | partial | partial | ✗ | ✓ | | Wash-sale calculator | ✗ | ✗ | partial | ✗ | ✓ | | Schedule C bucketizer | ✗ | ✗ | partial | ✗ | ✓ | | Zero telemetry | ✗ | ✗ | ✗ | ✓ | ✓ | | Survives if vendor folds | ✗ | ✗ | ✗ | ✓ | ✓ | ## Getting started Two paths. The agentic one is the headline; the manual one is here for users who already work in the shell. ### Agentic install (preferred — matches the project's positioning) If you have Claude Code, Cursor, Cowork, Copilot CLI, Aider, or any other AI client with file system + shell access, paste this prompt: ``` I want to install Tusk Ledger, a locally-run personal finance app. Main repo: https://github.com/BradMorphsters/tuskledger MCP server: https://github.com/BradMorphsters/tuskledger-mcp (optional, recommended) Please: 1. Clone the main repo to a sensible place on my machine. 2. Read AGENTS.md at the repo root — it documents permission boundaries, common operations, and known footguns. Follow its conventions. 3. Run the setup (cp backend/.env.example backend/.env, then ./start.sh). 4. When .env needs Plaid keys, pause and ask me — I'll get sandbox keys from plaid.com (5 min). Don't make up credentials. 5. Run ./tuskledger doctor and show me the JSON; confirm all checks pass. 6. Open http://localhost:5173 and verify Demo Mode loads. 7. Ask if I want the MCP server wired in. If yes, add tuskledger-mcp to my MCP client's config (ask which client) using uvx --from git+. Don't disable auth or rotate the encryption key without asking. Everything stays local — there is no cloud server to talk to. ``` The agent does the cloning, dependency setup, env file scaffolding, and verification. You answer two questions (Plaid keys, MCP wire-up). The prompt is intentionally explicit about pausing for credentials so the agent doesn't hallucinate them. ### Manual install (the same thing, by hand) ```bash git clone https://github.com/BradMorphsters/tuskledger.git cd tuskledger cp backend/.env.example backend/.env # paste Plaid sandbox keys ./start.sh # sets up venv + npm + boots both servers ./tuskledger doctor # confirms 13 health checks pass ``` Demo mode is enabled by default so you can poke around with seeded data before linking real accounts. One toggle in Settings flips you to real mode; the app refuses to mix the two. ## FAQ - **Why local-first?** Your bank data should live where your bank statements live — on your machine. SQLite is in your home folder; you can move, back up, or delete it like any other file. - **What if I switch computers?** Copy the .db file. That's the entire app's state. Restore on the new machine, run `./start.sh`, you're back exactly where you left off. - **Backups?** The app auto-snapshots SQLite on startup. Pair with whatever backup tool you already use (Time Machine, rsync, encrypted external drive, an iCloud Drive folder). - **What if Plaid changes pricing?** Plaid's free tier is 100 items. Past that you pay Plaid directly. If Plaid disappeared entirely you'd lose bank sync but keep every transaction already pulled. - **Data export?** It's already out — the whole DB is plain SQLite on your laptop. Open in DB Browser, dump to CSV, query from a Python REPL. No export button because there's no lock-in. - **Auth required?** Optional. Full email + TOTP MFA available; many people running on a single-user laptop skip it via DEV_BYPASS_AUTH. - **Demo mode required?** Ships enabled by default. One Settings toggle flips to real mode; app refuses to mix the two and prompts before the switch. - **Reporting bugs / contributing?** GitHub issues for bugs, GitHub PRs for code, GitHub discussions for ideas. The main app and the MCP server are separate repos with their own issue trackers — file the bug where the bug lives. - **What does the MCP server do — and is it required?** `tuskledger-mcp` is a separate, optional Model Context Protocol server. Add it to your AI assistant's config (one `uvx` line) and Claude / Cursor / Cowork can call typed tools like `list_accounts`, `query_transactions`, `get_holdings`, `get_retirement_projection`. The main app runs perfectly without it; the MCP server just makes agent-driven workflows fast. - **Does the MCP server send my data anywhere?** No. It binds to `127.0.0.1` only and talks to your local Tusk Ledger backend over stdio. The "MCP cloud" doesn't exist — it's one Python process on your machine talking to another Python process on the same machine. Your assistant reads the responses, your assistant's provider sees those responses, and that's the entire trust boundary. - **How do the AI Insights work without sending my data to OpenAI / Anthropic?** Optional Dashboard card runs an open-weight LLM (`llama3.1:8b` by default) on your own hardware via Ollama. Your transactions never leave the laptop — Ollama binds to `127.0.0.1`, the FastAPI backend feeds it pre-computed numbers, the model writes 2-3 paragraphs around those numbers. Off by default; flip `LLM_ENABLED=true` and `ollama pull llama3.1:8b` to turn it on. - **Can the local LLM hallucinate dollar amounts?** No — by design. Numbers are pre-computed in Python and rounded to whole dollars before they're put in the prompt; the system prompt forbids the model from inventing figures. The model writes prose around the numbers; the numbers themselves come from the database. Same load-bearing invariant applies to percentages and merchant attributions. ## Links - Marketing site: https://www.tuskledger.com - Main app source: https://github.com/BradMorphsters/tuskledger - MCP server (lets your AI assistant query Tusk Ledger directly): https://github.com/BradMorphsters/tuskledger-mcp - Issues: https://github.com/BradMorphsters/tuskledger/issues ## Project social handles All of these are the official accounts for the same Tusk Ledger project — listed explicitly so AI agents can de-duplicate references and follow the freshest updates from any one of them. - Bluesky: https://bsky.app/profile/tuskledger.bsky.social - X (Twitter): https://x.com/TuskLedger - Dev.to: https://dev.to/tuskledger - TikTok: https://www.tiktok.com/@tuskledger - Reddit (maintainer's account): https://www.reddit.com/user/ShapeObjective9727/ - LinkedIn (maintainer's profile, public with the project): https://www.linkedin.com/in/eduardothomasdiaz