Model or dataset
cdinnison/ray-finance avatar
cdinnison/ray-finance

ray-finance is a terminal advisor that answers with a decision, and it keeps your money on your machine

An open-source AI financial advisor that learns your situation and gets smarter every conversation.

307 stars39 forksTypeScriptMIT

At a glance

What is it?
ray-finance is a TypeScript CLI that links bank accounts through Plaid or Bridge, stores everything in an AES-256 encrypted SQLite database, and answers questions with a specific recommendation instead of a chart. The interesting engineering is in the setup edges: a hosted Pro tier that handles your keys for ten dollars a month, an OAuth redirect URI you must register by hand, and a container that exposes a different port than its compose file publishes.
Who is it for?
ray-finance fits someone who wants a recommendation grounded in real account numbers and refuses to hand their financial data to someone else's server, since the local encrypted database and the PII masking before any AI call are the reason to choose it. It does not fit a user outside the United States, Canada, or Europe, because bank coverage is Plaid and Bridge only, and it does not fit anyone unwilling to register an OAuth redirect URI for banks that require it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 61 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One setup wizard, two different products: a paid Pro tier or your own keys

`ray setup` offers two paths and they differ in more than price. Pro is a quick setup at $10/mo where Ray supplies the API key and your data still stays local; the flow asks for your name, opens a Stripe checkout for a Ray API key, links your accounts, and schedules a daily sync at 6am. Bring your own keys is free forever and asks you to pick an AI provider yourself: Anthropic, OpenAI, Ollama running locally, or any OpenAI-compatible endpoint, then choose a model and paste a key.

That fork is the design decision in this project. Pro removes the credential problem, and the trade is that the model calls are routed through a key you do not hold. The local Ollama option is the opposite end of the same axis, since it keeps inference on the machine as well as the data.

The banking step is identical in both modes: Plaid for the United States and Canada, Bridge for Europe including France and the broader EU through PSD2, or both, followed by linking checking, savings, credit cards, investments, loans, and mortgage.

The behaviour Ray is built around is opinionated rather than neutral. It is described as a CFO personality that does not list options but states what it would do and why, referencing your goals. The example in the docs gives a yes, a no, or a not yet with the condition that would change the answer.

Bank coverage is Plaid for North America and Bridge for Europe

There is no generic aggregator here. Two providers cover the supported geography, and the split is geographic rather than technical: Plaid supports the United States and Canada, Bridge supports Europe, with France and the broader EU handled through PSD2 authorisation.

Each provider has its own free developer account, and the setup wizard asks for whichever you chose. The `PLAID_ENV=production` default in the environment template is a reminder that this path is aimed at real data rather than a sandbox, so a first run against a live bank is the expected case rather than an exception.

The two providers are not interchangeable in the config. Plaid brings a client id and secret plus optional product selection, while Bridge has its own dashboard and keys. If you want both regions covered you enter both, and the linked accounts show up together afterwards.

Manual accounts exist as an escape hatch. `ray add` adds an account you type in yourself, such as a home, a car, or crypto holdings, which is the path for anything the two providers do not reach. `ray remove` takes an account out again, whether it was linked or manual.

OAuth banks need a localhost redirect URI registered in the Plaid dashboard

Linking a Plaid OAuth bank such as Chase or Capital One is not a single step, because the redirect has to exist on both sides. You set `PLAID_REDIRECT_URI=http://localhost:9876/oauth-return`, using your `RAY_PORT` value if you changed it from the default, and then register the identical URL in the Plaid dashboard under Team Settings, API, Allowed redirect URIs.

Both halves are required. Plaid permits `http://localhost` for local development, which is why the default points at the machine rather than a deployed domain, but the URL still has to be registered before the bank redirect will come back to the CLI.

If you run Ray in a container, the port is the thing to check first. The image exposes 9876 and starts `node dist/cli/index.js`, while the compose file publishes 3000 on the host. Those two numbers disagree, so an OAuth callback aimed at the default 9876 port will not arrive where compose is listening, and the flow will appear to hang at the bank redirect rather than fail with a clear message.

Leaving Plaid's optional products on without approval makes `ray link` fail

Plaid's Investments and Liabilities products are off by default. If your Plaid account is approved for them you opt in with `PLAID_OPTIONAL_PRODUCTS=investments,liabilities`, and the documented consequence of leaving them enabled without approval is that `ray link` fails.

That is a sharp edge worth understanding rather than working around. The failure is not a partial sync or a missing balance, it is the linking command refusing to complete, which is confusing if you assumed the variable was inert. The reason for the flag existing at all is access control on Plaid's side: these products need per-account approval, so a configuration that asks for them without the entitlement cannot succeed.

The wider pattern is the same one the encryption keys use. Ray keeps a small number of switches whose default is the conservative choice, and the documentation tells you what happens when you move them: leaving an unapproved optional product on breaks the link, and Plaid redirect URIs have to be registered in both places before OAuth banks work.

Environment template, at a glance:

bash
ANTHROPIC_API_KEY=
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_ENV=production
DB_ENCRYPTION_KEY=
PLAID_TOKEN_SECRET=

Two encryption keys, one for the database and one for stored bank tokens

The local-first claim is implemented with two separate secrets, and keeping them separate is the point. `DB_ENCRYPTION_KEY` is the passphrase protecting the local SQLite database, described as any strong passphrase, and the database itself is AES-256 encrypted. `PLAID_TOKEN_SECRET` is a second key used only for encrypting stored Plaid access tokens.

