# Project pack: Wealthfolio @ 1e08bbc

Facts about **Wealthfolio** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Wealthfolio shows what all your savings, pensions and investments are worth, in one place. Add your accounts, type in or import your trades from a CSV file, and it works out your net worth, returns, dividends and progress towards goals such as a house deposit or retirement. It can also track spending. Your figures stay on your own computer or server, not with a finance company.

## Version and source
- Repository: https://github.com/afadil/wealthfolio
- Pinned commit: `1e08bbc1e2ae88cb245130d315df4283b1fe256d`. Use exactly this version.
- Get it: `git clone https://github.com/afadil/wealthfolio wealthfolio && cd wealthfolio && git checkout 1e08bbc1e2ae88cb245130d315df4283b1fe256d`
- Or download a zip: https://github.com/afadil/wealthfolio/archive/1e08bbc1e2ae88cb245130d315df4283b1fe256d.zip
- Official docs: https://wealthfolio.app/docs/guide/self-hosting/docker
- Licence: **AGPL-3.0-only**. Free to use and change. If you run a changed version that other people use over the internet (not just you or your household), you must offer them your source code under the same licence. Private use has no extra obligations. The name and logo are trademarks of Teymz Inc. and are not covered by the licence, so a public copy should use its own name. The add-on SDK is MIT.

## Running it
- Easiest:

  ```sh
  # Easiest: download the desktop app for Mac, Windows or Linux from https://wealthfolio.app/download
  # Or run the web version in Docker, on this computer only:
  echo "WF_SECRET_KEY=$(openssl rand -base64 32)" > wealthfolio.env
  docker run -d --name wealthfolio --env-file wealthfolio.env -e WF_LISTEN_ADDR=0.0.0.0:8088 -e WF_DB_PATH=/data/wealthfolio.db -e WF_AUTH_REQUIRED=false -p 127.0.0.1:8088:8088 -v wealthfolio-data:/data wealthfolio/wealthfolio:latest
  # Then open http://localhost:8088. Keep wealthfolio.env safe.
  # To reach it from other devices, set a password (WF_AUTH_PASSWORD_HASH) first, as the README describes.
  ```

- Needs: The desktop app (macOS 12+, Windows or Linux), or Docker for the web version, For development, Node 24 (.node-version), pnpm, Rust 1.98 (rust-toolchain.toml) and the Tauri prerequisites
- Develop: `pnpm install --frozen-lockfile && cp .env.web.example .env.web && pnpm dev:web   # web UI on :1420, API on :8088; or pnpm tauri dev for the desktop app`
- Test: `pnpm --filter frontend exec vitest run && cargo test --locked -p <crate>`
- Check/lint: `pnpm check && cargo fmt --all -- --check && cargo clippy --locked -p <crate> --all-targets --all-features -- -D warnings`
- Build: `pnpm build   # web front end; docker build -t wealthfolio . for the full server image`
- Stack: rust, typescript, react (Tauri 2, Axum, Diesel, React, React Router, Tailwind CSS, shadcn/Base UI, Recharts, Vite). Difficulty for a non-developer with an AI: **advanced**. Theme, font, language, currency, AI provider and market-data sources are settings, and the add-on SDK lets you add whole new pages without touching the app. Code changes are harder: the React front end talks to two Rust back ends (the Tauri desktop app and the Axum web server), and every new call must be wired into both. Financial maths lives in Rust crates with strict tests.

## The project's own AI instructions
Read these in the repository before changing code: `AGENTS.md`, `CONTRIBUTING.md`.

