Skip to main content

legendary

Code-anchored, staleness-aware, git-native memory for coding agents.

Documentation  ·  Quickstart  ·  Concepts  ·  MCP tools  ·  Comparison

CI PyPI Python versions MIT


Coding agents are stateless: every session re-reads your repo, re-derives old decisions, and repeats debugging attempts that already failed. Memory frameworks remember conversations but are code-blind - a memory never knows it was about src/sync/worker.py:120 and never notices when that code changes.

legendary merges the two sides:

  • Anchored - memories link to a file / symbol / line range at a commit
  • Staleness-aware - when the anchored code changes, recall flags the memory stale; when it disappears, orphaned
  • Typed - decision (why it is this way), episode (tried X, failed because Y), convention, reference
  • Git-native - memories are markdown files in .legendary/memories/, committed with your code, diffable in PRs, shared with your whole team
  • Local-first - no cloud, no accounts, no API keys, no embeddings; SQLite FTS5 does search

The 30-second demo

$ legendary recall "strip None"
strip() breaks on None   [fresh]

$ vim app.py     # edit the anchored function

$ legendary recall "strip None"
strip() breaks on None   [stale - parse changed since 8fa2c31]

That flag is the whole point. Every other memory system would still serve you that memory with full confidence.

Quick start

cd your-repo
uvx --from legendary-mcp legendary init   # scaffolds .legendary/, prints MCP + hook setup

Add the printed MCP snippet to your client (Claude Code, Cursor, any MCP host). Your agent now has five tools:

Tool Purpose
remember save a memory anchored to code
recall search; results carry fresh/stale/orphaned flags
list_memories browse by type/tag/file
deprecate soft-delete with a reason
stale_report all memories whose code moved on

Optional auto-capture (Claude Code): the printed hooks run legendary inject at session start (context injection) and legendary extract at session end (LLM pass over the transcript, saved with source: auto-extract provenance).

CLI

legendary init | search <q> | reindex | doctor | extract [transcript] | inject | mcp

legendary mcp serves stdio by default; --transport http serves stateless streamable HTTP for containers and shared team deployments.

How staleness works

At write time each anchor stores a normalized content hash of the anchored region (symbol body, line range, or file). At recall time the region is re-resolved (symbols may move) and re-hashed. Changed hash => stale; missing file/region => orphaned. Stale memories still surface - the why often survives a refactor - but ranked lower and clearly flagged.

Whitespace-only changes do not invalidate a memory, and a symbol that merely moves down the file stays fresh, because anchors are re-resolved by symbol before hashing.

Architecture

flowchart TB
    subgraph host["MCP host - Claude Code / Cursor / Codex / any"]
        agent["Coding agent"]
    end

    subgraph legendary["legendary (uvx --from legendary-mcp)"]
        mcp["MCP server<br/>remember - recall - list_memories<br/>deprecate - stale_report"]
        cli["CLI<br/>init - search - reindex - doctor<br/>extract - inject"]
        svc["service layer"]
        subgraph core["core"]
            store["markdown store"]
            index["SQLite FTS5 index"]
            anchor["anchor resolve + hash"]
            stale["staleness verdicts"]
            rank["weighted ranking"]
        end
    end

    subgraph repodir[".legendary/ in your repo"]
        md["memories/*.md - committed"]
        db["index.db - gitignored"]
    end

    agent -- "MCP tools (stdio)" --> mcp
    agent -. "session hooks" .-> cli
    mcp --> svc
    cli --> svc
    svc --> store
    svc --> index
    svc --> anchor
    svc --> stale
    svc --> rank
    store --> md
    index --> db
stateDiagram-v2
    [*] --> fresh: remember() - region hashed at commit X
    fresh --> stale: anchored region edited
    stale --> fresh: memory re-anchored
    fresh --> orphaned: file / symbol deleted
    stale --> orphaned: file / symbol deleted
    fresh --> deprecated: deprecate(reason)
    stale --> deprecated: deprecate(reason)
    orphaned --> deprecated: doctor cleanup

What a memory looks like

---
id: mem-a1b2c3d4
type: episode
title: Retry logic in sync worker breaks under SQLite WAL
created: 2026-08-14T15:30:00Z
source: agent
status: active
anchors:
  - file: src/sync/worker.py
    symbol: SyncWorker.run
    lines: [120, 164]
    commit: 8fa2c31
    content_hash: sha256:9f8e...
tags: [sqlite, concurrency]
---
Tried wrapping retries in a transaction (attempt 1) - deadlocks under WAL.
Working approach: PRAGMA busy_timeout.

Human-readable, PR-reviewable, and it merges like code.

How this differs from other tools

Graphify / Serena mem0 / Zep legendary
Models code structure yes no anchors only
Remembers decisions no yes yes
Remembers failed attempts no partly yes (episode)
Memories tied to code entities n/a no yes
Detects when a memory goes stale n/a no yes
Team-shared via git graph committed no (service) yes
Retrieval needs an LLM no embeddings no

Code-graph tools answer "what is this code?"; legendary answers "what do we already know about it, and is that still true?" Running both is a good setup.

Documentation

Full docs at ashhadahsan.github.io/legendaryquickstart, concepts, MCP tool reference, CLI reference, benchmark, and FAQ.

Contributing? See CONTRIBUTING.md.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

legendary_mcp-0.1.0.tar.gz (174.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

legendary_mcp-0.1.0-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file legendary_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: legendary_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 174.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for legendary_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6416e7b15c59a72fe50aad72a3a3acde2ffd7a0c8f8b2741a1c07a896bfe72e0
MD5 1e24da17e713ccfb482d20de938b53ca
BLAKE2b-256 89252ba9c328a0b4a64ac6696b2a99a6a724ebb663892ce50b04b325d3455824

See more details on using hashes here.

File details

Details for the file legendary_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: legendary_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for legendary_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 741b69c8809662570e34f1c94580d7e2207c1bcc1fcc73b638ef912b90dac6d5
MD5 2f2aaf545a4d3cc556c236809ee64034
BLAKE2b-256 40f88ce24eb27c2a762b9799a41d9a503f010710b4aa540afdbd861d6366e718

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page