A financial ledger that can power all kinds of apps.
kasas is a self-hosted, single-binary Go service that ingests your financial data through pluggable sources — SimpleFIN, Teller, Plaid, Bitcoin, Ethereum, CSV file import (local folders or Google Drive), and inbound webhooks today — into a local SQLite (or Postgres) database and turns it into a programmable substrate: a REST API, a built-in MCP server, a canonical event stream, outbound webhooks, and sandboxed plugins.
It is deliberately not another Mint, budgeting app, or financial planner. It's the ledger those apps are built on. kasas owns the boring, load-bearing parts — connecting to your accounts, deduping and refreshing transactions, a durable history of every change, an extensible metadata model — so anything you build on top (budgeting, tax, fraud detection, forecasting, notifications, AI agents) starts from clean, queryable, event-driven data.
The built-in dashboard — one of three surfaces (REST · MCP · dashboard) over the same core.
- Backbone, not app. Unopinionated about the application layer, so the application layer can be anything — yours and everyone else's.
- Source-agnostic by design. Data arrives through pluggable sources — SimpleFIN, Teller, Plaid, Bitcoin, Ethereum, CSV file import, and inbound webhooks today — that normalize a provider into one neutral shape; a generic ingestion engine owns the rest. New sources plug into the same contract.
- The data you add is sacred. A sync refreshes what the source owns and never touches your labels or extensions. Every change is a fact, recorded as a durable event and an immutable history snapshot in the same transaction as the change.
- Build through real seams. An event stream, webhooks, plugins, and MCP — extend it without forking it.
- Boring to run. One static binary, no CGO, an embedded database and an embedded dashboard, Prometheus metrics, structured logs, graceful shutdown.
| 🔌 Pluggable sources | A source SDK normalizes any provider into one neutral shape; a generic engine persists it. SimpleFIN, Teller, Plaid, Bitcoin, Ethereum, CSV file import (local folders or Google Drive), and inbound webhooks ship today. |
| 🔄 Automatic sync | Scheduled polling of the configured source; inserts new transactions, refreshes source-owned fields, preserves your labels. |
| ✍️ Manual entry | Create, edit, and delete accounts and transactions by hand — alongside synced data, or as a standalone ledger — from the dashboard, REST, or MCP. |
| 🗄️ SQLite or Postgres | Zero-dependency embedded SQLite by default, or Postgres with one config change. Same binary, no CGO. |
| 🏷️ Labels & extensions | Strict key:value labels, plus arbitrary namespaced JSON extensions any app can attach — no schema change. |
| 🔗 Relationships | Explicit directed edges between transactions — link a refund to its purchase, or one leg of a transfer to the other — queryable from both ends. |
| 🔎 Search | One query language over every field and label/extension combo, with AND/OR/NOT, ranges, and grouping. |
| ⚙️ Rules | if <query> then apply <labels + extensions> — auto-applied to new transactions, runnable over history. |
| 📜 Events & history | An append-only, replayable change log, an immutable full-snapshot history per transaction, and a derived provenance view of each one's origin and lineage. |
| 🪝 Webhooks & plugins | Push HMAC-signed events to your services, or run sandboxed plugins in-process — Lua, JavaScript/TypeScript, or Go compiled to WASM. |
| 🤖 REST + MCP + dashboard | Three surfaces over one core: code, an AI agent, or the built-in WebAssembly UI. |
| 🔐 Auth & API keys | A dashboard token plus scoped, hash-stored API keys across read / write / admin tiers. |
| 📈 Metrics & self-update | Prometheus at /metrics, plus checksum-verified in-place self-update. |
Prebuilt multi-arch images are published to GHCR on every release.
export KASAS_SIMPLEFIN_SETUP_TOKEN="<your base64 setup token>"
docker compose up -d --build # or swap in image: ghcr.io/paulmeier/kasas:latestcurl localhost:8080/api/v1/sync # latest sync status
curl localhost:8080/api/v1/accounts # synced accountsThen open the dashboard at http://localhost:8080.
Volume permissions: the container runs as UID
65532— the mounted data dir must be writable by it:mkdir -p data && sudo chown -R 65532:65532 data.By default kasas is unauthenticated for reads (dangerous admin ops always need a token, and it refuses to start exposed-and-tokenless — the image ships the opt-in so it boots). Set a dashboard token and keep it on a trusted network — see Authentication.
Full walkthrough: Quick Start →
The complete documentation — architecture, internals, sequence diagrams, and a reference for every feature and surface — lives at paulmeier.github.io/kasas.
- Philosophy — the platform thesis
- System Overview — how it all fits together
- Configuration · Deployment
- REST API · MCP · Event Stream
See CONTRIBUTING.md for local development, how to build and test each area (including adding an ingestion source and the gated Postgres integration test), regenerating sqlc code, and the Conventional-Commits / release-please flow. CI — gofmt, lint, race tests against SQLite and Postgres, and a build stage — must pass on every PR.

