lore
Framework-agnostic project memory for AI coding agents.
A long-term knowledge base for software projects, maintained by AI agents. Captures the kind of context that normally lives only in the original developer's head — architecture, decisions, conventions — and persists it as plain Markdown files that any agent can consume.
lore is a SKILL, not a CLI tool. It is a Markdown spec (
SKILL.md) that AI coding agents — Claude Code, Cursor, OpenCode, Cline, Aider, GitHub Copilot — read to gain long-term project memory. You do notnpm installorpip installlore; you give your agent the URL and ask it to install the skill. From then on, phrases likelore initandlore syncare commands you say to your agent, not commands you type in a terminal. There is nolorebinary on yourPATH.
Installation
git clone https://github.com/TheaDust/lore.git <your-agent-skills-dir>
Or, simpler — tell your agent:
Install https://github.com/TheaDust/lore as a skill.
Each agent host loads skills from its own directory (~/.claude/skills/ for Claude Code, <project>/.claude/skills/ for project-scoped, etc.). Your agent knows its own skills directory and can clone the repo into the right place.
Looking for a specific doc? Jump to: Quick start · What it looks like · What lives in
.lore/· Seven workflows · Platform mirrors · Configuration · Upgrading · FAQ. Full reference docs live inreferences/. Want plain-language "when to use each workflow"? SeeWORKFLOWS.md(also in 中文).
What it solves
When you work on a project across multiple AI tools (Claude Code, Cursor, Cline, GitHub Copilot, Aider, LangGraph agents, DeepAgents) and across many sessions, context gets lost:
- Every new session re-explains the project. "We're using Next.js App Router, not Pages. Use Zustand, not Redux. Don't commit secrets."
- Decisions are forgotten. "Why did we pick X over Y?" → "I don't remember, let me ask the team."
- Agents disagree with each other. Cursor follows
.cursorrules, Claude Code followsCLAUDE.md, but the two files drift apart. - Onboarding takes weeks. New members / new agents need to learn the conventions from scratch.
lore maintains a single source of truth (.lore/) and projects it into whatever config files your agents already read. It tracks why decisions were made, not just what the code does, and keeps that history across sessions and tools.
Quick start
The commands below are phrases you say to your agent — there is no lore binary. With this skill loaded, your agent runs each phrase through the workflows defined in SKILL.md and references/workflows.md. Anything you'd normally type into a terminal goes to the agent instead.
# 1. Initialize (run once per project)
lore init
# Walks the project, drafts entries, asks for confirmation, creates .lore/
# 2. After a non-trivial change
lore sync
# Spans commits + uncommitted changes; flags contradictions as ALERT; proposes [NEW]/[STALE]/[REFINED]; waits for your call
# 3. After many changes, refresh the agent-facing summary
lore compress
# Regenerates SUMMARY.md; mirror update depends on `auto_mirror` (default: asks per target)
# 4. Force a mirror refresh (e.g. after hand-editing .lore/)
lore mirror
# Rewrites CLAUDE.md and other platform files from current state
Three read-only commands round out the toolkit:
lore query # Answer a question from memory, cite entry IDs
lore audit # Check memory vs. reality, write report to .lore/audit/
lore history DEC-2026-02-03-7c19 # Show git commits that touched an entry's code
lore history frontend/src/store.ts # ...or a file
lore history --scope=frontend # ...or every lore file in a scope
lore history --json # machine-readable
What this looks like
Querying memory
You: "How does this project authenticate API requests?" Agent (uses
lore query auth):
Found 6 entries matching 'auth':
[_global/DECISIONS.md#DEC-2026-07-10-6d9c]
Opaque base64 tokens over JWT; reason: simpler revocation, no library dep.
[scopes/backend/ARCHITECTURE.md#ARCH-2026-07-10-59ac]
Auth helpers in backend/app/auth.py:
hash_password, issue_token, login_required decorator.
[scopes/backend/CONVENTIONS.md#CONV-2026-07-10-84e3]
Missing/invalid token returns 401; resource not found returns 404.
[scopes/frontend/ARCHITECTURE.md#ARCH-2026-07-10-6de2]
Auth token stored in localStorage under todo.auth.token key.
[scopes/frontend/DECISIONS.md#DEC-2026-07-10-c1ea]
Axios over raw fetch; reason: interceptors for auth header injection.
Every answer cites the exact [file#ID] so you can cat the entry or run lore history <ID> to see why the decision exists.
What CLAUDE.md looks like
lore keeps per-session cost flat by emitting a small index, not the full memory:
<!-- LORE:START -->
## Lore (auto-managed)
Project memory at `.lore/`. Before project-specific questions, read `.lore/SUMMARY.md` as the digest, then open the referenced entries (`.lore/_global/`, `.lore/scopes/`) for the full text before answering or deciding; cite entry IDs (e.g. `_global/ARCHITECTURE.md#ARCH-2026-01-15-d7a3`) when using memory.
**Structure**:
- Digest: `.lore/SUMMARY.md` (top-level overview)
- Global: `.lore/_global/` (architecture, decisions, conventions)
- Scopes: `.lore/scopes/`
- `.lore/scopes/backend/` (Flask 3 + SQLAlchemy 2 + pytest; Python 3.11+)
- `.lore/scopes/frontend/` (React 18 + TypeScript + Vite + Zustand + Axios)
- `.lore/scopes/shared/` (TypeScript types mirrored as Python dataclasses)
**Query**: `lore query <term>` or `lore query <scope>:<term>`
**Update**: see the `lore` skill (init / sync / query / audit / compress / mirror / history)
<!-- LORE:END -->
---
## My notes (free edit)
- Anything you write here is preserved verbatim across every sync.
The mirror file opens with an imperative sentence (e.g. "Project memory at .lore/. Before project-specific questions, read .lore/SUMMARY.md as the digest, then open the referenced entries for the full text before answering or deciding.") so the consuming agent has a clear trigger to load memory. The line lives in ## Lore (auto-managed) and is rewritten on every compress or lore mirror regeneration.
Git traceability with lore history
lore history DEC-2026-07-10-e45d(asking "why did we choose bcrypt?")
# history: [DEC-2026-07-10-e45d]
> Entry: scopes/backend/DECISIONS.md
> Since: 2026-07-10T00:00:00 (entry #added date)
> File: backend
> Commits: 2 (showing all)
## 9f264f4 (2026-07-10, Lore Tester)
feat(backend): add alembic migrations and switch password hashing to bcrypt
## ed2b288 (2026-07-10, Lore Tester)
feat(backend): password hashing and JWT-style auth tokens
The agent reads the commit messages and tells you why — without you having to manually dig through git log.
What lives in .lore/
.lore/
├── SUMMARY.md # Top-level digest; new agents read this first
├── .config.json # Optional config (auto_mirror, sync_trust, ...)
├── _global/ # Cross-scope facts
│ ├── ARCHITECTURE.md
│ ├── DECISIONS.md
│ └── CONVENTIONS.md
├── scopes/ # Per-scope facts (frontend / backend / shared)
│ └── <scope>/
│ ├── ARCHITECTURE.md
│ ├── DECISIONS.md
│ └── CONVENTIONS.md
├── draft/ # Used by `init` for proposals pending confirmation
└── audit/ # Used by `audit` for reports
Each entry is a single Markdown bullet (≤ 2 lines) with a deterministic ID and inline status tags:
- [ARCH-2026-07-09-a3f2] Use Next.js App Router; reason: streaming + RSC. #added:2026-07-09
- [DEC-2026-02-03-7c19] Chose Zustand over Redux; reason: 60% less boilerplate. #added:2026-02-03 #verified:2026-06-15
- [CONV-2026-01-20-b1e8] Never commit secrets; use `dotenv` + `.env.local` (gitignored). #added:2026-01-20
Entries can also carry #superseded-by:LAYER-YYYY-MM-DD-xxxx, which points to the entry that replaced this one — letting find_stale, history, and compress walk the replacement chain instead of inferring it from prose.
For the full format spec (ID generation, tags, splitting rules), see references/entry-format.md.
Seven workflows
| Command | What it does | Writes | Reference |
|---|---|---|---|
init |
First-time project scan; drafts entries; user confirms | .lore/* + platform mirrors |
workflows |
sync |
Detects code changes; proposes updates; user approves | .lore/* only (not mirrors) |
workflows |
query |
Read-only; answers from memory with entry IDs | nothing | workflows |
audit |
Read-only; checks memory vs. current code; writes report | .lore/audit/* only |
workflows |
compress |
Generates SUMMARY.md from current entries |
SUMMARY.md + platform mirrors |
workflows |
mirror |
Force-regenerate platform mirrors (with content dedup) | CLAUDE.md, .cursorrules, etc. |
workflows |
history |
Read-only; lists git commits related to an entry / file / scope | nothing | workflows |
For a plain-language explanation of each workflow (when you'd actually use each one, with real scenarios), see WORKFLOWS.md (中文版: WORKFLOWS.zh-CN.md).
sync never updates mirrors — run lore mirror (or compress) to publish changes. To restore mirror updates on every sync, set "sync_updates_mirror": true in .lore/.config.json.
Sync trust levels
sync can auto-apply or require confirmation depending on the change type and the configured trust level:
| Change type | high |
medium (default) |
low |
|---|---|---|---|
| De-duplicate hit | auto | auto | confirm |
| REFINED, tags only (body unchanged) | auto | auto | confirm |
| REFINED, body changed (new ID + supersede link) | auto | confirm | confirm |
NEW entry |
auto | confirm | confirm |
STALE mark |
auto | confirm | confirm |
ALERT |
confirm | confirm | confirm |
The default medium is a balance: low-risk changes apply silently, real additions or contradictions still get your sign-off. Switch to high for high-confidence projects (you trust the agent fully) or low if you want to review every change.
Platform mirrors
lore's canonical store is .lore/*, but it projects into the config files agents already read. Targets are resolved by scanning the repo root for existing platform files (auto-detect). When none are present, lore init asks via multi-select which agents to write for. Setting mirror_targets in .lore/.config.json overrides this with an explicit list (Replace semantics).
| Platform | File | Auto-detected? |
|---|---|---|
| Claude Code | CLAUDE.md |
✅ |
| Cursor | .cursorrules (or .cursor/rules/*.mdc) |
✅ |
| Cline | .clinerules |
✅ |
| Aider / Codex / OpenCode | AGENTS.md (or CONVENTIONS.md) |
✅ |
| Windsurf | .windsurfrules |
✅ |
| GitHub Copilot | .github/copilot-instructions.md |
✅ |
| Continue.dev | .continue/rules/lore.md |
✅ |
| LangGraph / DeepAgents | (no file — read .lore/*.md directly) |
n/a |
Each mirror file is split by a --- separator into a ## Lore (auto-managed) section (bounded by <!-- LORE:START --> / <!-- LORE:END -->) and a ## My notes (free edit) section. Lore only writes inside the Lore section; My notes is preserved verbatim. (See the full example under "What CLAUDE.md looks like" above.)
Token cost
lore's token model has six components. Only the mirror file is per-session; everything else is on-demand or per-invocation.
| Component | Loaded when | Typical size | Per-session? |
|---|---|---|---|
| Mirror file (CLAUDE.md, AGENTS.md, etc.) | Every session start | ~600 bytes (index mode, worst case) | yes |
| SKILL.md (the lore spec itself) | Every lore <cmd> invocation |
~19 KB | no, per-invocation |
references/workflows.md (the seven procedures) |
Every lore <cmd> invocation (only the routed section) |
~17 KB | no, per-invocation |
.lore/SUMMARY.md |
Agent reads on demand as the table of contents | 1–30 KB | no, on demand |
scopes/<scope>/{ARCH,DEC,CONV}.md |
Agent reads only the relevant scope | 1–5 KB each | no, on demand |
lore query <term> result |
Agent runs a query | bounded by matches | no, per query |
The mirror is the only ambient piece — the agent sees it every session — and it stays ~600 bytes because it's an index, not the memory. Mirror size scales with scope count and descriptions, not entry count: a 30-entry and a 250-entry project with the same scope shape have identical mirrors. Everything under .lore/ is on-demand: the agent reads SUMMARY.md as a table of contents, then opens only the entries it needs. SKILL.md and the routed workflows.md section load only when you invoke a lore command, and lore query returns only matched lines. Dumping the full SUMMARY.md into CLAUDE.md works but trades session-start cost for zero fetch — not recommended.
Scripts
Helper scripts in scripts/ reduce repetitive mechanical work:
python scripts/id_hash.py "Use Next.js App Router" # → 409a (4-char ID hash)
python scripts/list_entries.py # List all entries (text)
python scripts/list_entries.py --scope=frontend --json # Filtered JSON
python scripts/find_duplicates.py # Find potential duplicates
python scripts/find_stale.py --days=90 # Find stale entries
python scripts/history.py DEC-2026-02-03-7c19 # Show git history for an entry
python scripts/history.py --follow-superseded DEC-2026-02-03-7c19 # Walk the replacement chain
All scripts are cross-platform Python 3.6+ with no third-party dependencies. Regression tests live in tests/ and run with python -m unittest discover -s tests -v from the repo root. See scripts/README.md (English) or scripts/README.zh-CN.md (Chinese) for details.
Configuration
.lore/.config.json is optional. The defaults work for most projects.
{
"schema_version": 1,
"auto_mirror": false,
"sync_updates_mirror": false,
"sync_trust": "medium",
"mirror_targets": ["CLAUDE.md"], // optional — auto-detected if absent
"mirror_mode": "index",
"compress_thresholds": { "max_entries": 500, "max_days_since_compress": 30 },
"sync_thresholds": { "min_lines_changed": 50, "min_directories_changed": 2 }
}
Field semantics: see references/config.md. New configs include schema_version: 1; old configs without it still work but trigger a warning. See references/compatibility.md for the compatibility policy.
Upgrading
git pull (or re-clone) is the normal upgrade path; your .lore/ is preserved verbatim across upgrades. If a commit ships a breaking change, the commit message is prefixed BREAKING: and names what you need to edit by hand. Run git log --grep=^BREAKING after pulling to see any since your last sync. The current schema is schema_version: 1; no migration tool has shipped, so today there is nothing to run after pulling. See references/compatibility.md for the versioning policy.
When NOT to use lore
lore is built for long-term projects. It's overkill for:
- Short-lived scripts / one-off demos. The maintenance overhead exceeds the value.
- Rapid prototyping where decisions change weekly. The decision-tracking machinery gets in the way.
- Tiny single-file projects. Just use a
README.md. - Projects where you never want AI to make decisions. If you want a pure read-only agent, lore adds no value.
- Massive monorepos with 50+ packages. The scope tree becomes unwieldy; consider splitting per-package or using a sub-skill per cluster.
FAQ
Q: Does lore work without git?
A: Partially. Most of lore is agent workflow described in references/workflows.md (routed from SKILL.md) — the agent reads your files, drafts entries, edits .lore/*.md, and (when asked) regenerates mirrors. Without git, the agent can still do init / query / audit / compress / mirror by reading files directly. What you lose: sync uses git diff to detect changes (no diff → the agent asks you what changed), and lore history requires a git repo (it runs git log). The helper scripts (list_entries.py, find_stale.py, etc.) work either way.
Q: Can I hand-edit .lore/*.md directly?
A: Yes. The files are plain Markdown. Use id_hash.py if you're adding new entries (to keep IDs deterministic). After hand-editing, run lore mirror to update agent-facing files.
Q: What if I don't want a mirror file at all (just .lore/)?
A: Set mirror_targets: [] in .config.json. The compress and mirror commands will be no-ops on the file system; only SUMMARY.md and the entry files matter.
Q: How is this different from Cursor's .cursorrules or Aider's AGENTS.md?
A: Those are flat lists of rules. lore is structured (architecture / decisions / conventions), atomic (one fact per entry), and historical (every entry has #added and #verified tags). It also produces those files for you.
Q: Does lore talk to the agent's API? A: No. lore is pure file I/O. The agent invoking lore does the semantic work (scanning code, deciding what to extract, classifying changes); lore provides the file layout, the ID scheme, the markers, and the verification scripts.
Q: What about the agent's native /init or /compact commands?
A: They serve different purposes — /init is a one-shot project scan, /compact compresses conversation context, and lore manages long-term project knowledge. All three coexist.
Q: I already generated a root AGENTS.md (via /init or a bootstrapping tool). Can I still use lore?
A: Yes — that's the designed flow. Run lore init and choose take over when it detects the existing AGENTS.md: the file becomes a two-section mirror, your original content is preserved verbatim as ## My notes (free edit), and lore's ## Lore (auto-managed) section is added above it. Lore only rewrites its own section, so the bootstrapped commands and conventions stay untouched. The same applies to CLAUDE.md, .cursorrules, etc. In reverse — if lore created the file first — run the bootstrap tool and choose skip, then paste its generated content into ## My notes.
Q: I added a new scope (e.g. a new package) after lore init. Do I re-run init?
A: No — run lore sync. It detects the new scope from the changed file paths, creates scopes/<name>/ automatically, and routes entries there. Then run lore mirror so the new scope appears in the agent-facing files. init is only for first-time setup or an explicit start-over.
Q: What's the difference between sync and mirror?
A: sync updates .lore/ from code changes (run after a feature or refactor). mirror updates agent-facing files (CLAUDE.md, .cursorrules, etc.) from current .lore/. sync deliberately does not update mirrors — mirror files should be human-merged, not regenerated on every commit, so git log stays readable. Run mirror (or compress) explicitly when you want agent-facing files to catch up.
Q: How is lore different from ADRs (Architecture Decision Records)?
A: ADRs are documents — one markdown file per decision. lore is structured project memory: one fact per entry, with a stable ID and #added / #verified / #stale markers. The DEC layer can replace docs/adr/ (one DEC entry per decision), but lore also covers ARCH (architecture) and CONV (conventions) in the same store, plus generates agent-facing summaries via compress / mirror. Use lore instead of ADRs, or alongside them (one DEC entry pointing to the existing ADR document).
Q: What if I disagree with an entry the agent wrote?
A: Edit .lore/*.md directly — it's plain Markdown. The next mirror / compress will reflect your edit, and the helper scripts keep the ID stable as long as the entry text is unchanged. To revert to pre-AI state, git checkout .lore/ like any tracked file.
Q: Can I sync .lore/ across multiple machines without git?
A: Git is the recommended transport (.lore/ is plain text in your repo; git push / git pull carry it). Other transports (Dropbox, OneDrive, Syncthing) work as long as you trust their text-file conflict resolution — they won't understand lore's ID scheme or #added markers. Don't run two agents on the same .lore/ simultaneously; last-writer-wins, and IDs aren't protected by a remote lock.
License
MIT — use, modify, redistribute, sublicense, and sell, including commercially. No warranty.
No comments yet
Be the first to share your take.