Personal budgeting system built on Actual Budget (self-hosted) with CSV/OFX import via CLI.
- Actual Budget runs in Docker (port 5006), stores data in
./data/(SQLite) - Import scripts are Node.js, using
@actual-app/api(official API) - Parsers in
src/parsers/— one per bank, each exportsdetect()andparse() - CLI at
src/cli.js— main entry point for importing transactions
| Bank | Import Method | Tool |
|---|---|---|
| TD Canada Trust | OFX file | CLI: node src/cli.js import --account td_chequing |
| CIBC | OFX file | CLI: node src/cli.js import --account cibc_chequing |
| Amex Canada | OFX file | CLI: node src/cli.js import --account amex |
| EQ Bank | CSV file | CLI: node src/cli.js import |
| Wealthsimple | CSV file (two formats: chequing + credit card) | CLI: node src/cli.js import |
| Wealthsimple | Holdings report CSV | CLI: node src/cli.js holdings |
./start.sh # Start Actual Budget (pinned to v26.4.0)
node src/cli.js import ./imports/ # Import all CSVs + OFX files
node src/cli.js import --dry-run ./imports/ # Parse without importing
node src/cli.js import --account ws_chequing file.csv # Explicit account (CSV)
node src/cli.js import --account td_chequing file.ofx # Explicit account (OFX)
node src/cli.js balances # Show balances
node src/cli.js holdings ./imports/holdings-report-*.csv # Update investment balances
node src/cli.js holdings --dry-run ./imports/holdings-*.csv # Preview without updatingTo track Wealthsimple investment account balances (RRSP, TFSA):
- Create two tracking accounts in Actual Budget (Settings → Add Account → Off-budget)
- Name them e.g. "WS RRSP" and "WS TFSA"
- Get each account's UUID from Actual Budget (Settings → Advanced → Show IDs, then click the account)
- Add them to
config/accounts.yml:accounts: ws_rrsp: "the-rrsp-account-uuid" ws_tfsa: "the-tfsa-account-uuid"
- Download the holdings report CSV from Wealthsimple (Accounts → Download → Holdings report)
- Run:
node src/cli.js holdings ./imports/holdings-report-2026-04-10.csv
Repeat monthly to track net worth over time. Fetches live USD/CAD rate from Bank of Canada for currency conversion.
- Amounts are integers in cents (Actual Budget format). Negative = outflow.
imported_iduses SHA-256 hash for CSV deduplication, or bank FITID for OFX. Safe to re-import same file.- Config lives in
config/accounts.yml(gitignored — contains server password and account UUIDs). - See
config/accounts.example.ymlfor the template. @actual-app/apiversion must match the Actual Budget server version (both v26.x).- Parser extensibility: add a new file in
src/parsers/, exportdetect(content, filename)andparse(content, filename), register insrc/parsers/index.js.
Server and API versions must match. To upgrade:
- Check latest version at https://actualbudget.org/docs/releases/
- Update
VERSIONinstart.sh - Update
imagetag indocker-compose.yml - Run
npm install @actual-app/api@<same-version> - Restart:
./start.sh
If you see out-of-sync-migrations errors, the versions are mismatched.
- Phase 1 (current): All imports via CLI — OFX (TD/CIBC/Amex) + CSV (EQ Bank/Wealthsimple)
- Phase 2: Splitwise API integration (shared expense reconciliation)
- Phase 2: Triangle Bank, Simplii parsers (when samples available)
- Phase 3: Mobile access via Tailscale + PWA