Skip to content

About

Read your BetterOff household finances from the terminal. Read-only, MIT.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

Repository files navigation

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⢿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⡟⠁⠈⢻⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⠏⠀⠀⠀⠀⠹⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠁⠀⠀⠀⠀⠀⠀⠈⢿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣿⣿⠟⠀⠀⢀⣤⣾⣷⣤⡀⠀⠀⠻⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣿⣿⣿⣿⠋⠀⣠⣴⣿⣿⠟⠻⣿⣿⣦⣄⠀⠙⣿⣿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⣿⣿⣿⡿⢁⣴⣾⣿⡿⠋⠀⢀⡀⠀⠙⢿⣿⣷⣦⡈⢿⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣀⣴⣿⡿⠋⣵⣿⣿⣿⣶⣿⣿⠟⠁⠀⢀⣴⣿⣿⣦⡀⠀⠈⠻⣿⣿⣶⣿⣿⣿⣮⠙⢿⣿⣦⣀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢀⣠⣾⣿⠟⠉⢀⣾⣿⣿⣿⣿⠿⠋⠀⠀⢀⣴⣿⡿⠟⠻⢿⣿⣦⡀⠀⠀⠙⠿⣿⣿⣿⣿⣷⡀⠉⠻⣿⣷⣄⡀⠀⠀⠀⠀
⠀⠀⣀⣴⣿⡿⠋⠁⠀⣰⣿⣿⣿⡿⠛⠁⠀⠀⣠⣴⣿⡿⠋⠀⠀⠀⠀⠙⢿⣿⣦⣄⠀⠀⠈⠛⢿⣿⣿⣿⣆⠀⠈⠙⢿⣿⣦⣀⠀⠀
⣤⣾⣿⠟⠉⠀⠀⢀⣼⣿⣿⠟⠋⠀⠀⠀⣠⣾⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣷⣄⠀⠀⠀⠙⠻⣿⣿⣧⡀⠀⠀⠉⠻⣿⣷⣤
⠛⢿⣿⣦⣀⠀⠀⠈⢻⣿⣿⣦⣄⠀⠀⠀⠙⢿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡿⠋⠀⠀⠀⣠⣴⣿⣿⡟⠁⠀⠀⣀⣴⣿⡿⠛
⠀⠀⠉⠻⣿⣷⣄⡀⠀⠹⣿⣿⣿⣷⣤⡀⠀⠀⠙⠻⣿⣷⣄⠀⠀⠀⠀⣠⣾⣿⠟⠋⠀⠀⢀⣤⣾⣿⣿⣿⠏⠀⢀⣠⣾⣿⠟⠉⠀⠀
⠀⠀⠀⠀⠈⠙⢿⣿⣦⣀⠈⢿⣿⣿⣿⣿⣶⣄⠀⠀⠈⠻⣿⣷⣦⣴⣾⣿⠟⠁⠀⠀⣠⣶⣿⣿⣿⣿⡿⠁⣀⣴⣿⡿⠋⠁⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠉⠻⣿⣷⣄⡻⣿⣿⣿⠿⣿⣿⣦⡀⠀⠈⠻⣿⣿⠟⠁⠀⢀⣴⣿⣿⠿⣿⣿⣿⢟⣠⣾⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣷⡈⠻⢿⣿⣷⣄⠀⠈⠁⠀⣠⣾⣿⡿⠟⢁⣾⣿⣿⣿⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⣿⣿⣿⣿⣄⠀⠙⠻⣿⣿⣦⣴⣿⣿⠟⠋⠀⣠⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣿⣿⣦⠀⠀⠈⠛⢿⡿⠛⠁⠀⠀⣴⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣷⡀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⣆⠀⠀⠀⠀⣰⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣧⡀⢀⣼⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

BetterOff CLI

Read your BetterOff household from the terminal: accounts, net worth, transactions, spending, cash flow, recurring bills, portfolio, and debts.

The CLI is read-only. It cannot move money, change records, or approve anything. It runs on macOS, Linux, and Windows.

CI Latest release

$ betteroff accounts
Display name                  Balance     Available balance  Balance as of     Type
Everyday Checking (...1234)   $4,210.55   $4,190.55          2026-10-22 16:00  depository
High-Yield Savings (...8841)  $18,250.00  $18,250.00         2026-10-22 16:00  depository
Rewards Visa (...0912)        $612.40     $9,387.60          2026-10-22 16:00  credit
Brokerage (...5530)           $52,318.09  $1,204.11          2026-10-22 16:00  investment
Solana Wallet (...7xQp)       $88.12      -                  2026-10-22 16:00  crypto
2 more columns hidden; use --json for everything

