Long-term memory for AI-coded codebases. A git blame for AI agents — but for the why. MCP server that captures the agent's reasoning live, in context, as each change is made. Local SQLite, zero deps.
claude mcp add selvedge -- uvx selvedge{
"mcpServers": {
"selvedge": {
"command": "uvx",
"args": ["selvedge"]
}
}
}MCP Servers overview
<p align="center">
<img src="docs/wordmark.svg" alt="selvedge" width="480">
</p>
<p align="center">
<a href="https://selvedge.sh"><strong>selvedge.sh</strong></a>
·
<a href="https://pypi.org/project/selvedge/"><strong>PyPI</strong></a>
·
<a href="https://github.com/masondelan/selvedge"><strong>GitHub</strong></a>
</p>
<p align="center">
<a href="https://github.com/masondelan/selvedge/actions/workflows/test.yml"><img src="https://github.com/masondelan/selvedge/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
<a href="https://pypi.org/project/selvedge/"><img src="https://img.shields.io/pypi/v/selvedge?cacheSeconds=3600" alt="PyPI"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
</p>
<!-- mcp-name: io.github.masondelan/selvedge -->
**Long-term memory for AI-coded codebases.**
A `git blame` for AI agents — but for the *why*, not just which line which
model touched. Captured live, by the agent, as the change happens.
Selvedge is a local MCP server. AI coding agents (Claude Code, Cursor,
Copilot) call it as they work to log structured change events with
reasoning. Your data stays in a SQLite file under `.selvedge/` next to
your code.
---
Six months ago, your AI agent added a column called `user_tier_v2`. You don't
know why. `git blame` points to a commit from `claude-code` with a generated
message that says "Update schema." The session that made the change is long
gone — and so is the prompt that produced it.
With Selvedge, you run this instead:
```bash
$ selvedge blame user_tier_v2
user_tier_v2
Changed 2025-10-14 09:31:02
Agent claude-code
Commit 3e7a991
Reasoning User asked to add a grandfathering flag for legacy free-tier
users during the pricing migration. Stores the original tier
so we can backfill discounts without touching billing history.
```
That reasoning was **captured by the agent in the moment** — written into
Selvedge from the same context that produced the change. Not inferred from
the diff afterward by a second LLM. Not a hand-typed commit message.
---
<!-- DEMO GIF
Record a 30–45 second terminal session showing:
1. `selvedge status` → shows N total events
2. `selvedge blame payments.amount` → full output with reasoning
3. `selvedge diff users --since 30d` → table of recent changes
4. `selvedge search "stripe"` → filtered results
Use `vhs` (https://github.com/charmbracelet/vhs) or Asciinema.
Replace this comment block with: 
-->
---
## Who Selvedge is for
Selvedge has two audiences. Same tool, same `pip install`, same SQLite
file under `.selvedge/`. Different scale of pain.
**Teams running long-term, AI-coded codebases.**
When the project is big enough that you (or someone else) will touch it
again in six months, twelve months, three years — but most of it was written
by an agent whose context evaporated the day each PR shipped. `git blame`
tells you what changed. Selvedge tells you *why* — even after the agent
session, the prompt template, the developer who asked for it, and the model
version are all long gone. This is the original use case: production
codebases, schema decisions, migrations, dependency changes that need an
audit trail that survives turnover.
**Solo developers using Claude Code on everyday projects.**
Side projects, weekend builds, the small internal tool you keep poking at.
You don't need enterprise governance — you just need to remember why you (or
your agent) did the thing you did yesterday, last week, last sprint. Run
`selvedge init` once. Add four lines to your `CLAUDE.md`. From then on,
`selvedge blame` is muscle memory — a way to talk to your past self when
your past self was an LLM.
If you've ever come back to your own AI-built project and thought "what was
this *for* again?", Selvedge is the missing piece.
---
## The problem
Human-written code leaks intent everywhere — commit messages, PR descriptions,
inline comments, the Slack thread that preceded it. AI-written code doesn't.
The agent has perfect clarity about why it made each decision, but that
context lives in the prompt and evaporates when the conversation ends.
Six months later, your team is debugging a schema decision with no trail.
`git blame` tells you *what* changed and *when*. It can't tell you *why*.
**Selvedge captures the why — live, by the agent itself, as the change is
made.** The diff is git's job. The why is Selvedge's.
---
## What's new in v0.3.8
**Active memory v1 (date-based).** Selvedge's append-only log learns to know
when its own data is stale. A decision can now carry a revisit date, and the
new **`stale_decisions`** tool surfaces decisions that have aged out — but only
the ones whose entity is *still in active use*, so an old-but-correct decision
nobody touches never nags. **Drop-in upgrade for anyone on 0.3.7.** This brings
the MCP surface to **8 tools**.
### `revisit_after` + `stale_decisions` — decisions with an expiry date
Set `revisit_after` on an architectural `log_change` — an ISO date or a
relative offset like `90d`:
```jsonc
log_change({
"entity_path": "deps/stripe", "change_type": "add", "entity_type": "dependency",
"reasoning": "Pinned Stripe SDK to v11 for the billing launch.",
"revisit_after": "180d" // revisit this pin in ~6 months
})
```
Later, `stale_decisions` returns the dated decisions that have come due — and
filters out pure age:
```jsonc
stale_decisions({})
// → only decisions past their revisit date whose entity is STILL in use:
[
{
"entity_path": "deps/stripe", "change_type": "add",
"reasoning": "Pinned Stripe SDK to v11 for the billing launch.",
"revisit_due": "2026-...Z", "days_overdue": 12,
"active_use_signals": ["queried"],
"stale_reason": "past its revisit date and still active — the entity was queried (blame/diff/prior_attempts) after the decision."
}
]
```
**Pure age never surfaces.** A decision only comes back if the entity is still
live — recently queried (`blame` / `diff` / `prior_attempts`) or its changeset
kept moving. That's the noise defense: a dated decision nobody has touched won't
nag. Templated and deterministic — no LLM, ever. The pattern-based half
(`expires_when` grammar, explicit `reject`/`revert` change types) lands in
v0.3.11; the v0.3.8 migration adds the `expires_when` column now so that's a
no-migration release.
### CLI parity for the wedge + CLI-awareness
`selvedge prior-attempts <entity>` lands — the v0.3.7 `prior_attempts` wedge
was the only MCP tool without a CLI command. It's a thin presenter over the
same store, so `--json` emits the identical list the tool returns. New
`selvedge stale` mirrors `stale_decisions` (with `--json` for cron / Slack
jobs). And the canonical agent-instructions block now names the CLI equivalents
alongside the MCP tools, so a shell-having agent is never blocked when the MCP
server isn't loaded. Selvedge stays **MCP-first**; the CLI is the additive
second path.
See [`CHANGELOG.md`](CHANGELOG.md) for the full list, the one-time migration-v3
note (metadata-only `ADD COLUMN`, fast even on multi-million-event DBs), and the
called-out test-budget overage from the bundled CLI + agent-block work.
---
## What's new in v0.3.7
The brand-defining release: **`prior_attempts`** — the tool that lets an
agent ask "was this tried before, and how did it turn out?" *before* it
starts — plus the **entity-canonicalization foundation** it sits on.
**Drop-in upgrade for anyone on 0.3.6.**
### `prior_attempts` — the wedge
Given an entity (or a free-text description), `prior_attempts` returns the
prior change attempts on it, each annotated with an **inferred outcome**
(`reverted` / `active`), a **confidence** tier, and — for reverted attempts —
the reasoning explaining *why it was rejected*. Outcome is inferred from
add→remove proximity (no LLM, ever — it's a templated query over reasoning
the agents wrote live).
Worked example — an agent about to re-add a column it doesn't know was
already pulled:
```jsonc
// The agent is asked to keep mobile users signed in across restarts. Its
// instinct is to add a persistent token column. It checks FIRST:
prior_attempts({ "entity_path": "users.auth_token" })
// → one high-confidence hit: this was tried and reverted.
[
{
"entity_path": "users.auth_token",
"change_type": "add",
"reasoning": "Store a per-user auth token so the app stays signed in.",
"outcome": "reverted",
"confidence": "proximity_high",
"outcome_reasoning": "Reverted: DB tokens couldn't be revoked without a write; moved to short-lived JWTs."
}
]
```
The agent reads the rejection reason and **changes its plan** — a
refresh-token endpoint on the stateless-JWT path, instead of re-introducing
the column the team already pulled. Full
[demo transcript](docs/demos/prior-attempts.md).
**Conservative by design.** `min_confidence` defaults to `proximity_high`,
so `prior_attempts` only returns the clear "tried, then reverted" signal —
an empty list is the trustworthy "nothing to worry about" answer, not noise.
Pass `min_confidence="proximity_low"` to widen recall. Pull-only: the agent
decides when to ask. This is the
["alternatives tried, rejected paths"](docs/comparison.html) capability the
line-attribution tools don't have.
### Entity foundation (lands first)
`prior_attempts` is only as good as the entity matching under it, so v0.3.7
fixes the silent history-split problem first:
- **Canonicalization on write.** `src/auth.py::login` and
`./src/auth.py::login` used to resolve to *different* entities. Now every
write goes through one chokepoint that strips `./`, collapses `//`,
normalizes separators, and trims — **preserving case on purpose**
(filesystems differ; silently lowercasing would collapse genuinely distinct
entities on case-sensitive Linux). `selvedge doctor` warns on sibling paths
thaWhat people ask about selvedge
What is masondelan/selvedge?
+
masondelan/selvedge is mcp servers for the Claude AI ecosystem. Long-term memory for AI-coded codebases. A git blame for AI agents — but for the why. MCP server that captures the agent's reasoning live, in context, as each change is made. Local SQLite, zero deps. It has 8 GitHub stars and was last updated today.
How do I install selvedge?
+
You can install selvedge by cloning the repository (https://github.com/masondelan/selvedge) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is masondelan/selvedge safe to use?
+
masondelan/selvedge has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.
Who maintains masondelan/selvedge?
+
masondelan/selvedge is maintained by masondelan. The last recorded GitHub activity is from today, with 0 open issues.
Are there alternatives to selvedge?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy selvedge to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/masondelan-selvedge)<a href="https://claudewave.com/repo/masondelan-selvedge"><img src="https://claudewave.com/api/badge/masondelan-selvedge" alt="Featured on ClaudeWave: masondelan/selvedge" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
The fastest path to AI-powered full stack observability, even for lean teams.
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!
⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。