# Lore

> Long-term Markdown project memory for AI coding agents. Use when the user wants to record, recall, audit, sync, or compress project decisions, architecture, conventions, monorepo scopes, or `.lore/` entries, including natural-language requests like "remember this decision" or explicit `lore init/sync/query/audit/compress/mirror`. Do not trigger on native `/init` or `/compact`, or generic init/com…

- **Type:** Skill
- **Install:** `agentstack add skill-theadust-lore-lore`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [TheaDust](https://agentstack.voostack.com/s/theadust)
- **Installs:** 0
- **Category:** [Content & Media](https://agentstack.voostack.com/c/content-and-media)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [TheaDust](https://github.com/TheaDust)
- **Source:** https://github.com/TheaDust/lore

## Install

```sh
agentstack add skill-theadust-lore-lore
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# lore — Framework-agnostic Memory Management

## What this skill is

A long-term knowledge base for a software project, maintained by AI agents. It is **not** a dev journal or a changelog. It captures the kind of context that normally lives only in the original developer's head:

- What the project is, how it is shaped (architecture)
- Why specific choices were made over alternatives (decisions)
- How code should be written and what to avoid (conventions)

This knowledge is persisted as **plain Markdown files** in `.lore/` at the project root. Any agent that can read files can consume them.

## When to trigger

The skill uses a **two-tier trigger model**:

**Tier 1 — Loading the skill.** Load this skill when the user explicitly invokes `lore`, names a subcommand, references `.lore/`, or asks to record, recall, audit, sync, or compress project memory about decisions, architecture, conventions, or monorepo scopes. Generic phrases like "init", "compress", "audit", or "query" alone are not enough — they may map to the agent's native commands or unrelated tasks (Claude Code's `/init`, `/compact`, security audits, SQL queries, etc.).

| User says (examples) | Command |
|---|---|
| "lore init" / "create lore memory bank" / "initialize lore" | `init` |
| "lore sync" / "sync this change to lore" / "record this decision in lore" | `sync` |
| "lore query" / "query lore" / "what's the project convention" | `query` |
| "lore audit" / "check lore" / "is memory still accurate" | `audit` |
| "lore compress" / "compress lore" / "summarize lore" | `compress` |
| "lore mirror" / "update CLAUDE.md" / "refresh mirror" | `mirror` |

**Tier 2 — Internal proposals (after the skill is loaded).** Once the skill is loaded for this session, certain commands may proactively propose themselves based on internal thresholds. These proposals still require user acceptance — the skill never mutates files silently.

- `sync` proposes when ≥50 changed lines span ≥2 directories, OR a new top-level module/directory/dependency was added or removed, OR a new convention was explicitly discussed in chat.
- `compress` appends a `[COMPRESS NOTICE]` to sync proposals when entries > 500, `SUMMARY.md` is missing, or last compression > 30 days ago.
- `audit` emits `[ALERT]` markers during sync when an active entry conflicts with current code or with a candidate change.
- `mirror` regenerates automatically during `compress` if `auto_mirror: true` is set in `.lore/.config.json`.

Other commands (`init`, `query`, `history`) are always explicit — they need user intent. See [`WORKFLOWS.md`](WORKFLOWS.md) for a plain-language explanation of when each workflow is used.

## Reference index

Detailed specifications live in `references/`. Load these on demand.

| File | When to load |
|---|---|
| `references/entry-format.md` | Writing entries, computing IDs, cross-file references |
| `references/summary-template.md` | Running `compress` — SUMMARY.md schema and selection rules |
| `references/audit-template.md` | Running `audit` — report format and severity definitions |
| `references/monorepo-detection.md` | During `init` — detecting scope boundaries from workspace config |
| `references/stale-new-markers.md` | During `sync` — full marking convention and user reply semantics |
| `references/platform-mirrors.md` | Platform file mapping (CLAUDE.md / .cursorrules / etc.), two-section file structure |
| `references/config.md` | `.lore/.config.json` schema and field semantics |
| `references/history-command.md` | Running `history` — full spec, dispatch rules, error table |
| `references/compatibility.md` | Versioning policy: `.config.json#schema_version`, migration tools, deprecation workflow |
| `scripts/README.md` | Helper scripts (id_hash, list_entries, find_duplicates, find_stale) — also in Chinese (`scripts/README.zh-CN.md`) |

## Memory architecture

### Directory layout

```
.lore/
├── SUMMARY.md              # Top-level digest. New agents read this first.
├── _global/                # Cross-scope facts (whole-project architecture, global decisions)
│   ├── ARCHITECTURE.md
│   ├── DECISIONS.md
│   └── CONVENTIONS.md
├── scopes/                 # Per-scope facts
│   ├── /
│   │   ├── ARCHITECTURE.md
│   │   ├── DECISIONS.md
│   │   └── CONVENTIONS.md
│   └── ...
├── draft/                  # Used only by `init`. Proposals pending user confirmation.
└── audit/                  # Used only by `audit`. Reports; never mutates main files.
```

**Scope detection during init:** see `references/monorepo-detection.md` for marker detection across pnpm / Yarn / npm / Lerna / Nx / Rush / Cargo / Go / Bazel. Single-package projects fall back to `_global/` only.

**Decisions placement:**
- Affects ≥ 2 scopes (e.g. "use pnpm workspaces", "TypeScript strict") → `_global/DECISIONS.md`
- Affects exactly one scope → that scope's `DECISIONS.md`

There is no separate metadata file. Every status lives as inline tags on entries themselves.

### Entry format

Each entry is a Markdown bullet (≤ 2 lines), with a layer prefix, a deterministic ID, and inline status tags. See `references/entry-format.md` for the full spec (ID generation via content hash, tag semantics, cross-file reference format, splitting rules).

```markdown
- [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
- [CONV-2026-01-20-b1e8] Never commit secrets; use `dotenv` + `.env.local` (gitignored). #added:2026-01-20
```

## Platform mirror

The canonical store is `.lore/*`. Agents that expect a single config file at the project root (`CLAUDE.md` for Claude Code, `.cursorrules` for Cursor, `.clinerules` for Cline, `AGENTS.md` for Aider, etc.) read a synced projection of that store.

**A mirror is a synced projection, not a strict derivative.** It contains two sections: a Skill-managed `## Lore` section (rewritten on mirror regeneration) and a user-editable `## My notes` section (preserved verbatim). Both sections are legitimate mirror content. The user can write personal preferences, temporary instructions, or any project-specific note in the My notes section; the Skill never touches it.

```markdown

## Lore (auto-managed)

# .lore SUMMARY (synced 2026-07-09)

...auto-generated content from .lore/*...

---

## My notes (free edit)

- Keep answers concise
- Prefer English
- Currently refactoring the user auth module
```

**Default behavior:**

- **Init**: targets are auto-detected (existing platform files in repo root) — see `references/platform-mirrors.md`. If none detected, ask the user via multi-select which agents they use. For each detected file lacking a `## Lore` section, ask take over / preserve / abort per file. Auto-create missing files with the full two-section template; refresh existing lore mirrors; preserve My notes verbatim.
- **Sync / Compress**: controlled by `.lore/.config.json#auto_mirror`. Default is `false` (ask per target). When `true`, mirrors update automatically. My notes section is **always** preserved.

By default the Lore section is an **index** into `.lore/` — paths plus a per-scope one-line description, ~500 bytes total. The agent reads `.lore/SUMMARY.md` (or calls `lore query `) on demand. See `references/platform-mirrors.md` for the template and adaptive rendering rules.

See `references/platform-mirrors.md` for the per-platform file mapping and the full two-section structure rules, and `references/config.md` for `.config.json` schema.

LangGraph / DeepAgents typically don't need a mirror file — they read `.lore/*.md` directly or ingest into the system prompt at runtime (the user's responsibility).

## Relationship to agent native commands

Several agents have built-in commands with similar names. lore does **not** replace them; it manages a different concern (long-term project knowledge vs. session context). The two coexist.

| Agent command | What it does | lore equivalent |
|---|---|---|
| Claude Code `/init` | One-shot project scan → generates `CLAUDE.md` | `lore init` (creates `.lore/` + mirror files) |
| Claude Code `/compact` | Compresses the current conversation context | `lore compress` (regenerates `SUMMARY.md` from entries) |
| Cursor `/init` (if present) | Project bootstrap | Same as Claude Code `/init` |

**How they interact:**

- If the user runs `lore init` and a non-lore `CLAUDE.md` exists, the init takeover check (step 0 in `init`) handles integration.
- If the user runs the agent's native `/init` on a project that already has `.lore/`, the skill should ask whether the user wants to take over the existing `CLAUDE.md` or leave it alone.
- If both `lore sync` and `/compact` are available, they do unrelated work — run them independently.
- If the user's intent is ambiguous (e.g. they say "init" without "lore"), defer to the agent's native `/init`. Do not silently invoke `lore init`.

To disable Claude Code's automatic `/init` on a project where `lore` is in use, set `"initHintShown": true` in `.claude/settings.json` (see Claude Code docs for current options).

## Workflows

### `init` — Initialize the memory bank

Runs once per project (or to start over).

0. **Resolve targets and takeover check.** Targets are determined by the resolution algorithm — see `references/platform-mirrors.md`. Default behavior: scan repo root for existing platform files; if none found, ask the user via multi-select which agents they use. Explicit `mirror_targets` in `.lore/.config.json` overrides auto-detect (Replace semantics). For each resolved target:
   - If the file does not exist → no action; it will be created later in step 7.
   - If the file exists AND contains a `## Lore` section → it's already a lore mirror; note it and continue (its My notes will be processed as seed in step 5).
   - If the file exists AND does NOT contain a `## Lore` section → it's likely from the agent's native `/init` or hand-written. Show the user:
     - (a) **Take over** — rewrite the file as a two-section mirror. The existing content becomes the My notes section (preserved verbatim, treated as seed knowledge in step 5).
     - (b) **Preserve as-is** — leave the file alone. Remove it from `mirror_targets` for this project (lore won't write to it). `.lore/` is still generated normally; the user can read `SUMMARY.md` directly or merge manually later.
     - (c) **Abort** — exit init. Nothing is created. The user can decide later.
   - Repeat for each resolved target before proceeding.
1. Check if `.lore/` already exists. If yes, warn and ask: archive the current one and re-init, or abort?
2. Detect monorepo structure (per `references/monorepo-detection.md`). Propose scope list to the user; let them rename / merge / split before proceeding. No monorepo → `_global/` only.
3. Scan the project (per scope if applicable):
   - Top-level structure, entry points, package manager, language version
   - Config files: `package.json`, `pyproject.toml`, `Cargo.toml`, `tsconfig.json`, `Dockerfile`, `Makefile`, CI
   - `README*`, `CONTRIBUTING*`, existing docs
   - Key dependencies from lockfiles
4. Write proposals to `.lore/draft/` mirroring the target layout (`_global/` and per-scope subdirs). Every entry gets `#added:` and a deterministic hash-based ID (see `references/entry-format.md`).
5. For any mirror file that already has a `## Lore` section (from step 0), read its My notes section as user-supplied seed knowledge. Parse as atomic bullets into the right layer/scope.
6. **Stop and show the user a summary**: which scopes, how many entries per layer per scope, sample of 5–10 entries, and what mirror files will be (re)generated (or skipped per step 0).
7. On user confirmation: `mv .lore/draft/* .lore/`, run an initial `compress` to generate `SUMMARY.md`, then (re)generate platform mirrors per the two-section structure — auto-create missing files, refresh Lore sections, leave My notes sections intact. Skip any target the user chose "preserve as-is" in step 0.
8. On user rejection: `rm -rf .lore/draft/`. Nothing persists.

The `draft/` directory gives a clean rollback path: nothing in `.lore/` is real until the user approves.

### `sync` — Update after a change

Runs after the user completes a feature, refactor, or bug fix.

**Trigger threshold — only propose sync when at least one is true:**
- `git diff --stat HEAD` shows ≥ 50 changed lines across ≥ 2 directories
- A new top-level module / directory / dependency was added or removed
- A new convention was explicitly discussed (e.g. user said "from now on we use X")
- The user explicitly invokes `sync` regardless of diff size

Pure typo fixes, lockfile-only changes, README rewording, or sub-30-line tweaks do **not** warrant `sync`.

**Compress threshold check (silent, runs before sync proposal):**
- Total entry count across all files > 500, **or**
- `SUMMARY.md` is missing, **or**
- `SUMMARY.md` last `Last compressed:` date is > 30 days ago

If any of these are true, the skill appends a `[COMPRESS NOTICE]` to the sync proposal. It does not block the sync — the user can defer.

**Procedure:**

1. **Detect the delta** from two sources, combined and de-duplicated:
   - `git diff ..HEAD` if `.lore/.config.json#last_sync_sha` is set and reachable from any local ref. This captures every commit since the last successful `sync`.
   - `git diff` (working tree vs. `HEAD`) — always included. Catches uncommitted changes that are not yet in any commit.
   - **Re-scan any new files**.
   - **Fallback** when `last_sync_sha` is absent (older config) or no longer reachable (e.g. after `git rebase` or a force-push that orphaned the SHA): use `git diff HEAD` alone and emit a one-line `[WARN]` to stderr noting that incremental sync is degraded. Working tree alone will not pick up commits made before the next sync ran — the user should re-run `sync` after `git pull --rebase` to re-establish the baseline.
   - **Empty repo** (no commits yet): `last_sync_sha` is `null`; only the working tree diff applies.
2. **Determine target scope(s)** for each change. Use `git diff --name-only` paths (over the combined commit + working-tree diff) to map files → scopes (e.g. `frontend/src/...` → `scopes/frontend/`). Cross-scope changes (root config files) → `_global/`.
3. **Classify each change** into one layer:
   - New module, new dependency, new file structure → `ARCHITECTURE.md`
   - "We picked X over Y because Z" → `DECISIONS.md`
   - New lint rule, new naming pattern, new "we never do X" → `CONVENTIONS.md`
4. **For each candidate entry**:
   - **Contradicts an existing entry** in the same scope/layer → mark the old one `#stale:` and `#superseded-by:` (where `` is the entry in this proposal that replaces it). Emit an `ALERT`.
   - **No replacement entry exists yet** (user is removing a fact without substituting) → mark the old one `#stale:` only; the chain can be backfilled later.
   - **Refines an existing entry** → update the text in place, bump `#verified:`.
   - **Genuinely new** → append with `#added:` and a new hash ID.
5. **De-duplicate**: before appending, run `python scripts/find_duplicates.py --json` to identify any candidate entry that overlaps with existing entries (same hash, or Jaccard ≥ `--threshold`). For each match, skip the new entry and bump `#verified` on the existing one. If the new entry is genuinely different in meaning (the script flags but doesn't decide), keep both.
6. **Apply trust level** (controlled by `.lore/.config.json#sync_trust`, default `"medium"`):

   | Change type | `high` | `medium` (default) | `low` |
   |---|---|---|---|
   | De-duplicate hit (same fact already present) | auto-apply | auto-apply | confirm |
   | Equivalent REFINED (text rewrite, same meaning) | auto-apply | auto-apply | confirm |
   | `NEW` entry | auto-apply | confirm | confirm |
   | `STALE` mark | auto-apply | confirm | confirm |
   | `ALERT` | confirm | confirm | confirm |

   Auto-applied changes are written silently and reported at the end. Confirmatio

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [TheaDust](https://github.com/TheaDust)
- **Source:** [TheaDust/lore](https://github.com/TheaDust/lore)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-theadust-lore-lore
- Seller: https://agentstack.voostack.com/s/theadust
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
