---
title: Installation
description: Three ways to install firma — a macOS or Windows installer (no terminal needed) or npm. All work the same way once set up.
---

export const requirements = [
  {
    icon: '1',
    title: 'Node.js 22 or later',
    desc: <>Check with <code>node --version</code>. Install from <a href="https://nodejs.org" target="_blank" rel="noopener noreferrer">nodejs.org</a> or via <code>nvm</code> / <code>brew install node</code>.</>,
  },
  {
    icon: '2',
    title: 'Claude Desktop',
    desc: <>Required for the MCP integration. Firma registers itself as an MCP server that Claude can call. Download from <a href="https://claude.ai/download" target="_blank" rel="noopener noreferrer">claude.ai/download</a>.</>,
  },
  {
    icon: '3',
    title: 'Finnhub API key (free)',
    desc: <>Used for price sync, earnings, insider transactions, financials, and news. Sign up at <a href="https://finnhub.io" target="_blank" rel="noopener noreferrer">finnhub.io</a>. The free tier is sufficient.</>,
  },
  {
    icon: '4',
    title: 'FRED API key (free)',
    desc: <>Used for macro indicators (VIX, yield curve, USD index, etc.) and the historical FX rate cache that powers accurate non-USD display of past entries. Sign up at <a href="https://fred.stlouisfed.org/docs/api/api_key.html" target="_blank" rel="noopener noreferrer">fred.stlouisfed.org</a>. Approval is instant.</>,
  },
];

export const steps = [
  {
    num: '1',
    title: 'Install globally',
    body: <>
      <code className="step-code">npm install -g @evan-moon/firma</code>
      <p style={{ marginTop: '0.4rem' }}>
        Installs two binaries: <code>firma</code> (CLI) and <code>firma-mcp</code> (MCP server).
      </p>
    </>,
  },
  {
    num: '2',
    title: 'Set your API keys',
    body: <>
      <code className="step-code">firma config set finnhub-key YOUR_KEY</code>
      <code className="step-code" style={{ marginTop: '0.3rem' }}>firma config set fred-key YOUR_KEY</code>
      <p style={{ marginTop: '0.4rem' }}>
        Finnhub keys are at <a href="https://finnhub.io/dashboard" target="_blank" rel="noopener noreferrer">finnhub.io/dashboard</a>.
        FRED keys are at <a href="https://fred.stlouisfed.org/docs/api/api_key.html" target="_blank" rel="noopener noreferrer">fred.stlouisfed.org</a>.
        Both are free.
      </p>
    </>,
  },
  {
    num: '3',
    title: 'Connect Claude Desktop',
    body: <>
      <code className="step-code">firma mcp install</code>
      <p style={{ marginTop: '0.4rem' }}>
        Writes the MCP server entry into Claude Desktop's config file
        (<code>~/Library/Application Support/Claude/claude_desktop_config.json</code> on macOS).
        Restart Claude Desktop to activate.
      </p>
    </>,
  },
  {
    num: '4',
    title: 'Tell Claude what you own',
    body: <>
      <p>
        Open Claude Desktop. Firma tools should appear in the toolbar.
        Drop a CSV / brokerage export / screenshot in chat (or just describe what you hold)
        and ask Claude to set up firma:
      </p>
      <p style={{ marginTop: '0.5rem', fontStyle: 'italic', color: 'var(--fg)' }}>
        "[trades.csv attached] Set up firma with these. Then sync prices and FX, and show me my portfolio."
      </p>
      <p style={{ marginTop: '0.5rem' }}>
        Claude calls <code>add_txn</code> with all rows in one array, then{' '}
        <code>sync</code>, then <code>show_portfolio</code>. No CLI commands needed for onboarding.
        See <a href="/docs/import">Importing Data</a> for more
        examples covering balances and cash flow.
      </p>
    </>,
  },
  {
    num: '5',
    title: 'Daily routine',
    body: <>
      <p>After the initial setup, just ask Claude for the brief once a day:</p>
      <p style={{ marginTop: '0.5rem', fontStyle: 'italic', color: 'var(--fg)' }}>
        "Sync everything and give me today's brief."
      </p>
      <p style={{ marginTop: '0.5rem' }}>
        Claude runs <code>sync</code> (incremental,
        sub-second after the first run), then <code>get_brief</code>. The response
        includes holdings with weights, today's P&L, news, upcoming earnings, macro
        context, and pre-computed insights. See <a href="/docs/brief">Daily Brief</a>.
      </p>
    </>,
  },
];

