Metadata-Version: 2.4
Name: codelore
Version: 0.1.1
Summary: Your codebase's memory. Persistent organizational memory for AI coding agents.
Project-URL: Homepage, https://github.com/Hanishsaini/Lore
Project-URL: Repository, https://github.com/Hanishsaini/Lore
Project-URL: Issues, https://github.com/Hanishsaini/Lore/issues
Author: lore
License: MIT
License-File: LICENSE
Keywords: agent,ai,claude,cursor,knowledge,mcp,memory
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.40
Requires-Dist: gitpython>=3.1.40
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.0
Requires-Dist: numpy>=1.26
Requires-Dist: rich>=13.7
Requires-Dist: sentence-transformers>=3.0
Requires-Dist: sqlite-vec>=0.1.6
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# lore

> **Your codebase's memory.**
> Persistent organizational memory for AI coding agents — so they stop repeating your team's past mistakes.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![MCP Compatible](https://img.shields.io/badge/MCP-compatible-7c3aed)](https://modelcontextprotocol.io)
[![Status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)]()

AI coding agents (Claude Code, Cursor, Codex) can write code. They still don't know **why** your team made the decisions baked into your codebase. So they confidently suggest the exact thing that broke production last quarter.

**lore** ingests your git history, ADRs, and postmortems; extracts the *why*; and serves it back to your agent over MCP — so before it touches code, it can recall:

- what your team has already tried and reverted
- which conventions exist and why
- which postmortems are sitting one mistake away from repeating

---

## The killer demo

```text
You    >  Add Redis caching to the payment endpoint.

Claude > Before I touch this, I checked lore — 3 relevant past decisions:

         1. [revert]      Redis caching reverted on payment writes
            Why:          Stripe webhook race condition caused duplicate charges
            commit a8f3b2c1  ·  2026-03-12

         2. [convention]  No in-memory caching on payment write paths
            Why:           Codifies ADR-014 so new contributors don't reintroduce the bug
            docs/adr/ADR-014.md  ·  2026-04-02

         3. [incident]    Duplicate-charge incident POST-221
            Why:          Stale cache during partial outage
            docs/postmortems/POST-221.md  ·  2026-05-09  ·  severity: high

         Suggested alternative: database query caching
         (see services/orders/cache.py)
```

That output isn't from a chatbot — it's a real MCP tool call that lore exposes to your agent.

---

## Why lore exists

Your AI agent has incredible coverage of:

- syntax
- frameworks
- public APIs
- general code patterns

It has **zero coverage** of the thing that actually matters in a mature codebase:

- *Why* a migration was rolled back two months ago
- *Why* Kafka was rejected in favor of Postgres LISTEN/NOTIFY
- *Why* there's a lint rule banning in-memory caches on `/payments`
- *Why* every onboarding engineer has to be told the same five things in their first week

That gap is where lore lives. The product thesis: **the next breakout layer in AI tooling is persistent organizational reasoning, not better autocomplete.**

---

## How it works

```
    ┌──────────────────┐  ┌─────────────┐  ┌────────────────┐
    │   Git history    │  │ ADRs        │  │ Postmortems    │
    │  (PRs, commits)  │  │ (markdown)  │  │  (markdown)    │
    └────────┬─────────┘  └──────┬──────┘  └────────┬───────┘
             │                   │                  │
             └───────────┬───────┴──────────────────┘
                         ▼
              ┌────────────────────────┐
              │   Signal pre-filter    │   drops ~80% of routine work
              └──────────┬─────────────┘
                         ▼
              ┌────────────────────────┐
              │  Decision extraction   │   LLM (Anthropic | Groq | Gemini | Ollama)
              │  (or heuristic mode)   │   or pattern-based, zero-setup
              └──────────┬─────────────┘
                         ▼
              ┌────────────────────────┐
              │   Embed (bge-small)    │
              └──────────┬─────────────┘
                         ▼
              ┌────────────────────────┐
              │  SQLite + sqlite-vec   │   local-first, your data never leaves
              │     + FTS5 (BM25)      │   your machine unless you choose so
              └──────────┬─────────────┘
                         ▼
              ┌────────────────────────┐
              │   Hybrid retrieval     │   vector ⊕ keyword via RRF,
              │   (RRF + boosts)       │   then source / type / severity / recency
              └──────────┬─────────────┘
                         ▼
              ┌────────────────────────┐
              │      MCP server        │   recall_decision, find_postmortems,
              │     (stdio transport)  │   related_history
              └──────────┬─────────────┘
                         ▼
          Claude Code  ·  Cursor  ·  Codex  ·  any MCP client
```

