Open Source · MIT Licensed

One AI subscription.
Mixed use, auto-attributed.

You use ChatGPT for work emails and personal recipes. Claude for client code and weekend projects. Stop paying for separate personal and business accounts. LedgerLLM routes every API call through a proxy, classifies each one as personal or business, and shows you exactly what's deductible — with one subscription, one API key, one bill.

$240/yr saved by dropping your second ChatGPT subscription
99.8% of AI spend is business — automatically classified
$0.042 per 1M tokens — Jev classification cost
$0 infra cost — runs on your machine

The problem

You're paying twice

ChatGPT Plus for personal use ($20/mo). ChatGPT Team for work ($25/user/mo). Claude Pro for personal ($20/mo). Claude Team for work ($30/user/mo). You're paying for the same models twice — just to separate personal from business.

You can't prove the split

Even if you use one account for everything, how do you prove to the IRS that 80% of your AI spend was business? You can't. So you either overpay for a separate business account, or you lose the deduction entirely.

Manual tracking doesn't scale

Spreadsheets. Notepad. "Was that prompt about the client or about dinner?" Every API call is mixed use — you can't manually tag hundreds of interactions per month. It's either too much work or too inaccurate to defend.

The solution

1

One proxy, all your tools

Route every AI client — Cursor, Claude Desktop, Hermes, any OpenAI-compatible tool — through a single LiteLLM proxy. One set of API keys, one bill, one source of truth. No more juggling personal vs work accounts.

2

Auto-classify every call

Each API call is classified as personal, business, or mixed by Jev AI — automatically, in the background, no manual tagging. You get a confidence score, business probability, and deductible probability under IRC §162.

3

See the split in real time

A local dashboard shows spend by provider, project, and tax category. You see exactly what percentage is business, what's deductible, and what's personal. Filter by project, export for Schedule C, or just check the numbers.

4

Deduct with confidence

Export a year-end report with deductible total, interaction count, and per-project breakdown. Every classification has a confidence score and an audit trail. Defensible documentation, not a guess.

How much could you save?

Duplicate subscriptions
ChatGPT Plus ($20/mo) + ChatGPT Team ($25/mo) = $45/mo — you only need one − $540/yr on duplicate subscriptions
Tax deduction
$360/yr AI spend × 80% business use = $288 deductible × 24% effective rate + $69/yr in tax savings
LedgerLLM cost
Jev API: ~$0.03/mo · Infra: $0 (self-hosted) Time: ~15 min setup Total: ~$0.36/yr
Net annual savings
~$609/yr by consolidating to one subscription + claiming the deduction

Example assumes $30/mo AI spend, 80% business use, 24% effective tax rate (CA single filer). Actual savings vary. Not tax advice — consult a CPA.

Features

Everything you need to use one AI subscription for both personal and business — and prove the split for taxes.

Automatic Spend Capture

LiteLLM proxy logs every API call — model, tokens in/out, dollar cost — to Postgres. No manual tracking, no spreadsheets. Just route your AI traffic through the proxy.

Jev Tax Classification

Each interaction is classified as personal, business, or mixed by Jev — with business score, deductible probability, and confidence. Fail-closed: errors default to personal (never business).

Project Keyword Routing

Define projects with keywords in config.yaml. Prompts are matched automatically — first match wins, case-insensitive. Or toggle to strict mode and let Jev handle project attribution contextually.

MCP Server (24 Tools)

Expose spend tracking as MCP tools for any AI client. Classify interactions, query reports, manage projects, export tax data — all from Claude Desktop, Cursor, Hermes, or any MCP-compatible client.

Spend Dashboard

Local FastAPI dashboard (port 8092) with CSS charts — no Chart.js dependency. Four tabs: Overview, Tax Breakdown, Projects, Providers. Light/dark theme, reads SQLite read-only.

Tax Report Export

Generate year-end reports for Schedule C. Export deductible total, interaction count, provider breakdown, and project spend. Includes disclaimer: not tax advice — consult a CPA.

Routing Strategy Toggle

Switch between hybrid (keywords first, Jev fallback), strict (always Jev for both tax + project), or keyword (free, no Jev). Toggle live via MCP without restarting the server. Cache clears instantly.

Data Sovereignty

Everything runs on your machine. SQLite at ~/.jev-ai-tracker/attribution.db, Postgres in Docker, LiteLLM bound to 127.0.0.1. No data leaves your network except the 500-char Jev API call (which can be PII-redacted).

Dual Transport MCP

stdio for local AI clients (Claude Desktop, Hermes, Cursor) — zero network, instant startup. SSE/HTTP for Docker-based or remote setups. Same 24 tools, same interface, your choice of transport.

Supported Providers

LiteLLM routes to 100+ providers. LedgerLLM ships with pricing for these models out of the box:

OpenAI GPT-5.6 Sol, GPT-5.6 Terra, GPT-5.6 Luna, GPT-5, GPT-5 Mini, GPT-5 Nano, GPT-6 Astra
Anthropic Claude Opus 5, Opus 5.5, Sonnet 5, Sonnet 5.5, Haiku 5
Google Gemini 3.1 Pro, 3.1 Flash, 3.0 Pro
xAI Grok 4.5, Grok 4
TypeSafe Jev (classification engine, $0.042/M tokens)
Local Ollama models (GLM-5.2, Llama-4, Qwen-3.6) — $0/token, hardware cost only

Quick Start

From zero to a working spend tracker in ~15 minutes. Requires Docker + Python 3.10+.

1

Clone & install

bash
git clone https://github.com/clance1/ledgerllm.git
cd ledgerllm
pip install -e .
2

Configure LiteLLM proxy

bash
cd litellm/
cp .env.example .env       # Fill in OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
cp config.example.yaml config.yaml
# Ensure store_prompts_in_spend_logs: true in config.yaml
docker compose up -d
3

Configure LedgerLLM

bash
cd ..
cp config.example.yaml config.yaml    # Define your projects + keywords
export LITELLM_MASTER_KEY=$(grep LITELLM_MASTER_KEY litellm/.env | cut -d= -f2)
export JEV_API_KEY=apikey_...           # Get one at https://docs.typesafe.ai
export JEV_MODE=dual
4

Initialize & verify

bash
jev-ai-tracker init      # Checks config, LiteLLM, provider keys, inits DB
jev-ai-tracker test       # Test each provider API key
jev-ai-tracker classify   # Pull spend logs + classify
jev-ai-tracker report     # View monthly report
5

Start the dashboard

bash
jev-ai-tracker dashboard   # FastAPI on 127.0.0.1:8092 (Docker)
# Open http://127.0.0.1:8092 in your browser
6

Add MCP to your AI client

Use mcp-stdio for local clients (recommended). Use mcp for Docker SSE.

Claude Desktop — claude_desktop_config.json
{
    "mcpServers": {
        "ledgerllm": {
            "command": "jev-ai-tracker",
            "args": ["mcp-stdio"],
            "env": {
                "JEV_API_KEY": "apikey_...",
                "LITELLM_MASTER_KEY": "sk-...",
                "JEV_MODE": "dual"
            }
        }
    }
}

Daily classification (optional cron)

crontab
# Classify new spend every night at 11 PM
0 23 * * * cd /path/to/ledgerllm && LITELLM_MASTER_KEY=sk-... JEV_API_KEY=apikey_... jev-ai-tracker classify

Documentation

Architecture, CLI reference, MCP tools, and the cloud roadmap.

Architecture

AI Client Cursor, Claude, Hermes LiteLLM Proxy :4000 · logs model, tokens, cost Provider API OpenAI, Anthropic, Gemini Postgres :5432 · spend logs spend logs LedgerLLM Classifier Jev + keyword routing Jev API api.typesafe.ai · $0.042/M pulls classify SQLite attribution.db stores Dashboard :8092 · FastAPI + Jinja2 MCP Server :8090 SSE or stdio · 24 tools CLI classify, report, status reads from SQLite
Core LedgerLLM components Your infrastructure External API

CLI Reference

jev-ai-tracker init Guided setup — checks config, env, LiteLLM, provider keys, inits DB
jev-ai-tracker setup Initialize SQLite database
jev-ai-tracker classify Pull spend logs from LiteLLM, classify with Jev + keywords
jev-ai-tracker report Generate monthly report (tax + project breakdown)
jev-ai-tracker status Database status, unclassified count, mode, routing strategy
jev-ai-tracker test Test each provider API key (OpenAI, Anthropic, Gemini, xAI, Jev)
jev-ai-tracker mcp Start MCP server in Docker (SSE transport, :8090)
jev-ai-tracker mcp-stdio Start MCP server locally (stdio, no Docker — recommended)
jev-ai-tracker dashboard Start spend dashboard in Docker (FastAPI, :8092)

MCP Tools (24)

Classification

  • classify_interaction — Classify a single AI interaction
  • import_subscription_usage — Import conversation history for classification

Routing Strategy

  • get_routing_strategy — Check current strategy (hybrid/strict/keyword)
  • set_routing_strategy — Toggle strategy at runtime

Tax Reports

  • get_monthly_report — Monthly tax + project breakdown
  • get_deductible_total — Year-to-date deductible spend
  • export_for_tax_filing — Year-end Schedule C export
  • get_spend_summary — Spend by provider + category
  • get_dual_report — Combined tax + project report

Project Management

  • add_project — Add a project with keyword routing
  • list_projects — List all configured projects
  • remove_project — Remove a project
  • get_project_spend — Spend for a specific project
  • get_all_project_spend — Spend across all projects
  • get_unassigned_spend — Spend not routed to any project
  • get_project_monthly_report — Monthly project report

Budgets

  • set_budget — Set a monthly budget for a tax tag
  • set_project_budget — Set a monthly budget for a project

Pricing

  • get_model_pricing_info — Per-million-token pricing for a model
  • list_all_model_pricing — All models grouped by provider
  • compute_token_cost — Compute dollar cost from token counts

Status

  • get_mode — Current mode, routing strategy, and projects
  • get_status — DB status, unclassified count, version
  • get_available_models — Models available through LiteLLM

Routing Strategies

hybrid default

Keyword routing first (free, deterministic). If no keyword matches, Jev handles project attribution as an additional question in the same API call. Best balance of cost and accuracy.

Cost: same as dual mode — Jev is already called for tax

strict

Always use Jev for both tax classification AND project attribution. Skip keyword routing entirely. Highest accuracy — Jev understands context, not just word matching.

Cost: ~$0.042/M tokens per call (every interaction)

keyword

Keyword routing only, no Jev for project attribution. Free, fully deterministic. Unmatched interactions get no project routing. Jev may still run for tax classification if JEV_MODE=dual.

Cost: $0 for project routing (Jev only for tax if dual mode)

Configuration

config.yaml
mode: dual  # Set via JEV_MODE env var: "tax", "project", or "dual"

projects:
  - name: poker-tracker
    keywords: [poker, tracker, fastapi]
    tax_category: business
    description: "Poker tracker app"

  - name: cocktail-rating-app
    keywords: [cocktail, rating, react, expo]
    tax_category: business
    description: "Cocktail rating app"

  - name: homelab
    keywords: [docker, homelab, opnsense, tailscale]
    tax_category: business
    description: "Homelab infrastructure"

Environment Variables

JEV_API_KEY Required for tax/dual mode. Get at docs.typesafe.ai
LITELLM_MASTER_KEY Required. LiteLLM proxy admin key
JEV_MODE dual (default), tax, or project
ROUTING_STRATEGY hybrid (default), strict, or keyword
LITELLM_API_URL Default: http://127.0.0.1:4000
MCP_TRANSPORT stdio (default) or sse
ATTRIBUTION_DB_PATH Default: ~/.jev-ai-tracker/attribution.db

Cloud Roadmap

LedgerLLM Cloud is in production. The cloud version will be a managed LiteLLM proxy — users point their AI client at ledgerllm.dev/v1/, add provider API keys once via the dashboard, and every call is automatically proxied, logged, classified, and visible in a real-time dashboard.

  • Managed LiteLLM proxy with per-tenant virtual keys
  • Multi-tenant Postgres with Row-Level Security (RLS)
  • KMS-encrypted provider key storage
  • PII redaction before Jev API calls
  • 30-day retention with auto-purge
  • Stripe billing (Free / Solo $12/mo / Pro $39/mo / Enterprise)
  • SOC 2 compliance (when enterprise demand justifies)

The OSS version is the foundation — same engine, same MCP tools, same Jev classification. The cloud adds zero-config setup, automatic capture, and a hosted dashboard. Users who want data sovereignty stay on the self-hosted version.

Security Principles

LedgerLLM is designed with security and data sovereignty as first principles. Here's how data flows, what's protected, and what you control.

Data Flow

Local

LiteLLM Proxy & Postgres

Every API call routes through LiteLLM on 127.0.0.1:4000. Spend logs (model, tokens, cost, prompt content) are stored in Postgres on 127.0.0.1:5432. Both are bound to localhost — no remote access.

Local

SQLite Attribution DB

Classification results and project routing are stored in ~/.jev-ai-tracker/attribution.db. File permissions set to 0600 (owner-only). The dashboard reads this file in read-only mode (mode=ro).

External

Jev API (TypeSafe AI)

The first 500 characters of each prompt are sent to api.typesafe.ai for classification. Jev does not store request bodies. Content is forwarded to TypeSafe AI's upstream model for processing but not for training. PII redaction is recommended before transmission.

External

Provider APIs

Your provider API keys (OpenAI, Anthropic, etc.) are stored in litellm/.env (gitignored). LiteLLM uses them to route calls to the correct provider. Keys are never logged, never displayed in the dashboard, and never sent to Jev.

Principles

Fail-Closed Classification

All Jev API parse errors, timeouts, and edge cases default to personal (non-deductible) — never business. A confidence threshold of 0.25 filters low-confidence business classifications down to personal. Conservative by design: better to miss a deduction than to overclaim one.

Data Sovereignty

Everything runs on your machine. SQLite, Postgres, LiteLLM, dashboard — all local. The only data that leaves your network is the 500-char Jev API call. No telemetry, no analytics, no phone-home. Your spend data never touches a server you don't control.

Localhost-Only Binding

LiteLLM binds to 127.0.0.1:4000. Postgres binds to 127.0.0.1:5432. Dashboard binds to 127.0.0.1:8092. MCP server binds to 127.0.0.1:8090. No service is exposed to the network by default. To capture from other devices, bind to your Tailscale IP explicitly.

Secrets Hygiene

All .env files are gitignored. config.yaml (with project keywords) is gitignored. *.db files are gitignored. API keys use os.environ/ references in LiteLLM config (not hardcoded). No secrets in tracked source files.

Prompt Logging is Opt-In

store_prompts_in_spend_logs: true is required in LiteLLM config for prompt content to be stored. Without it, only model + tokens + cost are logged — no prompt text. The Jev classifier degrades gracefully to keyword-only routing when prompts aren't available.

PII Redaction (Recommended)

Before sending prompt content to Jev, a regex-based PII redaction function strips API keys (sk-...), email addresses, phone numbers, bearer tokens, and AWS keys. The 500-char limit provides data minimization. Full redaction is a 20-line addition — see the security review.

No Prompt Snippets in Dashboard

The prompt_snippet column exists in the SQLite database (for classification), but the dashboard never displays it in charts, tables, or any UI element. This is a hard rule — enforced in the FastAPI routes that serve dashboard data.

MIT Licensed, Auditable

The entire codebase is MIT licensed and open source. Every line is auditable. No obfuscated binaries, no telemetry SDKs, no closed-source dependencies beyond the Jev API call (which you can disable with JEV_MODE=project).

Known Limitations

Closed-app AI clients can't be proxied. Claude iOS, ChatGPT mobile, and Claude.ai/ChatGPT.com web interfaces go directly to the provider — no custom endpoint setting. Only AI clients that support custom OpenAI-compatible base URLs (Cursor, Hermes, Claude Desktop, CLI tools) can route through LiteLLM.
No encryption at rest for SQLite. The attribution database is a plain SQLite file with 0600 permissions. For encrypted storage, consider SQLCipher. The Postgres spend logs are also unencrypted (standard postgres:16 image).
Jev API is a third-party processor. Under CCPA, Jev/TypeSafe AI is a service provider. A Data Processing Agreement (DPA) should be established. Zero Data Retention (ZDR) is available for enterprise customers.
Classification is probabilistic, not legal advice. Jev returns a confidence score and business probability. The tool generates a tax-ready report, but it is not tax advice. Consult a CPA for actual filing decisions.

Cloud Security (Future)

When the cloud version launches, it will add these security measures on top of the OSS foundation:

  • KMS-encrypted provider key storage — envelope encryption via AWS/GCP KMS, not a static salt key
  • Row-Level Security (RLS) — every Postgres table scoped by tenant_id, enforced at the database level
  • TLS 1.2+ on all endpoints — MCP over Streamable HTTP with Bearer auth
  • 30-day retention with auto-purge — prompt content auto-deleted after 30 days
  • Audit logging — every data access logged with timestamp, user ID, action
  • Privacy policy + subprocessor list — CCPA/CPRA compliant from day one
  • SOC 2 — pursued when enterprise demand justifies the audit cost