<Section label="Installation">
<div style={{display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(260px, 1fr))', gap:'1rem'}}>
  <div style={{background:'var(--subtle)', border:'1px solid var(--border)', borderRadius:'10px', padding:'1.25rem 1.5rem', display:'flex', flexDirection:'column', gap:'0.75rem'}}>
    <div style={{fontWeight:600, fontSize:'0.95rem'}}>macOS Installer</div>
    <p className="docs-body">Download and double-click. Node.js is bundled — nothing to install first. Claude Desktop and Claude Code are connected automatically; a setup dialog then shows the two <code>firma config set</code> commands for your free API keys.</p>
    <a href="https://github.com/evan-moon/firma/releases/latest/download/firma-mac-arm64.pkg" target="_blank" rel="noopener noreferrer" style={{display:'inline-flex', alignItems:'center', gap:'0.4rem', background:'var(--green)', color:'#0a0a0a', padding:'0.55rem 1.1rem', borderRadius:'7px', fontWeight:600, fontSize:'0.85rem', textDecoration:'none', width:'fit-content'}}>↓ firma-mac-arm64.pkg</a>
    <p style={{fontSize:'0.8rem', color:'var(--muted)', margin:0}}>Download → double-click → follow setup dialogs → restart Claude Desktop.</p>
  </div>
  <div style={{background:'var(--subtle)', border:'1px solid var(--border)', borderRadius:'10px', padding:'1.25rem 1.5rem', display:'flex', flexDirection:'column', gap:'0.75rem'}}>
    <div style={{fontWeight:600, fontSize:'0.95rem'}}>Windows Installer</div>
    <p className="docs-body">Download and run. Node.js is bundled and <code>firma</code> is added to your <code>PATH</code> — nothing to install first. Claude Desktop and Claude Code are connected automatically; a setup dialog then shows the two <code>firma config set</code> commands for your free API keys.</p>
    <a href="https://github.com/evan-moon/firma/releases/latest/download/firma-win-x64.exe" target="_blank" rel="noopener noreferrer" style={{display:'inline-flex', alignItems:'center', gap:'0.4rem', background:'var(--green)', color:'#0a0a0a', padding:'0.55rem 1.1rem', borderRadius:'7px', fontWeight:600, fontSize:'0.85rem', textDecoration:'none', width:'fit-content'}}>↓ firma-win-x64.exe</a>
    <p style={{fontSize:'0.8rem', color:'var(--muted)', margin:0}}>Unsigned — if SmartScreen warns, choose More info → Run anyway.</p>
  </div>
  <div style={{background:'var(--subtle)', border:'1px solid var(--border)', borderRadius:'10px', padding:'1.25rem 1.5rem', display:'flex', flexDirection:'column', gap:'0.75rem'}}>
    <div style={{fontWeight:600, fontSize:'0.95rem'}}>npm</div>
    <p className="docs-body">Install via npm. Requires Node.js 22+. Full CLI access alongside the MCP integration.</p>
    <code className="step-code">npm install -g @evan-moon/firma</code>
    <p style={{fontSize:'0.8rem', color:'var(--muted)', margin:0}}>Then set API keys and run <code>firma mcp install</code> — see the steps below.</p>
  </div>
</div>
</Section>

<Section label="npm Setup">
  <FeatureList items={requirements} />
  <div style={{marginTop:'1.5rem'}}>
    <Steps items={steps} />
  </div>
</Section>

<Section label="Local Data">
<div className="privacy">
  <div className="docs-body">
    All data is stored in <code>~/.firma/firma.db</code> (SQLite) and{' '}
    <code>~/.firma/config.json</code>. Nothing is sent to Firma servers.
    Back up <code>~/.firma/</code> to preserve your financial history.
  </div>
  <div className="docs-body">
    The SQLite file is readable with any SQLite client. Your data is never
    locked into a proprietary format.
  </div>
</div>
</Section>

<Section label="Support firma">
<div className="docs-body">
  If firma has been useful, give it a star on GitHub. It keeps the project moving.
</div>
<a href="https://github.com/evan-moon/firma" className="star-cta" target="_blank" rel="noopener noreferrer">
  <span className="star-cta-icon">★</span>
  <span>Star on GitHub</span>
  <span className="star-cta-arrow">↗</span>
</a>
</Section>