---

## Install

```bash
pip install codelore
```

> The package is `codelore`; the command it installs is `lore`.

Or from source:

```bash
git clone https://github.com/Hanishsaini/Lore.git
cd Lore
pip install -e .
```

Python 3.11+ required.

---

## Try it in 60 seconds (no API key, no setup)

```bash
pip install codelore
lore demo
```

`lore demo` loads a preloaded memory of a fictional payments platform and answers
the signature question against it — so you can feel the product before pointing it
at your own code. Ask it anything:

```bash
lore demo "why did we drop Kafka?"
lore demo "how should we store money?"
```

(First run downloads a small embedding model, ~80 MB. No LLM or API key needed —
the demo decisions are pre-extracted.)

## Quickstart on your own repo

```bash
cd your-project/
lore init
lore ingest .
lore ask "should I cache payment writes?"
```

That's it. The first run downloads a small embedding model (~80 MB).

### Also ingest ADRs and postmortems

These get **priority** at retrieval time — formal writeups outrank random commit messages.

```bash
lore ingest . --adrs docs/adr --postmortems docs/postmortems
```

---

## Pick an LLM (or none)

lore runs with whatever you have. It auto-detects in this order:

| Provider | Cost | Quality | Setup |
|---|---|---|---|
| **Anthropic Claude** | Paid | Highest | `export ANTHROPIC_API_KEY=…` |
| **Groq** | **Free tier** | High | `export GROQ_API_KEY=…` ([signup, no credit card](https://console.groq.com)) |
| **OpenRouter** | **Free models** | High | `export OPENROUTER_API_KEY=…` ([signup](https://openrouter.ai/keys)) |
| **Google Gemini** | **Free tier** | High | `export GEMINI_API_KEY=…` ([signup](https://aistudio.google.com)) |
| **DeepSeek** | Free credits | High | `export DEEPSEEK_API_KEY=…` ([signup](https://platform.deepseek.com/api_keys)) |
| **NVIDIA NIM** | **Free tier** | High | `export NVIDIA_NIM_API_KEY=…` ([signup](https://build.nvidia.com/settings/api-keys)) |
| **Ollama** (local) | Free | Medium | `ollama serve` + `ollama pull qwen2.5:7b` |
| Heuristic fallback | — | Low | nothing — works out of the box |

**Or skip exports entirely — use a `.env` file:**

lore auto-loads `./.env` (per-repo) and `~/.lore.env` (global) on every run.
Real environment variables always win, so a `.env` never clobbers a shell export.

```bash
cp .env.example ~/.lore.env     # then fill in one key
echo 'GROQ_API_KEY=gsk_...' >> ~/.lore.env
```

`.env` is gitignored by default — your keys never get committed.

**Force a specific provider:**

```bash
export LORE_LLM_PROVIDER=openrouter   # or: anthropic, groq, gemini, deepseek, nvidia, ollama
```

**Override the model on a provider:**

```bash
export LORE_OPENROUTER_MODEL=deepseek/deepseek-chat-v3:free
export LORE_NVIDIA_MODEL=meta/llama-3.3-70b-instruct
export LORE_DEEPSEEK_MODEL=deepseek-chat
export LORE_OLLAMA_MODEL=qwen2.5:14b
```

**Stitch multiple free keys together** (useful when one rate-limits):

```bash
export GROQ_API_KEYS="key1,key2,key3"
# lore rotates through them automatically on 429s
```

The same plural form works for every cloud provider: `ANTHROPIC_API_KEYS`,
`OPENROUTER_API_KEYS`, `GEMINI_API_KEYS`, `DEEPSEEK_API_KEYS`, `NVIDIA_NIM_API_KEYS`.

### Transparent fallback

If the active LLM rate-limits, returns malformed JSON, or hits a network error,
lore falls back to heuristic extraction for that one candidate — and **tells you
about it**. You'll see a stderr warning on the first event plus a per-run
summary at the end of ingestion:

```text
[WARN] 3/127 candidates fell back to heuristics (rate_limit=2, bad_json=1).
Quality on those entries will be lower than the configured LLM.
```

That way you can't accidentally ship a "fully LLM-extracted" memory that
was 40% heuristic without knowing it.

---

## Use with Claude Code

**One command:**

```bash
lore install claude-code
```

That writes (or merges into) `~/.claude/mcp_settings.json` with an entry
pointing at your current directory. Restart Claude Code and you're done.

If you want to manage multiple lore instances (e.g. one per repo), pass
`--name` and `--repo`:

```bash
lore install claude-code --name lore-payments --repo /path/to/payments-service
lore install claude-code --name lore-platform --repo /path/to/platform
```

Prefer to edit the config by hand? Run the server directly:

```bash
lore mcp --repo /abs/path/to/your/project
```

And add to `~/.claude/mcp_settings.json`:

```json
{
  "mcpServers": {
    "lore": {
      "command": "lore",
      "args": ["mcp", "--repo", "/abs/path/to/your/project"]
    }
  }
}
```

Once installed, Claude Code can call:

- `recall_decision(query)` — relevant past decisions for a proposed change
- `find_postmortems(query)` — past incidents touching the same area
- `related_history(query)` — broader context across all decision types

Use with **Cursor** and **Codex** is identical — both speak MCP.

---

## What lore tracks

| `decision_type` | When it surfaces                                            |
|----------------|-------------------------------------------------------------|
| `decision`     | An explicit choice between options                          |
| `revert`       | Something was tried and rolled back                         |
| `convention`   | A team rule (e.g. "no in-memory caching on payments")       |
| `incident`     | A postmortem-worthy event                                   |
| `tradeoff`     | A deliberate compromise future engineers should understand  |

Retrieval is opinionated: **reverts and incidents outrank the decisions they invalidate** when relevance ties. That's the whole point.

---

## Retrieval is hybrid and opinionated

- **Vector** search via `bge-small-en-v1.5` (384-dim, runs locally)
- **BM25** keyword search via SQLite FTS5
- Fused with **Reciprocal Rank Fusion** (k=60)
- Then boosted by:
  - **Source priority:** `postmortem ≈ incident > adr > pr > git_commit > markdown`
  - **Decision type:** `revert ≈ incident > convention > tradeoff > decision`
  - **Severity:** high-severity incidents float up
  - **Recency:** gentle 18-month half-life decay
  - **Extractor confidence**

Tuning lives in [`lore/search.py`](lore/search.py) — every weight is a single constant you can change.

---

## CLI reference

```bash
lore demo ["<question>"]            # try lore on a preloaded memory, no setup
lore init [path]                    # create .lore/memory.db
lore ingest [path] [opts]           # walk git + optional --adrs / --postmortems dirs
lore ask "<question>" [-k 5]        # query the memory
lore status                         # counts by type and source
lore mcp [--repo path]              # run the MCP server (stdio)
lore install claude-code [--repo p] # register lore with Claude Code (writes mcp_settings.json)
lore version
```

---

## Configuration (environment variables)

| Variable | Purpose |
|---|---|
| `ANTHROPIC_API_KEY` / `ANTHROPIC_API_KEYS` | Use Claude for extraction (best quality) |
| `GROQ_API_KEY` / `GROQ_API_KEYS` | Use Groq Llama 3.3 (best free option) |
| `OPENROUTER_API_KEY` / `OPENROUTER_API_KEYS` | Use OpenRouter (gateway to many free models) |
| `GEMINI_API_KEY` / `GEMINI_API_KEYS` | Use Google Gemini (free tier) |
| `DEEPSEEK_API_KEY` / `DEEPSEEK_API_KEYS` | Use DeepSeek chat (free credits) |
| `NVIDIA_NIM_API_KEY` / `NVIDIA_NIM_API_KEYS` | Use NVIDIA NIM (free tier) |
| `OLLAMA_HOST` | Override default `http://localhost:11434` |
| `LORE_OLLAMA_MODEL` | Override default `qwen2.5:7b` |
| `LORE_OPENROUTER_MODEL` | Override default `meta-llama/llama-3.3-70b-instruct:free` |
| `LORE_NVIDIA_MODEL` | Override default `meta/llama-3.3-70b-instruct` |
| `LORE_DEEPSEEK_MODEL` | Override default `deepseek-chat` |
| `LORE_LLM_PROVIDER` | Force `anthropic` \| `groq` \| `openrouter` \| `gemini` \| `deepseek` \| `nvidia` \| `ollama` |

---

## Roadmap

**v0.1 (current)** — git + markdown ingestion, hybrid retrieval, MCP server, four LLM providers, heuristic fallback.

**v0.2 — Launch polish**
- ~~`lore install claude-code` — one-command MCP config writer~~ **[shipped]**
- ~~Surface fallback events so silent quality regressions are visible~~ **[shipped]**
- ~~`lore demo` — preloaded memory so you can feel the magic with zero ingestion~~ **[shipped]**
- ~~`.env` auto-loading so keys don't need re-exporting~~ **[shipped]**
- LLM-extraction quality eval set (golden 50)
- `lore install cursor` / `lore install codex`

**v0.3 — Distribution**
- Linear / Jira / GitHub Discussions connectors
- Slack export ingestion (no auth required at first)
- VS Code extension wrapping the MCP integration

**v0.4 — Team mode**
- Hosted sync of decision graphs across a team
- Shared organizational memory with per-repo scoping

If you're a team that wants `v0.4` early, open an issue.

---

## Status

Pre-alpha. Works end-to-end on real git histories. Quality scales with your extractor (LLM > heuristics) and with how much your team actually writes down.

If `lore ask` returns mediocre results on your codebase, the most common causes (in order):

1. Heuristic-only mode — set any of the API keys above and re-ingest with `--force`.
2. Your team writes one-line commit messages with no rationale. lore can only recall what was once written down.
3. The memory is too small — try ingesting ADRs and postmortems too.

---

## Contributing

PRs welcome. The most valuable contributions right now:

- Connectors for new sources (Notion, Linear, Confluence, etc.)
- Provider plug-ins for additional LLMs (OpenAI, Mistral, OpenRouter)
- Eval datasets — real decision-recall pairs from your own codebase
- IDE / MCP-client integrations

To set up:

```bash
git clone https://github.com/Hanishsaini/Lore.git
cd Lore
python -m venv .venv && source .venv/bin/activate     # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
pytest                                                 # 38 tests, ~1s, no model download
```

Tests are hermetic — store/search tests use synthetic embedding vectors, so the
suite never pulls the embedding model. Ranking invariants (relevance leads,
boosts only break ties) and the `.env`/JSON parsers are all covered.

---

## License

MIT — see [LICENSE](LICENSE).

---

> Built with the conviction that AI coding agents will be the new operating layer for software development — and that the agents who *remember* will quietly outperform the ones who don't.