As of 2026-10-22 16:00 UTC

The accounts above are made up.

Before you start

You need a BetterOff account with the accounts and wallets you want to read connected. Every member of the household must turn on Chat data access in BetterOff's Settings before any agent, this CLI included, can read household data.

Install

With Homebrew on macOS or Linux:

brew install raintree-technology/tap/betteroff

Or with the install script:

curl -fsSL https://raw.githubusercontent.com/raintree-technology/betteroff.cli/main/install.sh | sh

The script downloads the binary for your system from the latest release into ~/.local/bin and refuses to install it unless it matches the release's SHA256SUMS. If the GitHub CLI is installed and signed in, it also checks the binary's build provenance, which proves it was built by this repository's release workflow. Set BETTEROFF_VERSION=0.1.2 for a specific version or BETTEROFF_INSTALL_DIR for another folder.

You can also download a binary from the release page and compare it with SHA256SUMS. The macOS binaries are signed with a Developer ID and notarized by Apple, so Gatekeeper accepts them. A browser download is not executable yet; run chmod +x on it first. On Windows, download betteroff-windows-x64.exe.

To check any release binary yourself:

gh attestation verify betteroff-darwin-arm64 --repo raintree-technology/betteroff.cli

From source

With Bun 1.4.3 or later:

git clone https://github.com/raintree-technology/betteroff.cli.git
cd betteroff.cli
bun install --frozen-lockfile
bun run build   # writes dist/betteroff

Sign in

betteroff login

Your browser opens BetterOff's sign-in and consent page. Approve the BetterOff CLI, and the browser hands a one-time code back to the CLI on 127.0.0.1; the CLI never sees your password. The CLI can ask only for read access, and it renews its access on its own for up to 30 days. You can end it at any time under Settings > Agent connections in BetterOff, or with betteroff logout.

Over SSH, the browser runs on your own computer, so its redirect to 127.0.0.1 cannot reach the CLI. betteroff login notices the SSH session and prints the link instead of opening a browser. Open it on your computer and approve; the browser then shows a page that cannot connect. Copy the full address from its address bar and paste it into the terminal. The address only works with the login that is waiting for it.

