Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Lightweight FIRE Tracker & API Server
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A self-hosted Financial Independence, Retire Early (FIRE) tracker and API server. Runs locally via Docker. All financial data is stored in
data/db.jsonon your machine with optional AES-256-GCM encryption (SYNC_MASTER_KEY). Read-only with respect to external financial accounts (no transactions initiated); local CRUD is fully supported. Being productionized toward real-time API-driven sync (eBay, Web3 wallets, Fidelity/Plaid) in PROD Phases 1–4. See docs/prod-plan.md.
fire is a local-first FIRE tracker for people who want one place to see the whole picture without handing their financial database to a hosted dashboard.
db.json, with optional AES-256-GCM encryption at rest.Try it: live browser demo · Run it locally: docker compose up -d · Use with Claude: see MCP Server and the fire-coach skill
Requires Docker Desktop.
# Clone and configure
git clone https://github.com/nitsuah/fire.git
cd fire
cp .env.example .env
API auth is required by default — edit .env and either set FIRE_API_KEY
(recommended; generate one with the command in Environment Variables)
or set FIRE_AUTH_DISABLED=true to run without auth for local-only use. The
server refuses to start with neither set.
# Start
docker compose up -d
The root compose.yaml names the project fire and includes
config/docker-compose.yml, so this runs from the repo root. docker compose up fire
starts just the app, and the longer docker compose -f config/docker-compose.yml …
form still works.
Open http://localhost:3001 (plain HTTP) or https://localhost (via the bundled Caddy reverse proxy — see HTTPS via Caddy below) in your browser.
# Stop
docker compose down
# Rebuild after dependency changes
docker compose build
docker compose up -d --force-recreate
Copy .env.example to .env and set values as needed. Most are optional for
basic local use — the one exception is FIRE_API_KEY (or its explicit
FIRE_AUTH_DISABLED opt-out), which the server requires just to start.
| Variable | Purpose |
|---|---|
PORT | Server port (default 3001) |
FIRE_API_KEY | Required by default. All /api/* routes require X-Api-Key: <value>. The server refuses to start unless this or FIRE_AUTH_DISABLED is set |
FIRE_AUTH_DISABLED | Set to true to run with no API auth at all (local-only use). Leave unset if anyone else could reach the server — see security-hardening.md |
FIRE_ADMIN_KEY | Required in production. Gates POST /api/admin/rotate-key via X-Admin-Key header |
SYNC_MASTER_KEY | 64-hex-char key to encrypt db.json at rest with AES-256-GCM |
SESSION_SECRET | Secret for signing session cookies (random string; server exits in production if unset) |
EBAY_CLIENT_ID / EBAY_CLIENT_SECRET | eBay Developer app credentials for Order API sync |
EBAY_ENVIRONMENT | sandbox (default) or production |
ETSY_CLIENT_ID | Etsy app keystring for receipts sync (with SYNC_MASTER_KEY). Optional: ETSY_SHARED_SECRET (sent as x-api-key: keystring:secret) and ETSY_REDIRECT_URI (defaults to <origin>/api/sync/etsy/callback) |
EBAY_REDIRECT_URI | OAuth redirect_uri sent to eBay. For a real eBay app this is your RuName. The default is derived from the incoming request (host + protocol, honouring the reverse proxy). Required on Netlify |
EBAY_VERIFICATION_TOKEN | 32–80 char token you also register in the eBay Developer Portal for Marketplace Account Deletion notifications |
EBAY_NOTIFICATION_ENDPOINT_URL | Public HTTPS URL of /api/sync/ebay/marketplace-account-deletion exactly as registered with eBay (used in the challenge hash). On Netlify: https://lifefire.netlify.app/api/sync/ebay/marketplace-account-deletion. The eBay variables also apply to the Netlify Functions deploy; see |
Generate keys:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
docker compose up -d also starts a
Caddy reverse proxy (config/Caddyfile) that
terminates TLS for https://localhost. Plain HTTP on http://localhost:3001
still works for same-machine use (OAuth redirect callbacks are configured
against it — see below), but the fire container's port is bound to
127.0.0.1 only, not every network interface, so another machine on the LAN
can't reach it in cleartext — only this machine can, over either :3001
directly or https://localhost via Caddy.
The certificate comes from Caddy's local CA (tls internal), so browsers
warn until you trust it once. caddy trust only updates the trust store
inside the caddy container — it does not touch your host or browser.
Instead, copy the CA cert out and import it yourself:
docker compose cp caddy:/data/caddy/pki/authorities/local/root.crt ./caddy-local-ca.crt
then import caddy-local-ca.crt via your OS/browser's certificate manager
(see Caddy's docs for OS-specific
steps).
For LAN IP access, add the IP as another site block in config/Caddyfile
(self-signed — pin the cert in your browser). For a public domain with a
real Let's Encrypt cert, replace localhost in the Caddyfile with the
domain and drop the tls internal line.
Connect Claude Code to your live financial data. The project ships a .mcp.json that Claude Code picks up automatically on startup — no edits needed, since Claude Code runs project MCP servers from the project root and the server resolves its data directory itself. Point it at a different data directory with the FIRE_DATA_DIR environment variable if you like:
{
"mcpServers": {
"fire-tracker": {
"command": "node",
"args": ["app/mcp-server.mjs"]
}
}
}
Tools (20, all read-only): fire_status_summary, get_net_worth, get_net_worth_trend, get_accounts, get_portfolio, get_transactions, get_recurring_charges, get_cds, get_upcoming_events, get_expenses, get_insurances, get_projection_settings, get_side_gig_income, get_side_gig_tax_summary, get_wallets, get_concentration_risk, get_diversification_score, get_swr_sensitivity, simulate_rebalance, get_emergency_runway
simulate_rebalance is a what-if: it reports allocation and diversification score before/after moving money between asset classes, and never trades or saves anything. With chaos: true it sweeps every single-leg move across liquid classes and your top positions at several sizes, scores each under bear/base/bull return assumptions you supply (defaults are placeholders) net of estimated capital-gains tax, and ranks the rows by a metric you pick. It reports a table, never a recommendation.
Claude skill: skills/fire-coach makes Claude a FIRE coach for this app. It maps questions to the right MCP tools, applies a FIRE playbook (the 4% rule, savings rate, order of operations, taxes, sequence risk, what to do when income stops) and points to the exact tab and button. Install it with mkdir -p ~/.claude/skills && cp -r skills/fire-coach ~/.claude/skills/.
Money-maker skills: skills/reseller-autopilot prices items and drafts listings, with net-after-fees on eBay, Etsy, Mercari, Poshmark and FB Marketplace and runs a weekly low-touch selling routine. skills/passive-income-lab sizes low-touch income streams against your runway and shows how far each moves your FIRE date.
Smoke-test locally:
docker compose exec fire node scripts/test-mcp.mjs
Every projection is a smooth line; life isn't. 🌪️ Chaos applies a seeded timeline of 37 kinds of life events to the base path. The plain path stays on the chart as a dashed "Without chaos" line.
| Category | Examples | Typical impact |
|---|---|---|
| Health | gallbladder surgery, ER visit, dental emergency, serious illness, knee/hip replacement | $1.2k – $14k one-time, rising ~2%/yr above inflation the later it happens; serious illness can add months of lost income |
| Pets | cat cancer, dog emergency surgery | $1.5k – $10k one-time (vet bills rise ~2%/yr above inflation) |
| Family | wedding, child birth, daycare ending, divorce, aging parent care, unpaid family loan, funeral, inheritance, inherited house, family gift | child −$8k to −$16k/yr for 18 years; divorce −20–35% of net worth; inheritance +$15k – $200k; inherited house: sell (+$220k), move in (+$15k/yr) or rent it out (+$11k/yr) |
| Career | job loss, new job/promotion, bonus, side hustle takes off, pay cut, RSUs | 2–10 months of income lost; a promotion is a signing bump or extra savings for 5–6 years (wages are flat in real terms) |
| Housing | roof/HVAC, water damage, rent hike / forced move, refinance, roommate / house hack | $2.5k – $35k one-time; rent +$3k – $6k/yr; refinance +$2.4k – $4.8k/yr for 15 years; roommate +$7k – $12k/yr |
| Auto | accident, major repair, replacement car, car loan paid off | $1k – $30k; a paid-off loan frees $4k – $5k/yr for a few years |
| Windfall | surprise tax refund, sold a collection, lottery/crypto, settlement or claim payout | +$400 – $40k |
| Legal & money | identity theft, surprise tax bill, lawsuit | $500 – $30k |
app/lib/chaos-events.js, .Every tab is a set of sections. Each section picks a column layout: full width, 2 equal, 2 wide-left, 2 wide-right, 3 equal, 3 wide-center or 4. Each column stacks cards. A card alone in its section spans the full width, so there are no fixed per-tab widths. On narrower screens sections drop to two columns, and on phones to one.
data/db.json inside the project directory (Docker volume-mounted).db.json at rest with SYNC_MASTER_KEY (AES-256-GCM).fire/
├── app/
│ ├── index.html # Single-page app entry point
│ ├── server.js # Express server (port 3001)
│ ├── mcp-server.mjs # MCP server — 20 read-only tools
│ ├── lib/
│ │ ├── db.js # State persistence (db.json, atomic writes)
│ │ ├── crypto-utils.js # AES-256-GCM encrypt/decrypt
│ │ ├── finance-calcs.js # Server-side projection engine (MCP + API)
│ │ ├── finance-core.js # Core FIRE math primitives
│ │ ├── finance-parsing.js # CSV parsing helpers
│ │ ├── projections.js # Blended return, passive income offset, depletion age
│ │ ├── html-utils.js # XSS escape utility (shared by table renderers)
│ │ ├── yahoo-prices.js # Yahoo Finance price fetcher (crumb-based)
│ │ ├── prices-provider.js # Price provider abstraction (Yahoo / Alpha Vantage / Polygon)
│ │ ├── webhook-integration.js # Webhook payload handler
│ │ ├── ebay-connector.js # eBay Order API OAuth + order fetch
│ │ ├── etsy-connector.js # Etsy Open API v3 OAuth (PKCE) + receipts → ledger rows
│ │ ├── etsy-handlers.js # Etsy OAuth handlers, shared by Express + Netlify
│ │ ├── etsy-sync.js # Etsy connection cards (browser)
│ │ ├── marketplace-reports.js # Mercari / Poshmark / FB CSV parsers + dedupe merge (browser + Node)
│ │ ├── cointracker-connector.js # CoinTracker OAuth (PKCE + DCR) + read-only MCP client
│ │ ├── cointracker-handlers.js # CoinTracker routes, shared by Express + Netlify
│ │ ├── cointracker-merge.js # Folds CoinTracker wallets into accounts (dedupe, browser + Node)
│ │ ├── crypto-balance.js # Crypto account value: ticker × price, or ENS/0x multichain total
│ │ ├── multichain-balance.js # Keyless multichain total (Blockscout + publicnode RPCs)
│ │ ├── web3-prices.js # Wallet-tracker balance fetch (ETH, BTC, SOL, EVM chains; BYOK keys)
│ │ ├── gdrive-backup.js # Google Drive encrypted backup/restore
│ │ ├── vehicle-api.js # NHTSA VIN decode + vehicle value estimate
│ │ ├── csv-import.js # Fidelity / Chase / CapOne CSV parsing (also routes eBay reports)
│ │ ├── ebay-report.js # eBay listings sales report parser + dedupe merge (browser + Node)
│ │ ├── metals-prices.js # Gold/silver spot (metals.dev + Yahoo futures fallback)
│ │ ├── fetch-utils.js # fetchJson helper (safe JSON parsing for browser managers)
│ │ ├── expenses.js # Expense calculation helpers
│ │ ├── side-gig.js # Side hustle fee-calc logic
│ │ ├── privacy.js # Privacy consent helpers
│ │ ├── server-utils.js # findAvailablePort, strictNum
│ │ ├── charts/ # Chart.js renderers (allocation drill-down, projections, CD ladder)
│ │ ├── tables/ # Table renderers (dashboard banner, positions, ledger, insights tiles, …)
│ │ ├── managers/ # UI managers (accounts, navigation, wallets, hustle accelerators, spending upload, …)
│ │ └── css/ # base / layout / components / widgets stylesheets
│ └── routes/
│ ├── state.js # GET / POST /api/state
│ ├── accounts.js # CRUD /api/accounts
│ ├── cds.js # CRUD /api/cds
│ ├── prices.js # GET /api/prices, GET /api/prices/stream (SSE)
│ ├── wallets.js # CRUD /api/wallets + /api/wallets/:id/refresh + /api/wallets/refresh-all
│ ├── vehicles.js # GET /api/vehicles/vin/:vin, POST /api/vehicles/:id/refresh-value
│ ├── (accounts.js also) # POST /api/accounts/:id/refresh-crypto, /refresh-metal
│ ├── backup.js # POST /api/backup/drive, GET /api/backup/drive/list, POST /api/backup/drive/restore
│ ├── sync.js # Webhook templates CRUD, POST /api/sync/webhook/:templateId; mounts the four below
│ ├── ebay.js # /api/sync/ebay/* (OAuth, sync, marketplace deletion)
│ ├── etsy.js # /api/sync/etsy/* (authorize, callback, status, toggle, sync, disconnect)
│ ├── plaid.js # /api/sync/plaid/*
│ └── cointracker.js # /api/sync/cointracker/* (authorize, callback, sync, inspect, disconnect)
├── netlify/
│ ├── functions/ # Hosted (lifefire.netlify.app) API: fire-api (metals, ENS lookup, crypto refresh),
│ │ # ebay-*, etsy, cointracker share the Express handlers; plaid still duplicates them
│ └── lib/http.mjs # Shared Function helpers
├── config/
│ ├── docker-compose.yml # fire + Caddy (HTTPS)
│ ├── Dockerfile # node:22-alpine
│ ├── Dockerfile.playwright # pinned Playwright image for UI tests
│ ├── playwright.config.js # real-browser UI regression suite (tests/e2e-ui)
│ └── eslint.config.mjs
├── scripts/
│ └── test-mcp.mjs # MCP smoke test (all 20 read-only tools)
├── data/ # db.json lives here (git-ignored)
├── docs/ # Architecture notes
├── .env.example # Environment variable reference
├── .mcp.json # MCP server config for Claude Code
└── package.json # fire-tracker v1.1.0
Architecture — docs/diagrams/architecture.svg · source docs/diagrams/architecture.mmd
Projection dataflow — docs/diagrams/projection-dataflow.svg · source docs/diagrams/projection-dataflow.mmd
Asset allocation drill down — docs/screenshots/asset-allocation-drill-down.png
Bull bear scenario bands — docs/screenshots/bull-bear-scenario-bands.png
Fee calculator — docs/screenshots/fee-calculator.png
Financial overview tab — docs/screenshots/financial-overview-tab.png
Growth presets — docs/screenshots/growth-presets.png
Header summary bar — docs/screenshots/header-summary-bar.png
Income logs — docs/screenshots/income-logs.png
Insights tab — docs/screenshots/insights-tab.png
Mobile responsive layout — docs/screenshots/mobile-responsive-layout.png
P l table — docs/screenshots/p-l-table.png
Privacy modal — docs/screenshots/privacy-modal.png
Projection engine — docs/screenshots/projection-engine.png
Responsive navigation — docs/screenshots/responsive-navigation.png
# Run tests inside Docker
docker compose exec fire npm test
# Run tests with coverage
docker compose exec fire npm run test:coverage
# Lint
docker compose exec fire npm run lint
# Real-browser UI tests (Playwright, in Docker)
docker build -f config/Dockerfile.playwright -t fire-playwright-e2e .
docker run --rm fire-playwright-e2e
# Nightly user journeys (visual baselines; see tests/journeys/README.md)
docker run --rm -e CI=true fire-playwright-e2e npm run test:journeys
The journeys also run every night in GitHub Actions. A failure opens a deduplicated bot:journey issue with screenshots, and the issue closes itself after three green nights. Open bot issues are listed in BUGS.md.
The system is being productionized toward real-time, API-driven data in four phases. All planned connections are opt-in, need user-provided credentials only where the provider issues them, and are read-only with respect to external accounts.
| Integration | Phase | Status |
|---|---|---|
| eBay Order API (auto-import sales) | Phase 1 | Live (user-provided credentials) |
| Etsy Open API v3 receipts (OAuth PKCE, self-hosted + hosted) | Phase 1 | Implemented (user-provided keystring); unit/route-tested against a mocked Etsy, live shop run pending |
| Mercari / Poshmark / FB Marketplace sales CSV import | Phase 1 | Live (browser-side; assumed export columns documented in docs/integrations.md) |
| Web3 wallet tracking (ETH, BTC, SOL, + EVM chains) | Phase 1 | Live (user-provided keys per chain) |
| Crypto account multichain value (ENS/0x, 7 EVM chains, tokens) | Phase 1 | Live (keyless: Blockscout + public RPCs) |
| CoinTracker wallets (read-only MCP) | Phase 1 | Implemented; blocked until CoinTracker enables MCP early access for the account |
| Google Drive encrypted backup | Phase 1 | Implemented self-hosted and on the hosted deploy (netlify/functions/gdrive-backup.mjs) via Google OAuth; success reported only after a verified read-back (#215); live round trip verified on the hosted deploy (2026-10-14) and self-hosted (2026-10-15) |
Vehicle value API (NHTSA VIN free; paid providers via VEHICLE_VALUE_PROVIDER) | Phase 1 | Live |
| Fidelity / Plaid positions + balance sync | Phase 2 | Live (user-provided credentials; sandbox ready) |
| Plaid on Netlify (hosted) | Phase 2 | Hosted only — endpoints route to netlify/functions/plaid.mjs at /api/sync/plaid/* (see docs/integrations.md); unit- and route-tested, live Link → sync run against the hosted deploy still pending |
| Stable stock quote API (Alpha Vantage / Polygon.io) | Phase 2 | Live (fallback: Yahoo Finance) |
| Rate limiting (300/min general, 30/min sync) | Phase 3 | Live |
| Security headers (CSP, X-Frame-Options, Referrer-Policy) |
See docs/prod-plan.md for the full productionization roadmap and docs/integrations.md for per-integration setup instructions.
Every committed Markdown doc in this repo (other than this README, .github/ and templates/), the same set mirrored into the Obsidian vault, so none of them is orphaned.
docs/
docs/CHANGELOG.mddocs/FEATURES.mddocs/METRICS.mddocs/ROADMAP.mddocs/TASKS.mddocs/backend-sync-architecture.mddocs/integrations.mddocs/privacy-policy.mddocs/prod-plan.mddocs/security-hardening.mddocs/weekly-checkin-prompt.mddocs/archive/
docs/archive/fire-feedback.mddocs/archive/fire-plan.mdpromo/
promo/README.mdpromo/brag-22s/
promo/brag-22s/storyboard.mdpromo/chaos-24s/
promo/chaos-24s/storyboard.mdpromo/
promo/features.mdskills/
skills/README.mdskills/fire-coach/SKILL.mdskills/fire-coach/references/app-guide.mdskills/fire-coach/references/financial-playbook.mdskills/reseller-autopilot/SKILL.mdskills/reseller-autopilot/references/platform-fees.mdskills/reseller-autopilot/references/listing-playbook.mdskills/passive-income-lab/SKILL.mdskills/passive-income-lab/references/streams.mdskills/passive-income-lab/references/fire-math.mdFIRE_API_KEY header auth required by default (opt out with FIRE_AUTH_DISABLED=true for local-only use); FIRE_ADMIN_KEY-gated key-rotation endpointapp/mcp-server.mjsGET /api/prices/stream) for live push; configurable via ALPHA_VANTAGE_API_KEY or POLYGON_API_KEY as stable alternativesPOST /api/sync/webhook/:templateId)GET /api/sync/ebay/authorize → callback → POST /api/sync/ebay/sync) auto-imports completed sales into the side gig ledger; includes the Marketplace Account Deletion endpoint eBay requires (/api/sync/ebay/marketplace-account-deletion, see docs/integrations.md)transactions_r shops_r): Connect Etsy in the Side Hustle Hub (or Settings → Marketplace Connections) pulls paid shop receipts into the ledger, deduplicated by receipt ID, with fees estimated from Etsy's schedule and tax tags left for you. Works self-hosted and on the hosted deploy (see docs/integrations.md)POST /api/sync/plaid/*); manual CSV import is disabled while Plaid sync is active. Connector controls live in Settings/api/wallets) with on-chain balance refresh; supports ETH/EVM, BTC, SOL, BNB, Polygon, Arbitrum, Base, AvalanchePOST /api/backup/drive, GET /api/backup/drive/list, POST /api/backup/drive/restore (requires GDRIVE_CLIENT_ID + GDRIVE_CLIENT_SECRET for Google OAuth, and a 64-hex SYNC_MASTER_KEY)GET /api/vehicles/vin/:vin) and value refresh (POST /api/vehicles/:id/refresh-value)express-rate-limit)https://localhost); the app port binds to loopback only/api/* routes return JSON 404s, and the browser's fetchJson helper reports non-JSON responses clearly instead of throwing parse errorsMETALS_API_KEY | Optional metals.dev key for gold/silver spot; without it the free Yahoo futures fallback (GC=F / SI=F) is used |
ETHERSCAN_API_KEY | Ethereum / ERC-20 balance fetching |
BSCSCAN_API_KEY / POLYGONSCAN_API_KEY / ARBISCAN_API_KEY / BASESCAN_API_KEY | EVM chain balance fetching |
COINGECKO_API_KEY | Optional; raises CoinGecko rate limit for crypto price lookups |
GDRIVE_CLIENT_ID / GDRIVE_CLIENT_SECRET | Google OAuth 2.0 Web application credentials for Drive backup |
GDRIVE_REDIRECT_URI | Optional OAuth callback override; defaults to /api/backup/drive/callback on the local server |
GDRIVE_BACKUP_FOLDER_ID | Optional Drive folder ID; otherwise fire-tracker-backups is created/located automatically |
VEHICLE_VALUE_API_KEY / VEHICLE_VALUE_PROVIDER | Paid vehicle value provider (dataone, marketcheck) |
PLAID_CLIENT_ID / PLAID_SECRET | Plaid credentials for brokerage/bank sync |
PLAID_ENV | sandbox (default) or production |
ALPHA_VANTAGE_API_KEY / POLYGON_API_KEY | Stable stock-quote API alternative to Yahoo Finance |
| Phase 3 |
| Live |
| HTTPS via Caddy reverse proxy | Phase 3 | Live |
| Plaid transaction sync → Expenses | Phase 2 | Live (user-provided credentials; verified against mocked API) |
| eBay Marketplace Account Deletion endpoint | Phase 1 | Live — needs a public HTTPS URL registered in the eBay Developer Portal |
| Precious-metals spot pricing | Phase 2 | Live (free fallback; optional metals.dev key) |