Splitting them means a leaked database passphrase does not hand over the tokens that would let someone reconnect to your bank, and a stolen token secret does not decrypt your transactions. The cost is one more secret for you to store.

Encryption at rest is only half of the story, because something still has to reach a model provider. The answer is PII masking: names, account numbers, and identifying details are scrubbed before anything is sent to the AI, so the remote model sees the shape of your finances rather than your identity. The project describes this as data being analysed rather than exposed.

For anyone running this on a laptop, that pairing is the reason to trust the local storage claim, and it is also why Ollama is offered as a provider. With a local model and a local database, the question of what left the machine reduces to what you chose to send.

Demo mode covers every dashboard but the AI chat still needs a key

You can see the whole interface before linking anything. `ray demo` seeds a database of realistic fake data, and every dashboard command then runs against it through the `--demo` flag.

bash
ray demo                # seed a demo database
ray --demo status       # financial overview
ray --demo accounts     # linked accounts with balances
ray --demo spending     # spending breakdown by category
ray --demo budgets      # budget tracking
ray --demo goals        # financial goal progress
ray --demo score        # daily score, streaks, achievements
ray --demo alerts       # financial alerts
ray --demo transactions # recent transactions

The dashboards need nothing else. The interactive AI chat does, because a model has to answer: you run `ray setup` and add a key from Anthropic, OpenAI, or any OpenAI-compatible provider, and only then does `ray --demo` start an interactive session where the questions are answered against the fake portfolio.

Install is a single global npm package:

bash
npm install -g ray-finance

The package needs Node 18 or newer and registers one binary, `ray`, so every command in the docs is a subcommand of the same executable.

Daily sync is a scheduled job, and the scheduler differs by operating system

Sync is not a background service you leave running. Automatic bank sync is scheduled through launchd on macOS or cron on Linux, and the Pro setup path schedules it for 6am. When you want it now, `ray sync` pulls the latest transactions and balances on demand.

The npm scripts show how thin the scheduled entry point is, with a `sync` script that runs `tsx src/daily-sync.ts`, a daily TypeScript entry rather than a daemon loop. The package itself is otherwise a normal TypeScript build: `tsc` compiles, the public assets are copied into `dist/public`, and tests run through vitest.

Two consequences follow from the design. On Windows there is no mentioned scheduler path, so a daily sync has to be arranged yourself. And because the job is external, a missed run is not retried by the app: `ray sync` is the manual answer, which matters if you are relying on balances being current when a conversation starts.

The Docker route has the same shape. The image is `node:20-slim`, copies the built `dist/`, exposes 9876, and runs the CLI entry point, with compose mounting `./data` to `/app/data` so the database survives a container rebuild and restarting the service unless stopped.

Editorial conclusion

ray-finance fits someone who wants a recommendation grounded in real account numbers and refuses to hand their financial data to someone else's server, since the local encrypted database and the PII masking before any AI call are the reason to choose it. It does not fit a user outside the United States, Canada, or Europe, because bank coverage is Plaid and Bridge only, and it does not fit anyone unwilling to register an OAuth redirect URI for banks that require it. Before linking a real account, read which Plaid optional products you are approved for, keep `PLAID_TOKEN_SECRET` separate from `DB_ENCRYPTION_KEY`, and remember that the daily 0 to 100 score and its 14 achievements are habit mechanics rather than financial advice.

Frequently asked questions

What is Ray AI used for?

In ray-finance it is the advisor itself: a local-first CLI that links your bank accounts and answers questions with a specific recommendation grounded in your actual numbers, keeping the encrypted database on your own machine and masking personal details before anything reaches a model.

How do I install ray-finance?

Run npm install -g ray-finance, which needs Node 18 or newer and registers a single `ray` binary. Then `ray setup` configures a provider and bank credentials, or `ray demo` seeds fake data to look around first.

Which banks and countries does ray-finance support?

Plaid covers the United States and Canada, and Bridge covers Europe including France and the broader EU through PSD2. You can enter both, and `ray add` exists for manual accounts such as a home, a car, or crypto that neither provider reaches.

What is the difference between Pro and bring your own keys in ray-finance?

Pro is $10/mo and supplies the Ray API key through a Stripe checkout while your data stays local and daily sync is scheduled at 6am. Bringing your own keys is free forever and asks you to choose Anthropic, OpenAI, Ollama locally, or any OpenAI-compatible endpoint and paste a key.

How is ray-finance data protected?

Everything sits in an AES-256 encrypted local SQLite database protected by DB_ENCRYPTION_KEY, while stored Plaid access tokens are encrypted separately with PLAID_TOKEN_SECRET. Names, account numbers, and identifying details are scrubbed before anything is sent to the AI.

Why does linking a Plaid OAuth bank need manual setup?

You must set PLAID_REDIRECT_URI=http://localhost:9876/oauth-return, or your RAY_PORT value if changed, and register the same URL under Team Settings, API, Allowed redirect URIs in the Plaid dashboard. Plaid allows http://localhost for local development, but both sides must agree.

Official sources

  1. cdinnison/ray-finance on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cdinnison-ray-finance.svg)](https://hysenlabs.com/projects/cdinnison-ray-finance)