memspecBLOCK
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Memspec is Git-backed project memory for AI coding agents, with verification and drift detection. Claims about code are anchored to file SHAs; when the code changes, memspec flags the claim for review instead of letting facts rot silently. Duplicate rejection, typed supersede chains, and per-claim provenance turn memory into testable claims, not a notes file.
Markdown files under .memspec/ are the canonical source of truth: human-readable, git-diffable, greppable. Lose the index, lose speed — not data. No backend service. No hosted memory API. No vendor lock-in.
Architecture
Agents remember claims and observe notes; everything lands as markdown under .memspec/. From there a structured layer — lifecycle (active → superseded → retired), code anchors, typed links, and temporal validity — feeds FTS5/BM25 search, the MCP server, and session-start hooks, so the next session wakes up with the right context instead of amnesia.
Features
- File-canonical. Memories are markdown files with YAML frontmatter. Human-readable, git-diffable, greppable. Lose the index, lose speed — not data.
- Three claim types + observations.
fact,decision,procedurewith per-type TTLs;observationfor point-in-time notes with hard expiry. - Lifecycle, not curation.
active | superseded | retired. Corrections create a new memory linked back to the original; supersede chains preserve the reason on every record involved. Past TTL = stale flag at read time, never deletion. - Code-anchored verification. Tie memories to git blob SHAs. When code drifts, memspec flags drifted anchors for review instead of letting facts about code rot silently.
- Linked notes (v0
65ede2495a52OBSERVED · 2026-10-12Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control.
claude mcp add memspec -- npx -y [email protected]
{
"mcpServers": {
"memspec": {
"command": "npx",
"args": [
"-y",
"[email protected]"
]
}
}
}Exposed tools (14)
12 read · 2 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
memspec_anchor | read | Link a memory to the source files it depends on. Records the git blob SHA of each file so verify/reconcile can detect when the code a memory describes has changed. Anchoring also asserts the memory is true against the current file state. |
memspec_export | read | |
memspec_get | read | Retrieve the full content of a specific memory by ID, plus its lineage chain (what it supersedes, and what superseded it). Use after memspec_search when you need the complete body of a result or want to trace the history of a knowledge claim. |
memspec_observe | read | |
memspec_outcome | read | Record what happened after a retrieved memory was acted on: |
memspec_question | write | Create or edit a question group — a named question with competing answer records, the preferred form when two or more records answer one question (clearer than pairwise conflicts_with). Create: pass a |
memspec_reconcile | read | Find anchored memories whose code has drifted. Compares each active memory\ |
memspec_relate | read | |
memspec_remember | read | |
memspec_search | read | Search project memory before answering questions or starting work. Call this at the start of every task to load relevant context. Returns ranked memories (facts, decisions, procedures) matching the query. Trust the top-level |
memspec_status | read | Check memory store health. Counts by type/state/witness, stale flags, drifted anchors, declared and inferred conflicts, schema violations, and sweep candidates. v0.11 sections: |
memspec_supersede | write | Replace, retract, or merge memory. Body filled = replacement (new active record supersedes the old). Body empty = retraction. merge_from collapses N duplicates into one survivor atomically (use to consolidate near-duplicates surfaced by status). Reason is persisted durably on every record involved. |
memspec_unrelate | read | |
memspec_verify | read |
Trust audit
BLOCKgrade D · trust 67/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (1 observation(s))
- Network
- none-observed
- Shell
- declared (5 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (19)
/^(\.env(\..*)?|\.netrc|\.npmrc|\.pypirc|id_(rsa|dsa|ecdsa|ed25519)(\.pub)?|credentials(\..*)?|.*\.(pem|key|p12|pfx|jks|keystore|kdbx|ppk))$/i;
memspec-0.7.2.tgz
memspec-0.8.0.tgz
memspec-0.9.0.tgz
await writeFile(join(dir, 'aws.txt'), 'AKIAABCDEFGHIJKLMNOP\n');
await writeFile(join(dir, '.ssh', 'id_rsa'), '-----BEGIN OPENSSH PRIVATE KEY-----\nabc\n-----END OPENSSH PRIVATE KEY-----\n');
await writeFile(join(dir, 'notes.md'), 'deploy key:\n-----BEGIN RSA PRIVATE KEY-----\nMIIE\n-----END RSA PRIVATE KEY-----\n');
return createHash('sha1')sha = createHash('sha1').update(`blob ${content.length}\0`).update(content).digest('hex');const sha = createHash('sha1').update(`blob ${buf.length}\0`).update(buf).digest('hex');return createHash('sha1').update(`blob ${buf.length}\0`).update(buf).digest('hex');const sha = createHash('sha1').update(`blob ${passwd.length}\0`).update(passwd).digest('hex');await writeFile(join(dir, '.ssh', 'id_rsa'), '-----BEGIN OPENSSH PRIVATE KEY-----\nabc\n-----END OPENSSH PRIVATE KEY-----\n');
assert.throws(() => validateEvidenceSource(root, join(dir, '.ssh', 'id_rsa')), /refusing evidence from a hidden path .*"\.ssh"/);
for (const bad of ['.ssh/id_rsa', 'server.pem', 'notes.md']) {assert.throws(() => validateEvidenceSource(root, join(dir, '.ssh', 'id_rsa')), /looks like a secret by name/);
assert.equal(anchorWithinBase(base, '../../etc/passwd'), false);
for (const repo of ['/etc', '../../../../../../../etc', '.', '..', 'a/b', 'a\\b']) {@modelcontextprotocol/sdk, better-sqlite3, commander, gray-matter, ulid, zod, @types/better-sqlite3, @types/node
Gates applied: no_behavioural_pass.
65ede2495a52full audit observations/trust-audit/mcp-server/siimvene__memspec.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | 65ede2495a52 | BLOCK | D | 67 | first audit |
Questions
What tools does memspec expose?
14 in total: 12 read-only, 2 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is memspec safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (67/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on.
What credentials does memspec need?
No credential environment variables were found in its source, so it appears to need none.
How does memspec run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as memspec at 0.11.0.
How current is this page?
The grade is for one exact copy of the source (65ede2495a52), read on 2026-10-12. The repository is watched and re-audited when it changes.