LadyM

English | 简体中文
A brain-inspired, multi-tier memory framework that lets LLM agents recall workspace
knowledge and codebase analysis with one keyword — instead of re-Read-ing and
re-Grep-ing the same files every turn.
LadyM caches your workspace's understanding — code analysis, decisions, skills, and
episodes — into a hierarchical, consolidating, decaying memory that any agent can recall
through a single keyword. Written in Go as a single static binary with zero cgo:
SQLite via modernc.org/sqlite, an in-process
brute-force cosine vector index, and gotreesitter
(a pure-Go tree-sitter runtime) for code indexing. Exposed via MCP, Claude Code
Skill, Go SDK, and CLI — all calling the same engine so behaviour is
identical everywhere.
What's New in 0.3.0
- Full Go rewrite — LadyM is now one static binary with no Python dependency and
zero cgo. Install with
go install or build from source; there is nothing else to set up.
- Pure-Go storage stack — SQLite runs on
modernc.org/sqlite, and the old sqlite-vec
extension is replaced by an in-process brute-force cosine index (storage/vector_index.go),
so the binary stays hermetic and cross-compiles anywhere.
- Pure-Go tree-sitter — code indexing uses
gotreesitter, which loads the same parse
tables as upstream tree-sitter without native builds.
- One engine, every front — the MCP server, CLI, and Go SDK all wrap the same
engine.Engine; behaviour is identical in every host.
The problem
Today's coding agents have no long-term memory. Every turn they re-Read the same files
and re-Grep for the same symbols, burning the context window on rediscovery. Plain vector
RAG helps, but it forgets why a decision was made, how a task was done before, and
what the codebase actually looks like beyond flat chunks.
LadyM turns that throwaway rediscovery into structured, evolving memory.
Why LadyM
|
What you get |
| 🧠 Code memory + general memory in one layer |
L2 fuses tree-sitter code symbols and plain facts in a single store, scored by one activation function. Memory and codebase RAG are one system, not two — a unique spot no other framework occupies. |
| 🔒 Local-first, zero-config start |
Default HashingEmbedding + llm.provider="none" runs the moment install finishes: no network, no model download, no API key. One SQLite file holds everything. |
| 🧬 Brain-inspired six layers + dual-path |
L0–L4 core store (working / episodic / semantic / procedural / associative) plus a System 2 worker that extracts L5 mental models and L6 forward intents, with a supersedes evolution chain so memories evolve instead of piling up. |
| 🔌 Four fronts, one engine |
MCP server, Claude Code Skill, Go SDK, and CLI all call the same Engine — identical behaviour whether you're in Claude Code, Cursor, a script, or the terminal. |
Quick start (30 seconds)
# 1. install (single static binary — no network or API key needed at runtime)
go install github.com/ProjAnvil/LadyM/cmd/ladym@latest
# 2. index the codebase you keep re-grepping
ladym index ./src
# 3. ask a question — get the analysis back, no Read/Grep needed
ladym recall "how does password verification work" --code
# 4. store a fact for later
ladym remember "auth uses JWT with 24h expiry" --tags auth,security
That's it — ladym is on your PATH and works fully offline.
How it compares
|
Local-first |
Codebase RAG fused |
Brain-inspired tiers |
Open source |
MCP/Skill/SDK/CLI |
| LadyM |
✅ |
✅ L2 fused |
✅ L0–L6 + System 1/2 |
✅ MIT |
✅ all four |
| mem0 |
partial |
❌ |
flat + graph |
✅ |
SDK |
| Zep / Graphiti |
cloud |
❌ |
temporal knowledge graph |
✅ |
SDK |
| Letta (MemGPT) |
self-host |
❌ |
OS-style agent runtime |
✅ |
SDK |
| Tencent Hy-Memory |
cloud SaaS |
❌ |
✅ L1–L6 |
❌ |
SDK |
LadyM borrows academic ideas from all of them (see
ARCHITECTURE.md §10) — its distinctive bet is fusing codebase RAG into
a brain-inspired memory that runs fully local.
Architecture
System 1 — online (ms) System 2 — offline worker (s–min)
┌───────────────────────────┐ ┌───────────────────────────┐
│ L0 Working (scratch)│ │ L5 Mental Model │
│ L1 Episodic (events) │ extract │ (cognitive frameworks)│
│ L2 Semantic (facts+CODE)│─────────▶│ L6 Forward Intent │
│ L3 Procedural (playbook)│ │ (predictive actions) │
│ L4 Associative (graph) │ └───────────────────────────┘
└───────────────────────────┘
▲
read ◀──── recall(query) : two-tier (lightweight → deep) + reflection gate
write ───▶ encode / consolidate / proceduralize / link / forget / decay
| Layer |
Brain analogue |
LadyM behaviour |
| L0 Working |
Prefrontal cortex (working memory) |
In-process bounded scratch buffer |
| L1 Episodic |
Hippocampus |
Time-stamped events; base-level decay |
| L2 Semantic |
Neocortex |
Consolidated facts and code analysis — one store |
| L3 Procedural |
Basal ganglia |
Playbooks + verified snippets, versioned |
| L4 Associative |
Associative cortex |
Zettelkasten edges with temporal validity |
| L5 Mental Model |
(metacognition) |
Cognitive frameworks abstracted from recurring episodes |
| L6 Forward Intent |
(planning) |
Predictive next-actions, asynchronously distilled |
Operations: encode (perception), consolidate (hippocampal replay → neocortex),
proceduralize (skill acquisition), recall (retrieval), link (association),
forget (synaptic pruning), reflect (metacognition).
The read path is heuristic-only — no LLM judge is ever invoked during recall, so it
stays fast and predictable. For the full cognitive-science provenance (what's borrowed
from MemGPT, mem0, A-MEM, Zep, HyMem, CoALA, ACT-R, and Anthropic's context-engineering
work) see ARCHITECTURE.md.
Install
As a global CLI (recommended)
go install github.com/ProjAnvil/LadyM/cmd/ladym@latest
This drops a single static ladym binary on your Go bin path
($(go env GOPATH)/bin). Requires Go 1.26+ to build; the binary itself has no
runtime dependencies.
Build from a clone
git clone https://github.com/ProjAnvil/LadyM.git && cd LadyM
go build -o bin/ladym ./cmd/ladym
./bin/ladym stats
Or use the install script, which builds and copies the binary to ~/.local/bin:
scripts/install.sh # or: scripts/install.sh /custom/bin/dir
For development
git clone https://github.com/ProjAnvil/LadyM.git && cd LadyM
go build ./... # compile everything
go test ./... # full suite, fully offline
The module is pure Go (github.com/ProjAnvil/LadyM) with a handful of library
dependencies — no native toolchain needed on macOS/Linux/Windows.
Integration
All four fronts call the same Engine, so behaviour is identical everywhere.
MCP server (Claude Code, Cursor, …)
Add to your MCP client config:
{
"mcpServers": {
"ladym": {
"command": "ladym",
"args": ["serve", "--db", "/absolute/path/to/ladym.db"]
}
}
}
The server speaks MCP over stdio and exposes nine tools — recall, remember,
record_event, search_code, index_code, consolidate, stats, link,
forget — described in mcp/server.go. record_event logs an L1
episodic event that feeds the System 2 worker's consolidation (L1 → L2) and the
gated L5 / L6 extractors (record ~3+ to arm those cycles).
Claude Code Skill
A drop-in skill is in skills/ladym-recall.md. Copy it to your
.claude/skills/ directory and the agent will pull workspace memory into context with a
keyword instead of re-reading files.
Go SDK
The ladym package is a one-import facade over the engine
(ladym/ladym.go):
import "github.com/ProjAnvil/LadyM/ladym"
eng, err := ladym.NewEngine(ladym.DefaultConfig())
if err != nil {
// handle error
}
defer eng.Close()
// index once (incremental — skips unchanged files)
report, err := eng.IndexCode("./src", false, "", nil)
// write path
eng.Remember("auth uses JWT with 24h expiry", ladym.LayerSemantic, ladym.TypeFact,
[]string{"auth"}, nil, "sdk", "")
eng.RecordEvent("claude", "fixed login bug", "", "success", nil, nil)
// read path: two-tier retrieval, ACT-R activation ranking
resp, err := eng.Recall("how does auth work", "", 8, nil, nil, 0)
for _, r := range resp.Results {
fmt.Printf("%.3f [%s] %s\n", r.Score, r.Memory.Layer, r.Memory.Summary)
}
// code-only shortcut
codeResp, err := eng.SearchCode("verify password", 8, "")
// cognitive operations
eng.Consolidate("", 0) // L1 episodes → L2 facts (ADD/UPDATE/DELETE/NOOP)
eng.Proceduralize("", 0) // recurring successful episodes → L3 playbooks
eng.Decay("", true, 0, 0) // ACT-R base-level forgetting (dry run)
eng.Link(srcID, dstID, "depends_on") // Zettelkasten edge
One-shot helpers — ladym.Recall(query, dbPath, workspace, topK),
ladym.Remember(...), ladym.IndexCode(...) — open a short-lived engine, run, and
close, for scripts that don't want to manage the lifecycle.
Python SDK (MCP wrapper)
Python apps talk to the Go engine through wrapper/py — a thin typed
client that spawns the ladym serve MCP server (JSON-RPC 2.0 over stdio) and exposes
the nine tools (recall, remember, record_event, search_code, index_code,
consolidate, stats, link, forget) as Python methods. No memory logic lives in
Python; the Go binary is the single source of truth.
from ladym_wrapper import LadymClient # sync
from ladym_wrapper import AsyncLadymClient # async
with LadymClient() as client:
client.remember("deploys go through Argo CD", source="notes")
hits = client.recall("how do we deploy?")
The Go binary is resolved in order: binary= argument → LADYM_BIN env var → PATH →
repo-local bin/ladym. Requires Python ≥ 3.12. See
wrapper/py/README.md for details. (The full 0.2.x Python
implementation is preserved on the
python branch.)
Injecting your own langchain-golang models
If your app already configures langchain-golang chat / embedding models
(with api key, base URL, model), wrap them and pass them straight to the Engine via
ModelRouting — no need to re-declare credentials in LadyM's config
(adapter/adapter.go):
import (
"github.com/ProjAnvil/LadyM/adapter"
"github.com/ProjAnvil/LadyM/ladym"
"github.com/projanvil/langchain-golang/core/modelconfig"
"github.com/projanvil/langchain-golang/partners/openai"
)
eng, err := ladym.NewEngineWithModels(ladym.DefaultConfig(), &adapter.ModelRouting{
Consolidate: adapter.WrapChatModel(openai.NewChatModel(
modelconfig.WithModel("gpt-4o"),
modelconfig.WithAPIKey(key),
modelconfig.WithBaseURL(url),
), ""),
AttentionGate: adapter.WrapChatModel(openai.NewChatModel(
modelconfig.WithModel("gpt-4o-mini"),
modelconfig.WithAPIKey(key),
), ""),
Embedding: adapter.WrapEmbeddings(openai.NewEmbeddings(
modelconfig.WithModel("text-embedding-3-small"),
modelconfig.WithAPIKey(key),
)),
})
Each of the five cognitive ops (consolidate, proceduralize,
attention_gate, l5_mental_model, l6_forward_intent) can take a
different model; unset ops fall back to Config.
LangGraph
The langgraph/ package integrates LadyM as a long-term memory layer for
langchain-golang LangGraph / LangChain agents. Two equivalent paths:
- Tools —
langgraph.CreateTools(eng, workspace, defaultTopK) returns LangChain
tools (recall_memory, remember_fact, search_code) for ReAct-style agents where
the LLM decides when to recall/remember.
- Nodes —
langgraph.CreateRecallNode(eng, topK, prefix, wsFn) /
langgraph.CreateRetainNode(eng, wsFn) return graph NodeFuncs that inject recalled
memory as a SystemMessage every turn and store the latest turn automatically.
langgraph.WorkspaceFromUserID() gives per-user workspace isolation from the
run-scoped user_id.
See docs/langgraph-integration.md for the design
walkthrough.
CLI
ladym index ./src # index a codebase (incremental)
ladym recall "auth flow" # recall across code AND facts
ladym recall "auth flow" --code --json # code-only, machine-readable
ladym remember "..." --tags auth # store a fact
ladym record --agent claude --action "fixed login bug" --outcome success
ladym consolidate # L1 → L2
ladym worker --once # fire the System 2 L5/L6 extractors
ladym stats # what's in memory
Run ladym <command> --help for flags; ladym completion <shell> generates shell
autocompletion. Each indexed result carries the symbol's identity, signature,
docstring, body snippet, and source file — plus the callers/callees are queryable
via the symbol graph. That is what saves the agent from re-reading.
Configuration
Config resolves through (highest precedence first): CLI flags → LADYM_* env vars →
./ladym.toml → ~/.ladym/config.toml → built-in defaults. ladym --config <path>
loads an extra TOML file on top.
| Env var |
Default |
Purpose |
LADYM_DB |
./ladym.db |
SQLite path (one DB per project by default) |
LADYM_WORKSPACE |
default |
Multi-workspace isolation in a shared DB |
LADYM_EMBEDDING |
hashing |
hashing / openai / ollama / http |
LADYM_EMBEDDING_MODEL |
(provider default) |
Model name for a hosted embedding provider |
LADYM_EMBEDDING_BASE_URL |
(provider default) |
Override embedding API base URL (OpenAI/Ollama-compatible) |
LADYM_EMBEDDING_API_KEY_ENV |
(none) |
Name of the env var holding the embedding API key |
LADYM_LLM_PROVIDER |
none |
none / openai / anthropic / ollama / http |
LADYM_LLM_BASE_URL |
(provider default) |
Override LLM API base URL (OpenAI/Ollama-compatible) |
LADYM_LLM_MODEL |
gpt-4o-mini |
LLM model name for the consolidation classifier |
LADYM_LLM_API_KEY_ENV |
(none) |
Name of the env var holding the LLM API key |
LADYM_ENABLE_WAL |
true |
Enable SQLite WAL journal mode (default on so multiple processes can share one db; set false on filesystems without WAL support) |
base_url support lets you point embedding and LLM calls at any OpenAI/Ollama-compatible
endpoint (e.g. vLLM, LiteLLM, local Ollama); the http providers let you template an
arbitrary embedding/LLM HTTP API. Finer knobs (LADYM_EMBEDDING_TIMEOUT_S,
LADYM_LLM_MAX_TOKENS, LADYM_LLM_TEMPERATURE, per-op overrides under [agents], and
the recall/activation weights) live in TOML or on the config.Config struct — see
config/config.go. Secret literals in TOML are rejected with a
warning; use <name>_env indirection or the secret store below.
Secret store (encrypted keys at rest)
Provider API keys can be stored encrypted (AES-256-GCM) under ~/.ladyM/ instead of
being pasted into your shell rc or CI secrets:
ladym config set-master-key # first time: generate a random master key
ladym config set DEEPSEEK_API_KEY sk-... # store a key (encrypted)
ladym config list # list names (values never echoed)
ladym config rm DEEPSEEK_API_KEY # remove
ladym config reset-master-key <newpass> # rotate master key; all secrets re-encrypted in place
Key resolution order — LLM providers: Config.LLMAPIKey plaintext field (dev escape
hatch, only honoured with allow_plaintext_secrets, off by default) → secret store
(~/.ladyM/secrets.enc) → process env var named by api_key_env. Embedding
providers skip the plaintext tier, resolving: secret store → env var. If none is set,
commands fail fast with a one-line ConfigError naming the env var and the fix command
(exit 1; MCP tools return a structured error instead of a stack trace).
Security boundary: the store guarantees encryption at rest — it prevents plaintext
leaking via cat secrets.enc, shoulder-surfing, or accidental paste into chat/logs/commits.
It does not protect against full ~/.ladyM/ exfiltration: the master key and ciphertext
live in the same directory (the trade-off for non-interactive MCP / background workers that
must decrypt without a passphrase prompt). For stronger isolation, keep ~/.ladyM/ on
encrypted storage and rely on OS file permissions (dir 0700, files 0600). Losing
master.key makes all secrets unrecoverable — back it up.
More CLI surface:
| Command |
What it does |
ladym config |
Local web config editor (Go net/http + html/template, edits ladym.toml; flags: --port, --no-browser) |
ladym worker |
Background System 2 consolidation daemon; flags: --once, --interval N (seconds) |
Testing
go test ./... # full suite, fully offline
go test ./engine/ -v # one package
go vet ./... # lint
The whole suite runs without network and without model downloads — the default
HashingEmbedding is deterministic and dependency-free, so CI is hermetic.
Documentation
- ARCHITECTURE.md — full design: the six memory layers, cognitive
operations, two-tier retrieval, the ACT-R activation function, storage layout, and the
code-indexing subsystem. English only.
- scenarios/ — executable end-to-end scenarios (S01 write/recall, S03
code index, S07 L5 mental model, S08 L6 forward intent, S09 attention gate, …) that
double as a living spec. scenarios/README.md is in Chinese.
- docs/ — deep dives (code-indexing analysis, LangGraph integration).
- The Go test suite (
*_test.go beside each package) — the executable specification.
Status & roadmap
✅ Six-layer engine, two-tier recall, ADD/UPDATE/DELETE/NOOP consolidation,
proceduralization, decay, pure-Go tree-sitter indexer (full symbol specs for
Python/JS/TS/Go/Rust/Java/C/C++, line-window chunking for Kotlin/C#/Ruby/PHP/Swift/Scala/
Bash/Lua/SQL/HTML/CSS), MCP server, CLI, Skill, Go SDK, pluggable providers + TOML
config, System 2 background worker, L5 mental-model / L6 forward-intent extraction,
ladym config web editor, encrypted secret store.
🚧 Next: GraphRAG-style cross-file ref resolution and multi-modal episodes.
Contributing
Contributions are welcome. The fastest way to help:
- Run
go test ./... (hermetic) and go vet ./... before submitting.
- Add a scenario under scenarios/ or a
*_test.go beside the changed
package for any new behaviour — they are the spec.
- Keep the read path heuristic-only; route any LLM use through the System 2 worker.
For the design rationale behind any layer or operation, read
ARCHITECTURE.md first, then open an issue to discuss before large
changes.
Citation
If LadyM informs your research or project, a citation is appreciated:
@misc{ladym2026,
title = {LadyM: A brain-inspired, multi-tier memory framework for LLM agents and codebase RAG},
author = {ProjAnvil},
year = {2026},
url = {https://github.com/ProjAnvil/LadyM}
}
License
MIT © ProjAnvil