Local-first personal finance dashboard for bank exports.
Import CSV, PDF, or OFX files, review transactions, categorize them, and explore them in a local web UI.
Spectra is a self-hosted tool for people who want to manage personal finances without giving a third-party app direct access to their bank account.
You export your bank statement, import it into Spectra, review the transactions, and use the dashboard locally on your machine.
Main capabilities:
- Import bank exports in
CSV,PDF, andOFX - Normalize messy statement formats and deduplicate transactions
- Categorize transactions with
local,OpenAI, orGeminiproviders - Review and correct imports before saving them
- Explore budgets, trends, recurring payments, and transaction history in a local web app
- Optionally sync outputs to Google Sheets
Currency handling, historical database migrations, backups, and offline behavior are described in Data and currency safety.
| Dashboard | Transactions |
|---|---|
![]() |
![]() |
| Budget | Trends |
|---|---|
![]() |
![]() |
- Export a statement from your bank.
- Start Spectra locally.
- Open
http://localhost:8080. - On the first run, Spectra redirects you to Settings to complete the required setup.
- Upload a
CSV,PDF, orOFXfile. - Review merchants and categories before importing.
- Use the dashboard to inspect spending, budgets, trends, and recurring payments.
Spectra runs as four independent local services behind one web gateway. Docker Compose starts the full set together. The native launcher also starts all four processes and shuts them down together. Only the gateway has a host-published port; the internal APIs stay on the Compose network or loopback.
There are two ways to run Spectra:
Docker: best for most usersNative Python: better for development
Spectra binds to 127.0.0.1 by default and uses local categorization. Docker Compose also binds
to loopback by default. Set SPECTRA_HOST=0.0.0.0 only when you intend to expose the service on
your network; the web app has no authentication, so do not expose it to an untrusted network.
- Docker Desktop on macOS/Windows, or Docker Engine with Compose on Linux
- Docker daemon running
git clone https://github.com/francescogabrieli/Spectra.git
cd SpectramacOS/Linux:
./spectra start --buildWindows PowerShell:
.\spectra.ps1 start -BuildWindows CMD:
spectra.cmd start -BuildOpen http://localhost:8080.
After the first build, you can usually start it without rebuilding:
macOS/Linux:
./spectra startWindows PowerShell:
.\spectra.ps1 startWindows CMD:
spectra.cmd startmacOS/Linux:
./spectra stop
./spectra logs
./spectra statusWindows PowerShell:
.\spectra.ps1 stop
.\spectra.ps1 logs
.\spectra.ps1 statusWindows CMD:
spectra.cmd stop
spectra.cmd logs
spectra.cmd statusmacOS/Linux:
./spectra start --port 3000 --buildPowerShell:
.\spectra.ps1 start -Port 3000 -BuildCMD:
spectra.cmd start -Port 3000 -BuildThen open http://localhost:3000.
- Python
3.11+ uv
git clone https://github.com/francescogabrieli/Spectra.git
cd Spectrauv sync --lockedMinimal local setup:
AI_PROVIDER=localOptional provider setup:
# AI_PROVIDER=openai
# OPENAI_API_KEY=...
# AI_PROVIDER=gemini
# GEMINI_API_KEY=...Optional Google Sheets sync:
# SPREADSHEET_ID=...
# GOOGLE_SHEETS_CREDENTIALS_FILE=credentials.jsonuv run python -m spectra --serveOpen http://localhost:8080.
When Spectra starts for the first time:
- Save your Base Currency in Settings.
- Confirm the active categorization mode (
local,openai, orgemini). - Optionally configure Google Sheets sync.
- Continue to Upload and import your first statement.
- Review categories and merchants before saving.
Spectra blocks imports until the base currency has been saved once. Google Sheets remains optional.
Set AI_PROVIDER in .env:
local: fully offline, no API key requiredopenai: requiresOPENAI_API_KEYgemini: requiresGEMINI_API_KEY
The local mode combines:
- merchant memory stored in SQLite
- fuzzy matching for similar merchant names
- a local ML classifier trained from seed data and your corrections
Google Sheets is optional.
To enable it:
- Create a Google Cloud project
- Enable Google Sheets API and Google Drive API
- Create a service account
- Download the JSON credentials file
- Share your target spreadsheet with the service account email
- Set
SPREADSHEET_ID - For native runs, set
GOOGLE_SHEETS_CREDENTIALS_FILEorGOOGLE_SHEETS_CREDENTIALS_B64. In Docker Compose, useGOOGLE_SHEETS_CREDENTIALS_B64; credential files are excluded from the image build context.
The CLI uses the same importer review/enrichment and ledger commit APIs as the web UI. Keep Spectra running in another terminal before using import commands:
# Terminal 1: start gateway, importer, enrichment, and ledger together
uv run spectra --serve
# Terminal 2: preview without changing the financial ledger
uv run spectra --file export.csv --dry-run
# Commit locally through the ledger (optional Sheets sync follows)
uv run spectra --file export.csv
# Process a folder through the same services
uv run python -m spectra --inbox inbox/
uv run python -m spectra --inbox inbox/ --dry-runThe process entrypoints and API ownership are documented in the service architecture and the repository layout.
Runtime data is stored locally in folders such as:
data/inbox/processed/
By default the canonical ledger lives at data/spectra.db. Only the ledger process opens or
migrates it. Import review staging and exchange-rate cache each use a separate store; neither is
mounted into the ledger container. A legacy data/prism.db is migrated only when the ledger
starts. If both names exist, the ledger uses data/spectra.db and leaves prism.db untouched.
- Spectra does not connect directly to your bank account
- Import, normalization, storage, and review happen locally
- In
localmode, categorization is fully offline - In
openaiorgeminimode, transaction data needed for categorization is sent to the selected provider
Install the dev environment:
uv sync --lockedRun the app:
uv run python -m spectra --serveRun tests:
uv run pytestSee also:
Spectra is licensed under the GNU Affero General Public License v3.0.
If you modify Spectra and run it as a network service, you must make the source code available under the terms of the license.
For commercial licensing, contact francesco.gabrieli.fg@gmail.com.