The sign-in is saved in your system keychain: macOS Keychain (through Apple's security tool, so upgrades never prompt for access), libsecret on Linux, or Windows Credential Manager. betteroff status shows how the CLI is signed in.

With an API token

For CI, or a machine whose keychain is locked:

  1. In BetterOff, open Settings > API tokens and create a token with read scopes only.
  2. Set BETTEROFF_API_TOKEN to it, or run betteroff login --token and paste it to save it in the keychain.

Use

betteroff overview
betteroff accounts
betteroff transactions --merchant "whole foods" --all-time
betteroff transactions --start-date 2026-09-01 --end-date 2026-09-30 --traits travel
betteroff analyze-spending
betteroff recurring
betteroff portfolio --group-by account
betteroff net-worth-history
betteroff debts

Run betteroff --help for every command and betteroff <command> --help for its flags.

In a terminal, results print as tables and labeled fields, with paging, data quality, and freshness notes at the end. When output is piped, or with --json, the CLI prints the exact JSON result, so it works in scripts and as a tool for AI agents:

betteroff recurring --json | jq '.data'

Lists are paged. When there is more, the footer prints the --cursor value for the next page.

How it works

The CLI calls BetterOff's public tool API, POST https://api.betteroff.finance/v1/tools/<tool>, the same tools the BetterOff MCP server offers. Its commands and flags come from the public spec at /openapi/tools.json, cached for an hour in ~/.cache/betteroff. A new read tool in BetterOff shows up as a command without a CLI update.

Only tools the spec marks read-only become commands. Tools that propose changes or request transfers are left out, even if the spec labels one read-only by mistake. BetterOff enforces the real limit: a browser sign-in can only get read scopes, and an API token has the scopes you gave it, so give it read scopes only.

Upgrade and uninstall

brew upgrade betteroff

With the install script, run it again. betteroff --version shows the installed version.

To remove the CLI, sign out first so the sign-in ends at BetterOff, then delete the binary and its cache:

betteroff logout
brew uninstall betteroff   # or: rm ~/.local/bin/betteroff
rm -rf ~/.cache/betteroff

Troubleshooting

Message What to do
Not signed in. Run: betteroff login Sign in, or set BETTEROFF_API_TOKEN.
Your BetterOff sign-in has expired or was revoked. Run betteroff login again. Sign-ins last up to 30 days, and ending the connection in BetterOff's settings revokes it.
The system keychain refused the request The keychain is locked, which is common over SSH. Run security unlock-keychain on macOS, or use BETTEROFF_API_TOKEN.
Sign-in timed out. The browser did not come back within 5 minutes. Over SSH, paste the address the browser ends on.
A command needs a flag you do not have betteroff <command> --help lists its flags; required ones are marked.

Environment variables

Variable Use
BETTEROFF_API_TOKEN Personal API token (bo_pat_...). Overrides the saved token.
BETTEROFF_API_URL API origin. Defaults to https://api.betteroff.finance.
NO_COLOR Any value turns off terminal styling.

Security

  • Read-only. Only tools the spec marks read-only become commands, and tools that propose changes or request transfers are left out by name as well. Give the token read scopes only; the token's scopes are the limit BetterOff enforces.
  • Sign-in uses OAuth with PKCE. betteroff login uses the authorization code flow on a loopback redirect (RFC 8252), checks state and the issuer on the way back, and identifies itself with a client metadata document on betteroff.finance that allows only read scopes. Each refresh replaces the refresh token, and a lock keeps two commands from refreshing at once. betteroff logout revokes the sign-in at BetterOff.
  • Tokens go only to BetterOff, over HTTPS. They are saved in the system keychain, never in a file. On macOS it goes through Apple's security tool on stdin, never on a command line. BETTEROFF_API_URL must be an https:// origin (http:// only for localhost), and the CLI never follows a redirect, so the token cannot be sent somewhere else by mistake.
  • Pinned trust. Requests trust a bundled Mozilla root certificate snapshot (src/ca.pem) instead of Bun's built-in list, which still includes roots Mozilla has distrusted.
  • Safe terminal output. Merchant names and other text come from banks and other third parties. The CLI replaces control characters and bidirectional overrides before printing, so that text cannot move the cursor, rewrite the screen, set the clipboard, or reorder what you see. --json output escapes the same characters and still parses to the same value.
  • Supply chain. Dependencies are pinned to exact versions with a frozen lockfile, and new releases wait 3 days before install. CI actions are pinned to commit SHAs with read-only tokens. CodeQL scans the code and workflows. OSV-Scanner checks every version in bun.lock against known vulnerabilities on each pull request and daily. Pull requests also fail on vulnerable new Actions, and Socket reviews dependency changes.
  • Verifiable releases. Release binaries are built by a GitHub Actions workflow from a version tag, with signed build provenance and SHA-256 checksums. Since v0.1.2 the macOS binaries are signed with a Developer ID (Zachary Roth, team 7F3ZJMU55Z), use the hardened runtime, and are notarized by Apple. Releases are immutable, so a published binary cannot be replaced.

Report a vulnerability to security@betteroff.finance, not in a public issue. See SECURITY.md.

Development

bun install --frozen-lockfile
bun run typecheck
bun run test

Tests use a fake API and never call BetterOff.

Releasing

  1. Set the version in package.json and VERSION in src/cli.ts, and merge.
  2. Tag the merge commit with a signed tag, git tag -s v<version>, and push the tag.

The Release workflow builds the binaries, signs and notarizes the macOS ones, attests provenance, publishes the GitHub release, and updates raintree-technology/homebrew-tap. Releases are immutable; to fix one, release a new version.

Secrets live in the release environment, which only v* tags can use:

Secret What it is
APPLE_DEVELOPER_ID_P12_BASE64 Developer ID Application certificate and private key, as base64 of a .p12 export
APPLE_DEVELOPER_ID_P12_PASSWORD Password of that .p12
APPLE_NOTARY_KEY_P8 App Store Connect API key (.p8 contents) with the Developer role, for notarytool
APPLE_NOTARY_KEY_ID That key's ID
APPLE_NOTARY_ISSUER_ID The App Store Connect issuer ID
HOMEBREW_TAP_DEPLOY_KEY Private half of a deploy key that can write only to the tap repository

Notarization is on (repository variable NOTARIZE is true), so a release whose macOS binaries are not signed and accepted by Apple is not published. Apple usually answers in minutes but can take over an hour; the job waits up to 80 minutes.

If a release run fails before it publishes, no release exists yet. Fix the cause, then move the tag to the fixed commit: git push origin :refs/tags/v<version>, re-create the signed tag, and push it. Once published, a release cannot change; release a new version instead.

The Developer ID certificate expires five years after it was issued. Binaries signed before then keep working, because each signature carries a secure timestamp. To replace it, export the new certificate and update the two APPLE_DEVELOPER_ID_P12_* secrets.

License

MIT, see LICENSE. The BetterOff name and logo are trademarks of FinSync LLC and are not covered by the license.

About

Read your BetterOff household finances from the terminal. Read-only, MIT.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages