BURNLENSDashboard

security · privacy · data flow

What BurnLens sees, what it never sends

Local-first by design · Apache-2.0 · cloud sync is opt-in and body-free

The short version

BurnLens is a proxy that runs on your machine. Your AI SDK talks to localhost:8420; BurnLens forwards the call to OpenAI, Anthropic, or Google; the response comes back unmodified. Cost calculation and logging happen locally, against a SQLite database at ~/.burnlens/burnlens.db.

Prompts and responses never leave your machine. If you choose to enable cloud sync for a team dashboard, BurnLens uploads only anonymized counts, costs, and hashes — never the bodies of requests or responses.

What stays on your machine, always

  • The full request body sent to the upstream provider (prompts, messages, tool definitions, attachments)
  • The full response body returned by the provider (model output, tool calls)
  • Your provider API keys — BurnLens passes them through; it does not store them
  • SQLite database at ~/.burnlens/burnlens.db (rows include token counts, cost, model, tags, and a SHA-256 hash of the system prompt; not the prompt text)
  • Any data burnlens scan reads from your local coding-agent log directories (~/.claude/projects/, Cursor bubble DB, Codex SQLite, ~/.gemini/tmp/)

What BurnLens strips before forwarding to the provider

Every request header starting with X-BurnLens- is removed before BurnLens forwards the call upstream. That means tag headers like X-BurnLens-Tag-Feature: checkout are visible to your local BurnLens instance but never sent to OpenAI / Anthropic / Google. Your Authorization header and request body pass through byte-for-byte.

Source: burnlens/proxy/interceptor.py (_clean_request_headers).

What cloud sync uploads (opt-in)

If — and only if — you run burnlens login and configure a bl_live_xxx API key, the background sync client batches local cost rows and posts them to api.burnlens.app/v1/ingest every 60 seconds. Each row in the batch is exactly these fields:

FieldWhy we need it
timestampOrder requests on the timeline
provideropenai / anthropic / google / etc.
modelPrice lookup and per-model rollups
input_tokens / output_tokens / reasoning_tokensCost math
cache_read_tokens / cache_write_tokensCache efficiency rollups
cost_usdAlready-computed cost (you don't have to trust ours)
duration_msLatency rollups
status_codeError-rate rollups
system_prompt_hash (SHA-256)Duplicate-system-prompt detection
tag_feature / tag_team / tag_customerOptional rollup dimensions you opted into

Source: burnlens/cloud/sync.py (_row_to_payload) — this is the entire upload schema. There is no other code path that ships data to the cloud backend.

What cloud sync never uploads

  • Request body (prompts, messages, tool definitions, attachments)
  • Response body (model output, tool calls, citations)
  • Streaming chunks
  • Provider API keys or auth headers
  • File paths, repo names, branch names — unless you explicitly pass them as tag values
  • Local environment variables outside of BURNLENS_TAG_* opt-ins

The sync function has no parameter for them. To send a prompt body to the cloud, you would have to fork BurnLens and add a field — which is to say, the privacy guarantee is a structural property of the code, not a policy promise.

Tags: what you choose to attach

Tag values you set (via X-BurnLens-Tag-Feature: checkout or BURNLENS_TAG_TEAM=payments) areuploaded by cloud sync — they are the rollup dimensions for the team dashboard. Treat tag values like log labels: don't put PII or secrets in them. The supported tag keys are feature, team, and customer; everything else stays in the local database but is not forwarded to the cloud.

Running entirely offline

Cloud sync is opt-in. If you never run burnlens login:

  • No API key is configured
  • The sync background task never starts
  • No outbound connection to api.burnlens.app is ever opened
  • The local dashboard at localhost:8420/ui, CLI commands (top, report, scan, analyze), and SQLite database all work normally

License and source

The proxy, CLI, dashboard, scan readers, and cost engine are Apache-2.0. You can audit, fork, self-host, or run BurnLens entirely offline. Source on GitHub. The cloud ingest backend that receives opt-in sync batches is not open source — it is a managed service for the hosted dashboard at burnlens.app.

Reporting a vulnerability

Please email security@burnlens.app with details and a proof of concept. We aim to acknowledge within 2 business days. Please do not file public GitHub issues for security reports.

FAQ

Does BurnLens see my prompts? BurnLens reads the request body locally to extract the model name and to forward it to the provider. Prompt content is written only to the local SQLite database. Cloud sync, if enabled, uploads counts and hashes — never prompt text.

Can the BurnLens cloud see who my customers are? Only if you put customer identifiers into the X-BurnLens-Tag-Customer header. By default, no customer data is in any field that gets uploaded.

What about provider API keys? They live in your environment and are forwarded in the Authorization header upstream. BurnLens does not log, persist, or upload them.

Is BurnLens SOC 2 / HIPAA / ISO 27001 certified? Not today. The hosted backend follows standard cloud-security practices (encrypted transport, scoped API keys, principle of least privilege). For regulated workloads, run BurnLens self-hosted with cloud sync disabled — that keeps every byte of LLM traffic inside your own infrastructure.

Related

Privacy Policy · Terms & Conditions · burnlens scan · Back to homepage