Skip to main content
Glama
README.md
<p align="center">
  <img src="https://raw.githubusercontent.com/evan-moon/firma/main/assets/og-image.png" alt="firma" width="560" />
</p>

<h1 align="center">firma</h1>

<p align="center">
  <strong>You earned well this year.<br/>Do you know where it went?</strong>
</p>

<p align="center">
  Drop your trade history into Claude. Get back the full picture<br/>
  portfolio, net worth, cash flow, stored in one local SQLite file. No account. No cloud. No catch.
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@evan-moon/firma"><img src="https://img.shields.io/npm/v/@evan-moon/firma.svg?style=flat&color=cb3837&logo=npm" alt="npm version"></a>
  <a href="https://github.com/evan-moon/firma/stargazers"><img src="https://img.shields.io/github/stars/evan-moon/firma?style=flat&logo=github&color=ffd700" alt="GitHub stars"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT"></a>
  <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/node-%3E%3D22-339933?style=flat&logo=node.js&logoColor=white" alt="Node >= 22"></a>
  <a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-ready-7c3aed?style=flat" alt="MCP-ready"></a>
</p>

<p align="center">
  <video src="https://github.com/user-attachments/assets/dbdaf14c-fc95-4c66-9d8e-8f674fb8aa7b" controls width="700"></video>
</p>

---

```
You:    Here's my IBKR trade history [trades.csv]. Set up firma.
Claude: I see 47 transactions. Logging in chronological order... done.
        Syncing prices and FX history... your portfolio: $179K, +61% all-time. TSLA is 78%.

You:    My portfolio feels really volatile lately. Should I be worried?
Claude: TSLA is 74% of your equity, a 10% TSLA move is a 7% net worth move.
        Cash flow is solid at $6.4k/month saved. The volatility is market, not lifestyle.

You:    That July expense spike looks alarming.
Claude: That was $57k in TSLL, a leveraged bet, not spending.
        Strip it out: expenses flat at ~$7k/month, savings rate 47.8%.

You:    Give me a full overview with charts.
Claude: Net worth: $294k → $490k in 8 months, pulled back to $427k with TSLA's Q1 dip.
        [builds net worth trend, income vs expenses, portfolio allocation, unrealized P&L]
```

---

## Your brokerage app shows you a number. firma shows you the truth.

- **It talks to Claude. Natively.** Every command lives behind MCP, log trades, sync prices, render charts, reason about your money. You type plain English; Claude does the rest.
- **Local-first, no exceptions.** Everything sits in `~/.firma/firma.db`. No server, no sync, no account. Your financial data never leaves your machine. Ever.
- **Nine markets, one source of truth.** US, KRX, KOSDAQ, JP, HK, LSE, XETRA, NSE, TW, plus crypto, commodities, and real estate. Stored in USD, shown in any currency, with *historical* FX from FRED: a 2018 balance gets the 2018 rate, not today's.
- **No holdings table to lie to you.** Portfolio, cost basis, P&L, all derived live from your trade log. Nothing drifts out of sync, because there's nothing to drift.
- **A brief that actually has an opinion.** `get_market_brief` doesn't dump data, it takes a stance. A weekly lean (aggressive or defensive), a ranked call per holding (BUY / ADD / HOLD / TRIM / SELL / AVOID with conviction and an English thesis), and a watchlist of what to look at next. Every holding is classified, run through a category playbook, and checked by a correlation guard that catches "more of what you already own" before it lands.
- **A simulator nobody else ships.** `project_net_worth` runs multi-scenario Monte Carlo over *your* portfolio at *any* horizon, next month or 30 years, one tool. `simulate_scenario` does the deterministic day-to-week version ("PCE comes in hot Thursday, how much does that cost me?"). You supply the assumptions, Claude discloses them verbatim, firma does the math. No hidden "advisor view."
- **Time-series features from day one.** The first `firma sync` backfills 90 days of daily history. Correlation, Sharpe, max drawdown, volatility, CAGR, populated immediately, not 30 days from now.
- **It tracks your decisions, not just your positions.** `show_thesis_track` reads your own trade reasons back to you against the outcome. `show_anti_portfolio` follows what you sold, the data brokerages hide because it exposes bad exits.

---

## Get started

```bash
# 1. Install
npm install -g @evan-moon/firma

# 2. Set API keys (both free)
firma config set finnhub-key YOUR_KEY   # finnhub.io, prices, news, earnings
firma config set fred-key YOUR_KEY      # fred.stlouisfed.org, macro & FX history

# 3. Connect Claude Desktop, then restart it
firma mcp install
```