## Customisation points (settings → extend → code)
- **appearance** [settings]: Light, dark or system theme, a sans, serif or mono font, and which menu items show. → `Settings → Appearance (apps/frontend/src/pages/settings/appearance/appearance-form.tsx)`
- **currency-language-region** [settings]: Your base currency, language, number and date format, time zone, and optional database encryption. → `Settings → General (apps/frontend/src/pages/settings/general/), 11 languages in apps/frontend/src/i18n/locales/`
- **accounts-goals-limits** [settings]: Group accounts (ISA, pension, savings), set yearly allowance limits and savings goals such as a house deposit. → `Settings → Accounts, Portfolios, Contribution limits (apps/frontend/src/pages/settings/accounts/, portfolios/, contribution-limits/) and Goals (apps/frontend/src/features/goals/)`
- **categories-and-spending** [settings]: Your own asset categories (e.g. "ethical", "property") and spending categories and rules. → `Settings → Taxonomies and Spending (apps/frontend/src/pages/settings/taxonomies/, apps/frontend/src/pages/settings/spending/)`
- **market-data** [settings]: Choose price sources, add API keys for extra providers, or set up a custom one. → `Settings → Market data (apps/frontend/src/pages/settings/market-data/), providers in crates/market-data/src/provider/`
- **ai-provider** [settings]: Turn the assistant on with OpenAI, Anthropic, Google, Groq, OpenRouter or a local Ollama model, or leave it off. → `Settings → AI providers (apps/frontend/src/pages/settings/ai-providers/ai-providers-page.tsx, crates/ai/src/ai_providers.json)`
- **csv-import** [extend]: Bring in trades, dividends and deposits from your broker's CSV export. → `Activities → Import (apps/frontend/src/pages/activity/import/), field guide in docs/activities/activity-types.md`
- **addons** [extend]: Add new pages, menu items and charts with a TypeScript add-on that reads accounts, holdings and activities with your permission. → `Settings → Add-ons (apps/frontend/src/pages/settings/addons/), SDK in packages/addon-sdk/, guide in docs/addons/index.md`
- **agent-access** [extend]: Let Claude or another MCP client read (and, if you allow it, draft) portfolio data with a scoped token. → `Settings → AI Agent Access (apps/frontend/src/pages/settings/agent-access/), crates/wealthfolio-mcp/, docs/architecture/cli-mcp-agent-access.md`
- **pages-and-routes** [code]: New screens or changes to existing ones. Text changes must be made in every language file. → `apps/frontend/src/routes.tsx, apps/frontend/src/pages/**, apps/frontend/src/features/**, text in apps/frontend/src/i18n/locales/en/`
- **backend-logic** [code]: New data or calculations. Every new call must be wired into both the desktop and web back ends. → `crates/core/ (logic), crates/storage-sqlite/migrations/ (data), apps/server/src/api/ and apps/tauri/src/commands/ (thin handlers), apps/frontend/src/adapters/`

## Must keep working
- Existing accounts, activities and price history. Make a .wfbackup export before changing code or upgrading.
- WF_SECRET_KEY and the encrypted secrets file. A new key makes stored API keys unreadable.
- Local-first privacy. Don't add new places where financial data is stored or sent (AGENTS.md is explicit about this).
- Database changes need a new migration in crates/storage-sqlite/migrations/; never edit one that has shipped.
- Both runtimes. A new back-end call must work in the desktop app (apps/tauri) and the web server (apps/server); check with the adapter parity test.
- Right-to-left layouts and every language file when changing text.

## Staying updatable
Settings, CSV import, add-ons and AI Agent Access cover most personal needs without a fork, and add-ons survive updates. Read AGENTS.md before code changes. Upstream welcomes pull requests but requires you to sign a CLA that lets Teymz Inc. relicense your code, including under proprietary terms.

## Data, costs and safety
- Personal data: **yes**. Stored in: One SQLite database on your device (desktop app data folder) or in the wealthfolio-data volume (/data) in Docker, plus an encrypted secrets file. Saved snapshots go in a backups/ folder beside the database. This is your complete financial picture. Use Settings → Exports to make a password-protected .wfbackup file before upgrades or code changes, keep the password in a password manager, and keep WF_SECRET_KEY with your backups. Wealthfolio also saves a snapshot automatically before each database upgrade.
- Service: Yahoo Finance and other market-data providers (optional, free (Yahoo); Alpha Vantage, Finnhub, MarketData.app and Metal Price API need your own key, often with a free tier): Daily share, fund and exchange-rate prices. The app sends ticker symbols, not your holdings or amounts.
- Service: AI provider (OpenAI, Anthropic, Google, Groq, OpenRouter or local Ollama) (optional, pay-per-use with your own key, or free with Ollama on your own computer): The optional AI assistant that answers questions about your portfolio and helps import CSV files.
- Service: Wealthfolio Connect (optional, paid subscription): Optional read-only sync with 30+ brokerages and encrypted sync between devices. Manual tracking and CSV import stay free.
- Service: OpenID Connect sign-in provider (Authentik, Authelia, Keycloak…) (optional, free (self-hosted) or varies): Log in to the web version with an existing account instead of a password.
- Setting `WF_SECRET_KEY` (**secret**: the person enters it themselves, never in chat): Web/Docker only. A 32-byte key (openssl rand -base64 32) that encrypts stored API keys and signs logins. Keep it forever; losing it makes stored secrets unreadable. Never paste it into an AI chat.
- Setting `WF_AUTH_PASSWORD_HASH` (**secret**: the person enters it themselves, never in chat): Argon2id hash of your login password for the web version. Needed whenever it is reachable from other devices. Never paste it into an AI chat.
- Setting `WF_AUTH_REQUIRED`: Set to false only when the app is private to this computer or a reverse proxy handles logins.
- Setting `WF_LISTEN_ADDR`: Address and port the server listens on (use 0.0.0.0:8088 in Docker).
- Setting `WF_DB_PATH`: Where the SQLite database file lives, e.g. /data/wealthfolio.db. WF_DATA_DIR is the newer alternative for a whole data folder.
- Setting `WF_CORS_ALLOW_ORIGINS`: The exact address you open the app at, e.g. https://money.example.com. Required when a password is set.
- Setting `WF_DB_REQUIRE_ENCRYPTION`: Set to 1 to create an encrypted database on a new install (it does not convert an existing one).
- Setting `WF_OIDC_CLIENT_SECRET` (**secret**: the person enters it themselves, never in chat): Only for single sign-on. Goes with WF_OIDC_ISSUER_URL, WF_OIDC_CLIENT_ID, WF_OIDC_REDIRECT_URL and an allow-list such as WF_OIDC_ALLOWED_EMAILS.
- Setting `WF_MCP_ENABLED`: Set to true to let outside AI agents read your portfolio over MCP (needs a login and a scoped access token). Off by default.
- Holds your full financial picture. The web version must have a password (WF_AUTH_PASSWORD_HASH) or a sign-in proxy before it is reachable from other devices, and should sit behind HTTPS.
- Keep WF_SECRET_KEY, the backup password and any broker or AI API keys out of AI chats and out of git.
- The AI assistant sends your questions and the portfolio figures it looks up to the provider you choose. Use Ollama to keep it all on your own machine.
- AI Agent Access (MCP) is off by default. When you turn it on, give each token the smallest scope it needs and review the audit log.
- Price updates send ticker symbols to Yahoo Finance or the providers you enable, but not your amounts.

---

# Customising Wealthfolio

Wealthfolio is a React front end on top of Rust, shipped two ways: a Tauri desktop/mobile app and an Axum web server for Docker. **Most personal changes are settings or add-ons.** Add-ons survive updates, so try them before touching code.

## Level 1: Settings (no code)
- **Look:** Settings → Appearance. Light, dark or system theme, a sans, serif or mono font, and the menu layout.
- **Money basics:** Settings → General. Base currency, language (11 available), number and date format, time zone and optional database encryption.
- **Your accounts:** Settings → Accounts and Portfolios. Group accounts the way you think about them (ISA, pension, joint savings).
- **Allowances and goals:** Settings → Contribution limits for yearly ISA or pension allowances; Goals for things like a house deposit or retirement.
- **Categories:** Settings → Taxonomies for your own asset groupings; Settings → Spending for spending categories and rules.
- **Prices:** Settings → Market data. Yahoo Finance works without a key; add keys for Alpha Vantage, Finnhub, MarketData.app or Metal Price API, or set up a custom provider.
- **AI assistant:** Settings → AI providers. OpenAI, Anthropic, Google, Groq, OpenRouter or a local Ollama model. Leave it off if you don't want it.
- **Web version only:** `WF_*` environment variables control the password (`WF_AUTH_PASSWORD_HASH`), single sign-on (`WF_OIDC_*`), the data folder and encryption. See the README's *Web Mode Configuration*.

