Using Bellamente

Connect any OpenAI-compatible client

Change one base URL. Bellamente sits between your client and your local model server (Ollama, LM Studio, llama.cpp, vLLM — anything speaking /v1/chat/completions):

# your client talks to Bellamente...
OPENAI_BASE_URL=http://127.0.0.1:8080/v1
# ...Bellamente talks to your model (default: http://127.0.0.1:11434/v1, i.e. Ollama)
BELLA_UPSTREAM_BASE_URL=http://127.0.0.1:11434/v1

On every chat turn the proxy offers your model a searchMemory tool, runs the recall locally when the model calls it, re-invokes your model with the results, and returns only the final answer — on buffered and streamed chats alike. The response headers tell you what happened (x-bella-memory-round: true means memory grounded that answer).

Give a coding agent memory today

Agents that read project instructions (Claude Code, Cursor, Codex, etc.) can use Bellamente directly over HTTP — paste this into your agent’s instructions:

This machine runs Bellamente, a local memory service, at http://127.0.0.1:8080 (no auth on localhost).
- To REMEMBER a durable fact: POST /memories with JSON {"memories":[{"content":"<the fact>"}]}
- To RECALL: POST /search with JSON {"q":"<what you need to know>"} — results include content and a similarity score.
- Recall before starting work on a topic; remember stable facts (preferences, decisions, environment details) when you learn them.
- NEVER store secrets — API keys, passwords, tokens, private keys, or credentials. Use your judgment; if a fact contains a secret, leave the secret out.
- Every response returns an x-bella-trace-id header; the human can audit any recall at http://127.0.0.1:8080/.

Give an MCP-native agent memory directly

Agents that speak MCP (Claude Desktop, Claude Code, Cursor, Cline, Codex) can use Bellamente as a native tool server — no HTTP glue, no copy-pasted prompt:

claude mcp add bellamente -- bella mcp

bella mcp speaks JSON-RPC over stdio and exposes nine tools on the SAME local memory store bella serve uses (no second database, no separate write path): memory_search, memory_write, memory_correct (change a specific memory by id, recording a new version), memory_forget (reversible soft-forget only — it never hard-deletes), memory_list, memory_history (a memory’s full version chain, forgotten versions included — the inspect-and-trust view), document_ingest, document_list, and trace_inspect. Every search is recorded as a recall trace you can read back with trace_inspect (optionally filtered by kind), exactly like the dashboard’s Traces view.

Measure retrieval quality

Run the deterministic E2E benchmark from the repo root:

bun run bench

It loads fixtures through POST /memories and POST /documents, queries POST /search in memories, documents, and hybrid modes, then reports recall@1/5/10, MRR, p50/p95 latency, and route-vector-vs-brute-force recall. The default run uses embedder=deterministic-hash so it measures the retrieval pipeline reproducibly. At this fixture size PGlite does not engage HNSW, so the vector comparison is an exact-vs-route delta; the 50k-row P1.5/#39 probe is where real ANN-loss behavior is measured. Set BELLA_EVAL_REAL_EMBED=1 to use the active local embedder. Latest checked deterministic run (seed=20260702, 110 queries): memories R@1/R@10/MRR 84.1%/100.0%/0.920, documents 100.0%/100.0%/1.000, hybrid 100.0%/100.0%/1.000, exact-vs-route delta@10 0.0%. Hybrid recall is an any-gold hit across the paired memory/document golds; the document and hybrid rows are deterministic ceiling checks, not a broad claim about every document corpus.

Your memory is a file

curl localhost:8080/export > bellamente-backup.json — chains, validity windows, forgotten flags, profiles, and documents in one portable JSON. Restore anywhere with curl -X POST localhost:8080/import -H 'content-type: application/json' -d @bellamente-backup.json; embeddings regenerate locally on the way in, so the same file works across machines and embedder tiers. Re-importing is a safe no-op.

Auto-capture: it remembers for you

After each answered chat turn, Bellamente conservatively captures durable first-person facts (“I prefer metric units”) through the same dedup path as manual writes. A small LLM pass through your own local model distills facts (never a cloud call); regex heuristics are the fallback.

  • Credentials, financial IDs, and medical disclosures are excluded and never stored — and the filter is re-applied to everything the LLM extracts.
  • Every capture is traced and reversible; captured memories are marked is_inference so they are forever distinguishable from things you stored deliberately.
  • Kill switches: BELLA_PROXY_CAPTURE=0 (capture off), BELLA_CAPTURE_DISTILL=0 (heuristics only).

Secrets are never stored

Bellamente is used by intelligent agents, so the first line of defense is the agent itself: the MCP tool descriptions and the HTTP agent-instructions above tell the calling agent to use its judgment and never store secrets. That’s where the real intelligence lives — the agent understands what’s sensitive.

As a deterministic backstop for when an agent slips, every memory write — manual POST /memories, MCP memory_write, batch, corrections, and auto-capture — also passes through a credential gate before it is embedded or stored. Detected credentials are stripped from the memory content and its structured metadata and replaced with a [redacted: <kind>] marker; the raw value never reaches the store. The gate works two ways:

  • Known formats (zero false positives): private keys (PEM blocks), AWS access keys, GitHub / GitLab tokens, Slack tokens, Stripe live keys, npm / HuggingFace tokens, and OpenAI / Anthropic / Google API keys.
  • Labeled values (provider-agnostic): any value explicitly labeled as a secret — api key = …, token: …, AUTH_TOKEN=…, the password is … — is redacted whatever the provider, because it keys on the label, not the format. (The value must look like a token, so English like “the password is required” is left alone.)

The surrounding context survives ("prod key is [redacted: OpenAI API key], in vault X"), and the API/MCP response reports what was redacted. On the auto-capture path, the local distillation model is additionally asked to drop credentials outright.

Honest limits — this is deliberate. A secret is defined by intent, not shape, so no deterministic gate catches everything: a bare, unlabeled random token, or a password that is an ordinary word, can slip through. We deliberately do not use high-entropy heuristics — they would shred the git SHAs, UUIDs, and base64 blobs you legitimately store, and worst of all on auto-capture, which writes silently. The gate is tuned to not eat real developer memories: documented placeholders like AWS AKIAIOSFODNN7EXAMPLE, sk_test_ keys, JWTs, and git SHAs are left alone. Storing a real credential deliberately? Send allowSecrets: true on that write.

The dashboard

Open http://127.0.0.1:8080/ in a browser. Three views:

  • Traces — every search/proxy/capture event: what was retrieved, scores, latency, what was injected into the model.
  • Search — a recall playground with the same knobs the API has.
  • Memory — browse, edit (creates a new version), forget (reversible), delete, and view the full version history of every memory.

Nothing is silently overwritten: edits version, forgetting is auditable, hard delete says what it takes with it.

Report a bug — bella report

When something breaks, bella report assembles a bug report for you — but it opens nothing and sends nothing. It prints a content-free summary and a prefilled GitHub issues/new link; you review exactly what will be shared, then click submit on GitHub yourself. Consistent with “never phones home”, the binary transmits nothing.

bella report

What the report contains: version, OS, the embedder tier/model, disk + storage sizes, and your recent errors grouped by fingerprint — codes and counts only, never messages, stacks, file contents, or conversation text. Storage locations are reduced to directory names + sizes (never the absolute path, which would carry your username), and the database is shown as a mode (embedded/external) — never the connection URL.

If bella mcp or another process is holding the local database, run bella report with it stopped to include the full error list; a running bella serve on localhost is read through its content-free errors endpoint automatically.