**Rather not touch a terminal?** Grab the [macOS](https://github.com/evan-moon/firma/releases/latest/download/firma-mac-arm64.pkg) or [Windows](https://github.com/evan-moon/firma/releases/latest/download/firma-win-x64.exe) installer, Node.js is bundled, Claude is wired up for you.

Then **drop your data into Claude**, a CSV, a brokerage export, plain text. It logs everything and syncs prices automatically.

> If firma helps you see where your money went, [⭐ star the repo](https://github.com/evan-moon/firma/stargazers), it's the cheapest way to help others find it.

---

## How it's split: MCP thinks, the CLI keeps you safe

firma is **MCP-first**. Analysis, briefs, recommendations, news, valuation, projections, all of it happens in conversation with Claude. The CLI exists for the three things a chat can't safely own: **setup, manual data entry, and repair.**

```bash
# Setup
firma config set <key>        # finnhub-key / fred-key / currency
firma mcp install             # register with Claude Desktop
firma doctor                  # check keys, data state, FX cache, coverage

# Manual entry
firma add txn                 # buy / sell / deposit / dividend / tax, any of 9 markets
firma add monthly             # month-end balance + cash flow in one flow
firma add snapshot            # sync prices, snapshot today's portfolio

# Repair (when Claude or you got it wrong)
firma edit txn / balance / flow / snapshot
firma delete txn / ...        # alias: firma rm

# Verify (read-only, just confirm what landed in the DB)
firma show portfolio / txns / balance / flow / snapshot / profile / fx

# Sync
firma sync                    # prices (Finnhub) + FX history (FRED) + correlation cache
firma sync fx                 # FX history only
```

Everything analytical (`get_market_brief`, every `show_*`, `report`, `project_net_worth`, `simulate_scenario`) lives in Claude. Two tool families that never mix: **diagnostic** (what's true right now, no fortune-telling) and **thought experiment** (what-ifs, assumptions always disclosed).

---

## Architecture

A Yarn Berry monorepo with a strict port-and-adapter layout. The application layer never imports an external API directly, it talks to domain interfaces, and adapters implement them.

```
packages/
  domain/        ports + types, zero external-API knowledge
  external-api/  raw clients (finnhub, fred, worldbank, gdacs, yahoo, …), zero domain knowledge
  adapter/       the only layer that imports both sides
  use-case/      business logic (portfolio, brief, advisor, projection, scenario)
  shared/        db + utils
apps/
  cli/  mcp/  docs/
```

**The rule:** external-API packages know nothing about firma's domain; domain packages know nothing about any external API. `@firma/adapters` is the single bridge. Adding a data source touches no command and no business logic, a new raw client, one adapter, one registration line.

See [CONTRIBUTING.md](CONTRIBUTING.md) for the full walkthrough and the recipe for adding a provider.

## Development

Requires Node.js 22+ and Yarn Berry.

```bash
corepack enable
yarn install
yarn dev:cli show portfolio    # CLI dev mode
yarn typecheck
yarn test
```

---

## The ecosystem

**firma** is one of three local-first tools that share one principle, **your data stays on your machine, and the AI comes to it.** They interoperate through any MCP client, and none depends on the others.

```mermaid
flowchart TB
    U([You])
    subgraph I["Interfaces, talk to your tools"]
        direction LR
        CD[Claude Desktop]
        CC[Claude Code]
        H["Herald · voice"]
    end
    subgraph T["Local-first tools, each owns its data, on your machine"]
        direction LR
        F["firma · money<br/>~/.firma"]
        M["memex · memory<br/>~/.memex"]
        S["skope · news<br/>~/.skope"]
    end
    U --> I
    I -- MCP --> F & M & S
    F <-. never call each other .-> M
    M <-.-> S
```

- **[firma](https://github.com/evan-moon/firma)** · money, portfolio, net worth, cash flow
- **[memex](https://github.com/evan-moon/memex)** · memory, notes and the context behind them, across sessions
- **[skope](https://github.com/evan-moon/skope)** · news, a personalized lens on the world

You reach them through Claude Desktop, Claude Code, Cursor, or **[Herald](https://ai-herald.vercel.app)**, a voice interface. The tools compose through the model, never by calling each other.

---

## License

MIT © [Evan Moon](https://github.com/evan-moon)

TDQS

A4/5.0

Scored across 37 tools

Disambiguation4/5

Tools are grouped by domain (transactions, balance, flow, portfolio, market analysis) with clear descriptions. Some overlap exists between get_market_brief and show_portfolio, but descriptions clarify the primary vs drill-down roles. Overall, distinct purposes are well-maintained.

Naming Consistency5/5

Almost all tools follow a consistent verb_noun pattern (add_*, delete_*, edit_*, show_*, etc.). Exceptions like 'report' and 'sync' are still clear and do not break the pattern. Excellent consistency.

Tool Count3/5

At 37 tools, the server is heavy but covers a broad domain (personal finance, investments, market data). While many tools are justified, the count is on the high side for typical MCP servers, potentially overwhelming for users.

Completeness5/5

The tool surface is remarkably complete: CRUD for transactions, balance, flow, snapshots; analytical reports, market data, projections, risk metrics, thesis tracking, and profile management. Nearly every common financial operation is supported without obvious gaps.

Maintenance

ActivityActive
ResponsivenessSyncing