## Level 2: Extend (no fork)
- **CSV import:** Activities → Import. The fields each activity type needs are in `docs/activities/activity-types.md`.
- **Add-ons:** a TypeScript add-on can add pages, menu items and charts and read accounts, holdings, activities and market data, with the user's permission. Start with `npx @wealthfolio/addon-dev-tools create my-addon`, then run Wealthfolio with `VITE_ENABLE_ADDON_DEV_MODE=true pnpm tauri dev` (or `pnpm dev:addons` for the browser only). Guides: `docs/addons/index.md`, `docs/addons/addon-api-reference.md`. Install finished add-ons from Settings → Add-ons. Examples live in the separate `wealthfolio/wealthfolio-addons` repository.
- **AI Agent Access (MCP):** Settings → AI Agent Access creates scoped tokens so Claude Desktop or another MCP client can query your portfolio. On the web version also set `WF_MCP_ENABLED=true`. Design notes: `docs/architecture/cli-mcp-agent-access.md`.

## Level 3: Code
Read upstream `AGENTS.md` first. It is strict and specific. Summary:

| Change | Where |
|---|---|
| New page or route | `apps/frontend/src/routes.tsx` + `apps/frontend/src/pages/**` or `apps/frontend/src/features/<feature>/` |
| Shared UI components | `packages/ui/` (`@wealthfolio/ui`) |
| Colours and theme tokens | `apps/frontend/src/globals.css`, `apps/frontend/src/themes/` (`pnpm themes:generate`) |
| Text | `apps/frontend/src/i18n/locales/<lang>/*.json`, every language (`pnpm --filter frontend i18n:check`) |
| Calling the back end | `apps/frontend/src/adapters/` (shared, `tauri/` and `web/`) |
| Back-end logic | `crates/core/` |
| New data | new migration in `crates/storage-sqlite/migrations/` + `crates/storage-sqlite/src/` |
| Desktop command / web endpoint | `apps/tauri/src/commands/` (register in `apps/tauri/src/lib.rs`) and `apps/server/src/api/`; keep both thin |
| AI assistant tools and prompt | `crates/ai/src/` (`system_prompt.txt`, `tools/`) |

## Running locally
- **Just use it:** download the desktop app from https://wealthfolio.app/download, or run Docker on this computer only:
  1. `echo "WF_SECRET_KEY=$(openssl rand -base64 32)" > wealthfolio.env` and keep that file safe.
  2. `docker run -d --name wealthfolio --env-file wealthfolio.env -e WF_LISTEN_ADDR=0.0.0.0:8088 -e WF_DB_PATH=/data/wealthfolio.db -e WF_AUTH_REQUIRED=false -p 127.0.0.1:8088:8088 -v wealthfolio-data:/data wealthfolio/wealthfolio:latest`
  3. Open http://localhost:8088.
  4. Before opening it to other devices, set `WF_AUTH_PASSWORD_HASH` and `WF_CORS_ALLOW_ORIGINS` (README → Authentication), or use `compose.yml`.
- **Develop:**
  1. Install Node 24, pnpm, Rust 1.98 and (for desktop) the Tauri prerequisites.
  2. `pnpm install --frozen-lockfile`
  3. Web: `cp .env.web.example .env.web`, then `pnpm dev:web` and open http://localhost:1420.
  4. Desktop: `cp .env.example .env`, then `pnpm tauri dev` (uses a separate development profile).
- **Check:** `pnpm check`, `pnpm --filter frontend exec vitest run`, and for Rust `cargo test --locked -p <crate>`, `cargo fmt --all -- --check`, `cargo clippy --locked -p <crate> --all-targets --all-features -- -D warnings`.

## Pitfalls
- Back up first (Settings → Exports, password-protected `.wfbackup`). Keep the backup password and `WF_SECRET_KEY` somewhere safe.
- Never point development at your real desktop profile. `pnpm tauri dev` uses its own profile on purpose.
- A new back-end call must be wired into both runtimes; `apps/frontend/src/adapters/adapter-command-parity.test.ts` catches gaps.
- Clippy rejects `unwrap()` and `panic!` outside tests.
- In Docker Compose files, Argon2 hashes need their `$` signs quoted or doubled.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/wealthfolio/1e08bbc/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/wealthfolio/1e08bbc/SKILL.md)
