v0.23.0 · 2026-10-08 · pre-1.0 · open source

Typed project knowledge for AI agents.

Memstead is a local engine for knowledge your agents maintain: typed markdown files in your repository or in git, read and written over MCP and the command line. A schema decides what each kind of note must hold, and the engine refuses a write that does not fit, naming what is missing.

If your agents already keep notes or a wiki in markdown, this is that habit with a schema in front of it, typed links between the notes and a recorded writer for every change.

Build something on it, and tell us what breaks.

Every push runs 3,716 Rust test functions on Linux and macOS, feeds the parsers that read outside files 25,500 generated inputs, and drives the release binaries from outside. A coverage-guided fuzzer runs on demand, and every release archive carries signed build provenance (how it is tested). It is pre-1.0, so commands and file formats can still change between releases: pin a version when you build on it. Pick an idea below, or bring your own.

  1. Installcurl -sSf https://memstead.com/install.sh | sh
  2. In a repositorymemstead quickstart --repo .
A real mem drawn as a plan: one room per type of note, sized by how many notes it holds and shaded by how many links each note carries on average. Memstead's own introduction, 50 notes of 9 types and 205 links, read when this page was built.

How it works

The schema refuses a wrong write.

Required sections and fields, allowed values, which links may connect which types. A write that breaks the schema is refused with a typed code and what is missing, and nothing reaches disk.

Links are typed and checked.

An edge has a type the schema declares, with allowed endpoint types and, where declared, no cycles. A link to a note that does not exist yet becomes a visible placeholder.

The files are yours, in git.

Markdown with frontmatter in a folder of your project, or a git repository the engine writes with one commit per change. Every change records who made it and, when given, why.

Agents over MCP, people over the CLI.

memstead-mcp serves 21 tools to Claude Code, Cursor, Gemini CLI, Codex or any MCP client. memstead has 93 commands and subcommands, with the same results as JSON.

Three refusals, from simple to strict

A small plan schema written for this example: steps that depend on other steps, and criteria that decide when a step is done. Everything below is the 0.22.0 binary's own output, recorded on 2026-10-01; long payloads are cut where marked.

  1. A note lacks what its type requires.

    The rule a linter could check too: a criterion must say how to run it.

    memstead: ERROR [MISSING_REQUIRED_SECTION]: missing 1 required section(s) for type 'criterion':
      - 'check' (Check) — write_rules: The command or observation that passes or fails; concrete enough for someone else to run
    [trimmed]
  2. A link would make the plan go in circles.

    A rule over two notes: dependencies may not loop, and a criterion, not a step, may decide a step.

    $ memstead relate release--migrate-the-store DEPENDS_ON release--ship-the-export-command
    memstead: ERROR [RELATIONSHIP_CYCLE]: creating edge DEPENDS_ON from 'release--migrate-the-store' to 'release--ship-the-export-command' would close a cycle in the DEPENDS_ON subgraph — existing path: release--ship-the-export-command → release--migrate-the-store; remove an edge along this path to break the cycle, then retry
    [details trimmed]
    
    $ memstead relate release--ship-the-export-command VERIFIES release--migrate-the-store
    memstead: ERROR [INVALID_REL_SHAPE]: relationship 'VERIFIES' from type 'step' to type 'step' violates declared shape — allowed sources: criterion; allowed targets: step. Suggested rel-type: 'DEPENDS_ON'.
  3. A step is marked done before someone else checked it.

    A rule over content, history and identity. The author's own check does not count. The reviewer's does, until the author quietly weakens the criterion; then it is stale, and the step stays open until the reviewer checks again.

    # agent-a wrote the step and its criterion, and checked the criterion itself
    $ memstead update release--ship-the-export-command --metadata status=done
    memstead: ERROR [CONSTRAINT_UNSATISFIED]: write refused: […] transition_requires_checks: status=done requires a fresh confirming check record on every entity related via [VERIFIES] — unconfirmed: 'release--export-round-trips-byte-identically' (self_checked)
    
    # reviewer checks it; then agent-a rewrites the criterion's check to something easier
    $ memstead update release--ship-the-export-command --metadata status=done
    memstead: ERROR [CONSTRAINT_UNSATISFIED]: write refused: […] unconfirmed: 'release--export-round-trips-byte-identically' (check_stale)
    
    # reviewer checks the new wording
    $ memstead update release--ship-the-export-command --metadata status=done
    # Updated `release--ship-the-export-command`
    - Metadata: status (set)

    The rule that does this, from the schema's step type:

    constraints:
      - kind: transition_requires_checks
        field: status
        to_value: done
        relationships: [VERIFIES]
        direction: incoming
        min_related: 1
        severity: block

The identities (agent-a, reviewer) are declared by the caller, not authenticated: the rule keeps an honest team honest and leaves a tamper-evident trail; it is not access control. Lab commands also carried --role and --auto-hash, left out above.

Get started

  1. 1 · Installcurl -sSf https://memstead.com/install.sh | sh
  2. 2 · In a repositorymemstead quickstart --repo .
  3. 3 · Thenrestart your agent and ask it to record a decision and its reason

The installer puts memstead and memstead-mcp into ~/.cargo/bin and adds that directory to your shell's PATH through its startup files unless INSTALLER_NO_MODIFY_PATH=1 is set. Or brew install memstead/memstead/memstead-cli memstead/memstead/memstead-mcp, or cargo install memstead-cli memstead-mcp, or a release archive you check yourself (how). In an empty folder, memstead quickstart without --repo. A running agent session does not pick up a newly added MCP server, hence the restart.

Ideas to build

Ideas for what to build on the engine. Two of them run in this project's own work; the rest wait for someone to try them.

Each card opens what you build, what carries it, three commands to start, and where it stops. Where a card shows output, it is the engine's own, recorded on 2026-10-01.

Gaps worth building on top of the engine, and what it leaves out on purpose
  • A bridge to the open knowledge format other wiki tools write (OKF): read a folder of OKF notes in as entities through the checked write path, write a mem back out.
  • A duplicate and contradiction finder. The engine ships none; search, typed links and the change feed give such a tool its material.
  • A graph view of a mem. The engine ships no renderer by design and leaves drawing to exports: memstead export --format json has the nodes and edges.
  • A watcher for cited web pages. The engine never touches the network; a script fetches the pages on a schedule and feeds what it saw to memstead verify-anchors --observations, which is the intended route.

Left out on purpose

  • Semantic search. No embeddings and no vector index, by design: the store is the exact layer and the agent reading it is the semantic layer. Search is BM25 over words with typed filters.
  • A one-shot import of a notes folder. Every note enters through a checked write. The declared path for an existing source is a binding plus the Claude Code plugin's /ingest skill, which builds the mem batch by batch.
  • Calculation. The engine holds the inputs and names what is missing; it never computes a sum or fills a form.

built-in schema: default

A decision log with a CI guard

What you build

Your agent records decisions, rules and their reasons as notes in the repository. Each note carries an anchor to the files it describes. A CI job runs verify on every push and exits 6 when an anchored file changed since the note was written, so someone looks at the note again. Verify also counts every file in the binding's scope that no note covers, so narrow the scope or exclude what needs no note before the job gates anything.

What carries it

The built-in default schema (principle, assertion, process and seven more types), a binding that names the repository as the source, file and span anchors, projection verify.

Start

memstead quickstart --repo .
# restart the agent; ask it to record a decision, anchored to the file it is about
memstead projection verify <mem>/<binding> --full --fail-on-findings   # in CI; exclude files that need no note first

Real output

-MAX_DELAY_SECONDS = 30
+MAX_DELAY_SECONDS = 90

$ memstead projection verify bookshelf/bookshelf --full --fail-on-findings
**Verdict: DRIFTED** — 2 finding(s) recorded over the current key (drifted: 2).
[trimmed]
exit 6

$ memstead anchors --mem bookshelf
- `bookshelf--catalogue-retries-never-wait-longer-than-30-seconds` — anchored file `src/retry.py` (hash: 25d22160c66a77b7, state: drifted)
[trimmed]

A throwaway repository: an agent's note capped retries at 30 seconds; a commit raised the cap to 90.

Where it stops

Verify notices that an anchored file changed, not that a note is wrong. The report counts the moved files; memstead anchors names the notes. A file anchor fires on every change to that file.

built-in schema: default

Ops runbooks an agent can follow

What you build

One process note per runbook. The default schema's process type requires a trigger and preconditions, and gives steps and failure paths their own sections. An agent that writes a runbook without them is refused and told what each section must hold.

What carries it

The built-in default schema's process type; typed links such as REQUIRES and TRIGGERS between runbooks.

Start

memstead quickstart --repo .
# ask the agent: record how a deploy rollback works, as a process
memstead search rollback --type process

Real output

ERROR [UNKNOWN_SECTION]: unknown section 'purpose' for type 'process' — declared sections: postconditions, preconditions, steps, trigger, variations. Did you mean 'postconditions'?

What an agent got back over MCP when it guessed a section name. Its next two writes fixed it.

Where it stops

The engine stores and checks runbooks; it runs nothing and schedules nothing.

built-in schema: obligation

Contracts, duties and deadlines

What you build

Each duty is an obligation note with a due date and a stated consequence, linked to the party and the commitment it comes from. memstead due lists what falls due in the next 90 days, overdue first.

What carries it

The built-in obligation schema (obligation, party, commitment, decision) with its due-date axis; memstead due.

Start

memstead init --name contracts --schema obligation@0.1.0
memstead create --type obligation --title "Annual boiler inspection"   # refused until it is complete
memstead due

Real output

memstead: ERROR [MISSING_REQUIRED_SECTION]: missing 2 required section(s) for type 'obligation':
  - 'duty' (Duty) — write_rules: Who owes what, to whom, by when — one paragraph, citing the source (link the commitment or evidence entity).
  - 'consequence' (Consequence) — write_rules: What is forfeited, incurred, or lost when the due date passes unmet. State it concretely — this section is why the entity exists.
[trimmed]

Where it stops

Due is a query. The engine sends no reminder; a cron job or CI step that runs memstead due does.

built-in schema: software

Requirements for regulated software

What you build

Each requirement is a note with a MUST or SHOULD statement and its rationale, linked to the specs that satisfy it. A reviewer records a check against a requirement's current content; an edit makes that check stale until it is checked again.

What carries it

The built-in software schema (requirement, spec, decision, incident and five more types), typed links, memstead check with --identity.

Start

memstead init --name payments --schema software@0.5.0
memstead create --type requirement --title "Refunds settle within five business days"
memstead check <id> --verdict ok --identity reviewer --method "read against the spec"

Real output

memstead: ERROR [MISSING_REQUIRED_SECTION]: missing 2 required section(s) for type 'requirement':
  - 'statement' (Statement) — write_rules: One sentence. Starts with the subject followed by MUST, SHOULD, MAY, MUST NOT, or SHOULD NOT (RFC 2119).; Testable: a reader should be able to judge, given a system state, whether the statement holds.
  - 'rationale' (Rationale) — write_rules: Why this requirement exists — what risk, regulation, or goal drives it. Enough context to judge whether the requirement still applies.
[trimmed]

Where it stops

Identities are declared by the caller, not authenticated, so a check is not an electronic signature. For publishing specification documents, StrictDoc and sphinx-needs are mature.

in use here

built-in schema: default

A claims register for docs or a website

What you build

Each statement a page makes is a note, anchored to the file, record or web page it rests on, with the exact words it quotes. A verify run reports the statements whose source changed or whose quoted words are gone. This site's own statements are kept this way.

What carries it

Span and url anchors with quoted phrases, the quoted-phrase preparation, verify-anchors --observations for pages a script fetched.

Start

memstead quickstart --repo .
# ask the agent: record each claim on the page as a note, anchored with the words it quotes
memstead projection verify <mem>/<binding> --full

Where it stops

It notices a moved source, not a statement that was wrong from the start. The engine fetches no web page; a script fetches and feeds in what it saw.

in use here

your own schema

Agent work plans with gates

What you build

A plan is a mem; each step is a note with acceptance criteria. The schema declares that a step may move to done only when every criterion that verifies it carries a check by another identity against the criterion's current content. memstead gates lists the open steps in dependency order, which is what an unattended loop picks its next step from.

What carries it

A schema you write with gated transitions; memstead check, memstead gates, health --strict.

Start

memstead gates
memstead check <criterion> --verdict ok --role checker --identity reviewer --method "ran the suite"
memstead update <step> --auto-hash --metadata status=done   # refused without that check

Where it stops

No built-in schema declares gates; you write the schema. Identities are declared, not authenticated. On 0.22.0, two writes from separate processes at the same moment can both land; the fix is in the source, not yet released.

built-in schema: planning

One hard decision, planned

What you build

A small mem for one decision that takes days: the goal, the options, the risks each option carries, the open questions, and finally the decision. Typed links tie an option to the goal it serves and a risk to the option it threatens.

What carries it

The built-in planning schema (goal, option, decision, step, risk, open_question, note); memstead overview.

Start

memstead init --name choose-a-database --schema planning@0.4.0
# ask the agent: lay out the options for the goal, with their risks
memstead overview

Where it stops

planning@0.4.0 asks for a date and deciders even on a decision that is only proposed.

any mem

A knowledge package to hand on

What you build

Seal a mem with its schema and its check records into one .mem file. Whoever installs it gets it mounted read-only; the engine tags every entity it serves from it as third-party and withholds the schema's instruction prose from the receiving agent.

What carries it

memstead export --format mem, memstead install, the third-party trust model.

Start

memstead export --format mem
# hand the .mem file over
memstead install <file.mem>

Where it stops

There is no public registry. An archive cannot link into another archive. The engine cannot stop an agent from acting on the text it reads.

your own schema

Metric definitions anchored to SQL

What you build

One note per metric: the definition in words, who owns it, the decisions behind it, and a span anchor on the lines of the SQL file that compute it. A dashboard number with a changed query shows up in verify.

What carries it

A small schema of your own (metric, source table, owner), span anchors with line locators, projection verify.

Start

memstead schema new metrics   # a package folder; edit its types
mkdir notes && cd notes && memstead init --name metrics --schema default@1.3.0
memstead schema install ../metrics && memstead mem set-schema metrics metrics@0.1.0

Where it stops

Nobody has built this yet. The anchors and the check exist; the schema and the habit do not. Verify needs a binding over the SQL folder (memstead projection init).

your own schema

A research evidence graph

What you build

Claims, sources and objections as notes, with support and attack as typed links. The schema language can declare attack relationships, require a path from every claim to evidence, and forbid circular support; health then labels which claims stand.

What carries it

Schema features no built-in uses yet: attack relationships with grounded labelling, must_reach, acyclic sets; memstead health.

Start

memstead schema new evidence   # a package folder; edit its types
mkdir notes && cd notes && memstead init --name evidence --schema default@1.3.0
memstead schema install ../evidence && memstead mem set-schema evidence evidence@0.1.0

Where it stops

Nobody has built this yet. The engine draws no argument map; it computes the labels.

your own schema

A world bible for long fiction or games

What you build

One note per character, place, faction and event, with typed links (born in, member of, happens before). Required sections keep every character sheet complete; an acyclic happens-before keeps the timeline from looping.

What carries it

A schema of your own, typed links with endpoint types, acyclic relationships, overview clusters.

Start

memstead schema new world   # a package folder; edit its types
mkdir notes && cd notes && memstead init --name world --schema default@1.3.0
memstead schema install ../world && memstead mem set-schema world world@0.1.0

Where it stops

Nobody has built this yet. The schema checks shape; whether a scene contradicts a character is still the writer's call.

your own schema

An FMEA for a hardware product

What you build

One note per failure mode, linked to its effects, causes and the control that catches it. A required outgoing link makes a failure mode without a control a health finding; a reviewer's check goes stale when the note changes.

What carries it

A schema of your own with required outgoing edges, memstead check, health --strict in CI.

Start

memstead schema new fmea   # a package folder; edit its types
mkdir notes && cd notes && memstead init --name fmea --schema default@1.3.0
memstead schema install ../fmea && memstead mem set-schema fmea fmea@0.1.0

Where it stops

Nobody has built this yet. The engine computes no risk priority numbers; it does not calculate.

What is in the box

The engine's features in ten families, each with the release it arrived in and what it leaves out.

Each card opens one line per feature with the release it arrived in, a link to the reference for the detail, and what the family does not include. Counts are read from the source this page was built from.

7 features

Files and storage shapes

Not included

No merge of diverged histories: pull only fast-forwards. A folder workspace has no atomic batches, forks or proposals; those need a mem-repo.

Detail

Getting started · Back up a mem-repo

10 features

The schema language

Not included

No numeric ranges, no enforced cardinality beyond at least one required link, no rules that span two mems.

Detail

Write a schema

6 features · 263 typed error codes

Validation and typed refusals

Not included

Shape, not truth: a note that passes every check can still be wrong.

Detail

Error code index

8 features

The typed graph and its health

Not included

No graph rendering, no computed totals: the engine counts edges and labels nodes, nothing more.

Detail

CLI reference

6 features

Concurrency and provenance

Not included

On 0.22.0, two writes from separate processes racing with the same hash can both be accepted; the fix is in the source, not yet released. Identities are declared by the caller, not authenticated.

Detail

MCP tools

5 features

Search and reads

Not included

No semantic search and no embeddings, by design; no stemming. The index is rebuilt in memory at every load.

Detail

MCP tools

8 features

Sources, anchors and drift

Not included

The engine never fetches anything and never writes an entity from a source; an agent repairs through the checked write path. It notices a moved source, not a wrong note.

Detail

Grow a mem from a source · Verify in CI

6 features

Plans, checks and gates

Not included

No authentication: a check is not an electronic signature. No scheduler, no reminders, no notifications.

Detail

Write a schema

6 features

Packaging and sharing

Not included

No public registry and no hosting. An archive cannot link into another archive.

Detail

Publish a mem · Review a proposal

6 features · 93 CLI commands and subcommands · 21 MCP tools

Interfaces

Not included

Windows builds are published and untested. The crates carry no API promise. The WebAssembly build has no search, and its npm package stopped at 0.18.1.

Detail

CLI reference · MCP tools · Parity

Who builds it, and where it stands

Built by

Memstead is built by one developer, Björn Bösenberg in Berlin, who directs AI agents and writes no code by hand. The engine also carries Björn's other projects: installable packages of curated, cited reference knowledge; a document analysis that models what a body of records says and what follows from it; the project knowledge behind a client website; and Trustillery, a public project that keeps evidence as checkable collections anyone can challenge with a proposal.

The engine's own work plans are mems. Each step is a note that the schema lets close only after a different identity has recorded a check against its current content, and an unattended agent loop picks its next step from the open gates.

Status

Pre-1.0: commands, schemas and file formats can still change between releases. One developer, no outside review yet. Windows builds are published and untested. Every measurement, with its method and its limits, is in the reference below; so is how the engine is built and tested.

Not claimed, not included

RetrievalNot the engine's job. It works on the write side; how good an answer is depends on the agent that reads the mem, and the engine ships no retrieval layer of its own. The read-side measurements are in the evidence.
TruthThe schema checks shape, not truth. A note that fits can still be wrong.
Automatic memoryNone. Nothing enters a mem by itself; every note is a write that passed the schema.
Simultaneous writersOn 0.22.0, two writes from separate processes at the same moment can both be accepted, and the later one overwrites the earlier. Found on 2026-10-01; the fix is in the source and not yet released.
Database, vectorsNone. The store is markdown and git; search is full text and structure, with no embeddings.
Registry, hostingNone. No account, no hosted service, no public catalogue of mems.

Join in

Something broke?

Open an issue with what you ran and what came back. A refusal you did not understand counts. GitHub issues

Built something?

Post it under Show and tell, with the schema if you wrote one. GitHub Discussions

Want to change the engine?

Pull requests go through the same machine checks as the maintainer's own work. CONTRIBUTING.md

Questions worth asking first

The terms used on this page are defined in GLOSSARY.md. How Memstead relates to agent-memory systems and other neighbours is in PRIOR_ART.md.

Is this a database?

No. There is no server process holding the data, no query language, no transaction across mems and no replication. The store is markdown files or git objects, and the search index is rebuilt in memory at every load. One database idea does carry over: the schema refuses a write that breaks it, as a table's constraints do. The records, though, are prose documents a person reviews as a diff.

What happens when two agents write at once?

Each update names the hash of the version it read. If another write has completed in between, the update is refused with HASH_MISMATCH and the current hash, and nothing is merged. Two writes racing at the same moment from separate processes are not yet serialized on 0.22.0: both can be accepted, and the later one overwrites the earlier (fixed in the source, not yet released). Before every operation the engine checks whether another process changed the mem, reloads it, and says so in the response (MEM_RELOADED), so the agent knows its cached hashes are stale. Across two machines nothing merges by itself: pull refuses a diverged branch, and a second line of work goes through memstead mem fork and a reviewed memstead proposal merge.

Why not let the agent read the code?

For questions about how the code behaves, it should. A mem is for what the source does not contain: why a decision went the way it did, which rule applies where, what a part is meant to do. The project measured the difference on its own engine (§6).

Who builds this, and how?

One developer, Björn Bösenberg in Berlin, who directs AI agents and writes no code by hand. No person reads each change before it lands; the checks in §5 stand in for that review, and the contribution guide applies the same gates to outside pull requests. The project's own decisions are public as a mem in engineering/. By the project's own account, work began in mid-February 2026; the public history starts on 2026-07-01.

How is this different from an instruction file such as CLAUDE.md or AGENTS.md?

An instruction file is free text the agent loads at the start of a session, and nothing checks what goes into it. A mem is typed: the schema refuses a malformed write, links are checked edges, every change is recorded, and the agent searches it rather than loading all of it. The two work side by side.

Which agents does it work with?

Any agent that speaks MCP. memstead quickstart writes the wiring for the ones you pick among Claude Code, Cursor and Gemini CLI, and prints the one command for Codex; any other client points at the memstead-mcp binary.

Does it work offline?

Yes. The engine, the CLI and the MCP server run on your machine and read files you control. The network is needed to download the binaries, and by the commands that talk to a git remote or a registry you name.

Who owns my data?

You do. Mems are markdown files in your project or in a git repository you hold. There is no account and no hosted service, and the files stay readable if you stop using Memstead.

How big can a mem get?

It is designed for 1,000 to 5,000 entities, with no hard cap. At 5,000 entities a cold command took about a quarter of a second on the measured machine, and the cost grows linearly beyond that (§4).

Is it safe to mount someone else's mem?

A mem is data your agent queries, not instructions it should obey. The engine mounts an installed mem read-only, serves its schema as structure only, withholds the schema's instruction prose, and tags every entity it serves as third-party. It cannot stop an agent from acting on the text, so treat installed content as quoted data.

Can I share a mem?

As a file: memstead export --format mem seals it into one .mem file, and memstead install <file> mounts it read-only. The CLI can also publish to a registry you name with --registry; there is no public registry.

Reference

The specification, the method, every measurement and the history, folded so the page stays short; every word is in the page source. Terms are defined in GLOSSARY.md.

§1ContractWhat a write is guaranteed, and what it is not.
§1Contract

What a write is guaranteed, and what it is not.

A schema works on your agent's notes the way constraints work on a table: a write that breaks it is refused, with the reason. The comparison with a database ends there (Questions).

Guaranteed

Every writeis checked against the mem's schema before anything reaches disk: the entity type, required sections and fields, field types, allowed values and patterns, relationship types and their endpoint types, acyclic relationships, and every further rule the schema marks as blocking. A write that fails is refused with a typed code and a details payload naming what is missing or allowed. Nothing is written, and the CLI exits 5.
Every updatenames the content hash of the version it read. If another write has completed since, the write is refused with HASH_MISMATCH and the current hash (exit 4), and nothing is merged. Two writes racing at the same moment are another case (see below). Over MCP the hash is required. On the CLI, --auto-hash and --force relax the check, each only when you pass it.
Every linkis a typed edge checked against the schema. A relationship type the schema does not allow, a wrong endpoint type, a cycle in an acyclic relationship, or a link into another mem that the workspace configuration does not grant is refused. A link to an entity that does not exist yet creates a stub, an empty placeholder, and reports it as a warning. A delete is refused while other entities still point at the target.
Every changeis recorded. In a mem-repo, a git repository the engine writes with one branch per mem, each change is one git commit carrying the operation, the acting client and, when given, a role, an identity and the writer's note. In a folder mem, a plain folder in your project, it is one line in the mem folder's .memstead/changes.jsonl.
Every batchbatch-create, batch-update and batch-relate (mem-repo workspaces) land completely or not at all, and a refused batch names every failing entry.
Every readis deterministic. No model is called on the query path, so the same files give the same answer.

Not guaranteed

TruthThe schema checks shape, not truth. A write that conforms can still be wrong. In the blind battery of 2026-09-06, answers drawn from a mem that had passed every write check still carried claims the source code refuted (§6).
RetrievalNot a goal. The schema's job is to refuse a malformed write; answer quality depends on the reading agent, and in a controlled eval typed and equally curated plain notes scored alike (§6).
Automatic captureNone. Nothing enters a mem by itself: the engine records nothing from conversations and imports no folder of notes. Every entity is a write that passed the schema.
Outside editsA folder mem sees changes made through the engine. A file edited by another tool goes unnoticed, and reads serve the old content until a reload (OUT_OF_BAND_EDITS_UNDETECTED). A mem-repo compares its branch head before every operation.
Simultaneous writersOn 0.22.0 the hash check and the write are not atomic across processes. Two writes racing at the same moment with the same hash can both be accepted, and the later one silently overwrites the earlier. This was found on 2026-10-01 with parallel writers on both workspace shapes; the fix is in the source and not yet released.
Two repositoriesA change that touches mems in two git repositories is two commits that can fail independently.
Who wrote it--role and --identity are declared by the caller and not verified. History makes them tamper-evident, not true.
$ memstead create --type principle --title "Every write carries an idempotency key"refused · exit 5
memstead: ERROR [MISSING_REQUIRED_SECTION]: missing 2 required section(s) for type 'principle':
  - 'statement' (Statement) — write_rules: One or two sentences. The rule, law, or constraint. Must be testable: can you check whether something violates it?
  - 'scope' (Scope) — write_rules: Where this principle applies. Domain, context, conditions. A principle without scope implies universality — state it explicitly if so.
every-write-carries-an-idempotency-key.mdaccepted
---
type: principle
created_date: 2026-09-30T11:29:17Z
last_modified: 2026-09-30T11:29:17Z
authority: proposed
universality: contextual
---

# Every write carries an idempotency key

## Statement
Every mutating endpoint requires an idempotency key, so a retried payment never charges twice.

## Scope
The public payments API and every internal service that writes to the ledger.

The first lines of the engine's refusal, verbatim, and the file it writes once the same note carries its two sections.

§2FitWhere a mem pays off: the material the code does not say, kept free of malformed writes.
§2Fit

Where a mem pays off.

A mem is meant for what the code does not say: decisions and their reasons, rules and where they apply, intent, how the parts are meant to fit. The engine keeps that material in a form every writer must follow, with a recorded writer for every change.

On the write side, a pre-registered ten-round comparison with a plain markdown folder found the schema-checked knowledge base free of duplicates and contradictions (0 per 100 items, against 8.13) while it held twice as many items. Its mechanism is not identified: the engine ships no duplicate or contradiction detector, and the control arm with a plain linter was not run.

The read side is not what the engine sets out to improve, and the measurements agree. Typed entities did not help an agent answer better than equally curated notes (0.973 against 0.983, scores from 0 to 1). In the same ten-round comparison the schema-checked side answered its question battery worse (0.286 against 0.575), and a substantial part of that gap is material its writers never recorded. For questions about how code behaves, reading the code did better than reading the mem: on eleven fixed questions about Memstead itself, 9 to 2. Method and limits of every figure are in §6.

The schema checks shape, not truth. A conforming entity can still be wrong, and the engine's answer to that is review rather than validation: every change is a diff with a recorded writer.

§3PathFour steps from install to an answer that names its sources.
§3Path

Four steps from install to an answer that names its sources.

  1. Install the binaries.curl -sSf https://memstead.com/install.sh | shInstalls memstead and memstead-mcp into ~/.cargo/bin. The script runs the two installers each release publishes, and each checks the SHA-256 of the archive it downloads. Unless ~/.cargo/bin is already on your PATH, the installers add it through your shell's startup files (.profile, .bashrc, .zshrc, the fish configuration); INSTALLER_NO_MODIFY_PATH=1 leaves them alone. sh -s -- --version <tag> pins a release. To remove Memstead, delete the two binaries and the install receipts under ~/.config/memstead-cli and ~/.config/memstead-mcp.
  2. Start a workspace in your repository.memstead quickstart --repo .Creates .memstead/ with the workspace state and a binding, the declaration that names the repository as the mem's source so the engine can report when the two drift apart; a mem in a folder of its own holding one seed entity and pinned to the built-in default schema; and the MCP wiring for the agents you pick when it asks: .mcp.json for Claude Code, .cursor/mcp.json for Cursor, .gemini/settings.json for Gemini CLI. For Codex it prints the codex mcp add command instead. --agent skips the question; without a terminal it wires Claude Code. It reads no source file and adopts none of your files as entities. In an empty folder, memstead quickstart does the same without the binding.
  3. Restart the agent, then let it write.Restart the agent session afterwards: a session that is already running does not attach an MCP server added while it runs. Then ask the agent to record something the code does not say: a decision and its reason, a rule, how two parts are meant to fit. A write that does not conform comes back refused with what is missing (§1), and the agent can write it again with the fix.
  4. Ask in a new session.The new session finds the entities over MCP. Ask it to name the entities it used: each id maps to a markdown file you can open, and memstead entity <id> --provenance shows which client created it and which last changed it.
§4SpecificationThe engine, as a specification.
§4Specification

The engine, as a specification.

Data model

  • A mem is a graph of typed markdown entities about one subject. It pins one schema by exact version, name@version.
  • An entity is one markdown file: YAML frontmatter for metadata, level-two headings for sections, a ## Relationships list for typed edges. Its id is <mem>--<slug>. Its _hash, the first 16 hex characters of a SHA-256 over its markdown, is the token an update must present.
  • A schema is a YAML package. For each entity type it declares sections (required or optional, optionally with a markdown shape), metadata fields (string, number, date or boolean, with allowed values and patterns) and constraints. For the mem it declares the relationship vocabulary: endpoint types, acyclic relationships, and which relationships may point into another mem. The built-in schema default@1.3.0 has 10 entity types and 37 relationship types; memstead type lists the types of the schema a mem pins.
  • A workspace mounts mems. One engine process serves one workspace, and a link from one mem into another needs a grant in the workspace policy.
  • concept 10 · 13.5 links
  • guide 10 · 7.6 links
  • claim 7 · 4.7 links
  • limit 6 · 3.5 links
  • principle 6 · 11.5 links
  • behavior 5 · 6.2 links
  • stance 3 · 7 links
  • meta 2 · 8.5 links
  • story 1 · 7 links

fig. 1 · The plan of a real mem, read when this page was built: Memstead's own introduction, 50 entities of 9 types. That mem itself is not published. One room per entity type: area by entity count, shade by the average number of typed links per entity of that type.

Two storage shapes

Folder memMem-repo
Created bymemstead quickstart, memstead initmemstead mem-repo init, then memstead mem init per mem
Mems per workspaceonemany
Entity files.md files in the mem's folderfiles on the branch <mem> of mem-repo/.git
Change recordone JSON line per change in the mem folder's .memstead/changes.jsonl; your own git versions the filesone git commit per change, with trailers
Atomic batch-* commands, recoverrefused (UNSUPPORTED_WORKSPACE_SHAPE)available
A change by another process is noticed bythe change log's last entry (engine writes only)the branch head
Moving between machinesyour own gitmemstead push, fetch, and pull (fast-forward only)

Concurrency

Writes are optimistic. An update carries the hash it read; if another write has completed since, HASH_MISMATCH returns the current hash and nothing is written. On 0.22.0 the check and the write are not atomic across processes, so two writers racing with the same hash can both succeed (see Not guaranteed, §1). Before every operation the engine compares each mem's head with what it loaded; when another process has written, it reloads that mem and attaches a MEM_RELOADED warning and a mem_changed notice listing what changed.

The limits: a folder mem notices only engine-made changes; mems in two git repositories change in two independent commits; pull refuses a branch that has diverged. A second line of work goes through memstead mem fork and a reviewed memstead proposal merge. An entity edited on both sides is shown in all three versions and never merged automatically.

Reads

No model is called on the read path. Search ranks with BM25 plus title and per-section weights, itemised on every hit, and filters by type, metadata and graph distance. There are no embeddings and no vector index. The search index is built in memory at load and never written to disk. memstead overview groups entities into clusters with Louvain community detection, within a token budget. memstead health reports orphans, stubs, stale entities, dangling links and schema constraints; --strict exits 1 on any unacknowledged finding.

Interfaces

  • CLI, memstead: 93 commands and subcommands. --json returns the same shape as the MCP server. Exit codes: 0 success, 1 other failure, 2 usage error, 3 not found, 4 hash conflict, 5 refusal, 6 findings in a gated verify.
  • MCP server, memstead-mcp: 21 tools over JSON-RPC on stdio, one process per client. It finds its workspace by walking up from the directory it starts in.
  • Error codes: 263, each listed with the surfaces that emit it and where in the source.
  • Claude Code plugin (MIT): skills that set up a workspace, grow a mem from a source and keep it current, and hooks that stop direct edits to a folder mem's entity files.
  • Rust crates on crates.io, published as dependencies of the two binaries, with no API promise.
  • WebAssembly build: reads a sealed mem in the browser, without search. It is built from the source tree; the npm package stopped at 0.18.1.

Moving a mem

memstead export --format mem seals a mem into one .mem file, a zip archive with the entity files, the config, the schema and per-entity provenance. Two exports of an unchanged mem are byte-identical. memstead install <file> mounts one read-only. A mem also exports as JSON, as one self-contained HTML page with no scripts, or as one markdown document (--format llms-txt).

Keeping a mem true to a source

A binding records that a source, such as a codebase or a folder of documents, belongs in a mem. Entities carry anchors to the files they describe. memstead projection verify reports coverage, anchors whose files changed, and freshness as three separate numbers, never one score; --fail-on-findings exits 6 so CI can tell drift from a failed run. The engine never writes entities from a source. An agent does, through the same checked write path.

Measured limits

A mem is designed for 1,000 to 5,000 entities; the engine sets no hard cap. At 5,000 entities a cold CLI command, which pays one full load of the workspace, took about a quarter of a second. Measured on 2026-09-10 and 2026-09-11 with engine 0.20.0 on an Apple M5 Max, release binaries, a synthetic mem-repo of spec entities with about three edges each:

Entities5002,5005,0007,500
Cold CLI boot59 ms145 ms255 ms371 ms
Warm MCP search0.43 ms0.49 ms0.62 ms0.69 ms
Warm entity read with relations0.82 ms1.08 ms1.39 ms1.71 ms
Warm overview1.6 ms6.3 ms12.6 ms19.2 ms

The cost grows linearly with the entity count. The shape carries to other machines; the milliseconds are this one's. One batch-create of 7,500 entities took about 4.7 s. The harness is cargo run -p xtask -- sizing-curve; the first measurement, on 2026-08-06, was not linear (§6).

§5MethodAI agents write the code. Machine checks stand in for review.
§5Method

AI agents write the code. Machine checks stand in for review.

Memstead is written by AI agents working for one developer, Björn Bösenberg in Berlin, who writes no code by hand. No person reads each change before it lands. The contribution guide states the terms for everyone: an agent judges a change against the machine checks, and the question asked of it is which check covered it, not whether a human understood it. Of the 926 commits in the public history up to v0.22.0 (30 September 2026), 867 carry a Co-Authored-By: Claude trailer.

The engine is written in Rust so that the compiler and the borrow checker carry part of the review a single developer gives up. The chain below carries the rest. Counts are read from the engine source this page was built from.

  1. One definition of green. run-tests.sh decides whether a tree passes, and CI runs that script, not a copy of it. It runs every leg and reports every failure rather than stopping at the first. The legs: cargo fmt --check; cargo clippy with every warning as an error; guards that keep private paths and internal references out of the public tree; 3,716 Rust test functions, none marked ignored and none retried on failure; the doc tests; the Claude Code plugin's Node tests; a check that every memstead command and flag in the shell examples of the public documentation exists in the binary just built; the documented CI example for projection verify, run in both outcomes; and a self-test of the blind-battery instrument.
  2. CI on every push. Every push to main and every pull request runs run-tests.sh on x86-64 Linux and on macOS. Separate jobs run the WebAssembly build's tests in Node, audit the dependencies against the RustSec advisory database (with one documented exception), and check that the workspace builds on its declared minimum Rust version, 1.91.
  3. The binaries, driven from outside. A separate workflow builds the release binaries on every push and drives them over JSON-RPC: a mem-repo round trip (create, update, relate, read, search, change feed), the schema refusals UNKNOWN_SECTION, INVALID_ENUM_VALUE and MISSING_REQUIRED_SECTION, and the conflict path with HASH_MISMATCH.
  4. Untrusted input. Four parsers take input from outside the engine: entity markdown and frontmatter, .mem archives, schema content expressions and search queries. Every test run feeds the markdown, archive and expression parsers 25,500 inputs generated from fixed seeds (counted in the source on 2026-09-30) and asserts that nothing panics and that parsing and writing back reach a fixed point. Search must return the same hits whichever Unicode normalization form a query arrives in. A coverage-guided libFuzzer tier with 4 targets runs when someone dispatches it. An input it finds is fixed at the parser, never by accepting more, and joins the corpus: 16 inputs that once crashed the frontmatter parser are replayed in every test run. The changelog records 15 parser defects found by these two tiers: 3 in 0.10.0, 11 in 0.12.0, and 1 in 0.19.0, found by two inputs.
  5. Reference generated from the code. The CLI reference (93 commands and subcommands), the MCP tool reference (21 tools) and the error-code index (263 codes) are generated from the source at every documentation build and never committed. A page without its generation stamp does not deploy.
  6. A release is a tag. cargo run -p xtask -- release <version> refuses a dirty tree, an empty [Unreleased] section, manifests whose versions disagree, or a red run-tests.sh, and changes nothing in git itself. Pushing the tag builds 7 targets, attaches a SHA-256 checksum and a signed build-provenance attestation to every archive, publishes to GitHub Releases, Homebrew and crates.io, and then asks each channel which version it serves; the run fails if one lags. For 0.21.0 the Homebrew job itself failed, so the run was red, the check never ran, and the formulas were pushed by hand; the cause is fixed in 0.22.0.

Not covered

  • Windows. The Windows build is published and never tested. Of the 7 release targets, CI tests x86-64 Linux and one macOS runner; the others are built without a test run.
  • Coverage. No code-coverage figure has ever been measured. The test count is a count.
  • Deeper analysis. No mutation testing, no Miri, no sanitizers outside the fuzz tier.
  • Fuzzing on a schedule. The long tier runs when someone dispatches it and is never a required check. Between 2026-08-24 and 2026-09-09 it ran 13 times in CI and found failing inputs in 9 of those runs; 0.20.0, 0.21.0 and 0.22.0 shipped without a fuzz run. A run over all four targets, dispatched on 2026-09-30 after 0.22.0 shipped, found no failing input in 15 minutes per target.
  • Required checks. The rule in the contribution guide is that nothing lands past a red run-tests.sh: the author runs it before pushing, and no machine enforces that. main has no branch protection, so CI runs after a commit lands, and a red CI run is repaired by a later commit. Waiting for green CI before tagging is a step in the release runbook, not a machine gate.
  • Code signing. The binaries carry no platform signature: the macOS binary has the linker's ad-hoc signature, and Windows signing is not configured. The provenance attestation is the check that exists.
  • Performance regressions. No CI job measures speed. The sizing curve is rerun by hand; its current figures are from engine 0.20.0.
  • Supply chain. No SBOM and no dependency licence policy.
  • Outside review. No independent audit or review of the engine has been published.

Check a release yourself

Every release archive has a .sha256 file beside it and a signed SLSA build-provenance attestation. With the GitHub CLI:

gh release download v0.23.0 -R memstead/memstead -p 'memstead-cli-<target>.tar.xz*'
shasum -a 256 -c memstead-cli-<target>.tar.xz.sha256
gh attestation verify memstead-cli-<target>.tar.xz -R memstead/memstead

<target> is a Rust target name such as aarch64-apple-darwin or x86_64-unknown-linux-gnu. The attestation ties the archive's digest to the release.yml run at that tag and to the commit it built. Checked for v0.22.0's x86_64-unknown-linux-gnu archive on 2026-09-30: workflow release.yml@refs/tags/v0.22.0, commit ea69139e.

§6EvidenceWhat was measured, including what went against the engine.
§6Evidence

What was measured, including what went against the engine.

Each run below is published with its method and data in docs/proof/ or docs/sizing-curve.md. Each is one run, not a benchmark, and the project ran all of them itself.

Divergence campaign July 2026 · pre-registered · record

Question
Does refusing non-conforming writes pay off as a knowledge base grows over ten rounds of an evolving source repository?
Method
Two arms were filled by writer sessions that started fresh each round, from byte-identical digests of a public repository's history: a markdown folder that accepted every write, and a mem that refused non-conforming ones. A twelve-question battery, three trials per arm, a blinded judge, and three blinded integrity audits per arm. The decision bands were fixed before the first run and applied mechanically.
Result
Integrity, positive: after round 10 the mem held 0 duplicates or contradictions per 100 items across three audits, the folder 8.13, and the mem held 81 items to the folder's 41. Accuracy, negative: the mem scored 0.286, the folder 0.575, and the gap widened at every checkpoint.
Added later
Not pre-registered (2026-08-25). Five of the twelve questions ask about bug records. The mem's writers recorded 26 distinct bug identifiers to the folder's 244 and used the schema's incident type zero times. A substantial part of the accuracy gap is material that was never written, which counts against the engine, not for it.
Limits
Neither result can be assigned to typing or to the engine's read tools: each arm was read with its own tools, and the cell that would separate them was not run. The integrity result has no identified mechanism, since the engine ships no duplicate or contradiction detector, and the control arm with a plain linter was not run. It is one campaign, on one source repository, with one model. At the round-5 audit the order was reversed (the mem 1.52, the folder 0.00). No session recorded proof that it reached the engine.

Substrate eval 2026-07-08 · record

Question
Given the same source material, do schema-typed entities let an agent answer better than equally curated plain notes?
Method
One model captured both forms from the same corpus, a text on Memstead's own design. Each arm answered with its whole substrate in context under an 8,000-token budget, so retrieval played no part. A blind judge scored three trials. A screen removed any task the model could answer without the corpus (one of six).
Result
Typed 0.973, plain notes 0.983: a difference of -0.010 ± 0.006, no measurable difference. Both covered 22 of 22 facts.
Limits
Any claim that typing makes answers better is unsupported. It is one run with one model on a corpus that fits in context. It says nothing about corpora larger than the context, and nothing about refusing bad writes, scale, or who may write what.

Blind battery 2026-09-04 and 2026-09-06 · record

Question
On eleven fixed questions about how Memstead works, does an agent that may read only the engine's own mem answer as well as one that may read only the Rust source?
Method
Two fresh readers per question, one large model and one small; citations stripped; a seeded random A/B order. A third fresh agent grades each pair against the source and by running the release binary. The instrument is ci/blind_battery.py, whose mechanics self-test in every run-tests.sh.
Result
2026-09-04, the mem at its version 0.2.2, before any sync: source 7, mem 4. 2026-09-06, after a sync that walked every claim in the mem: source 9, mem 2, with margin sums of 15 to 3. The mem won on what an installed mem can and cannot do, and on one question about concurrent writes answered by the small model.
Limits
No general verdict on mems against code follows. It is one mem, about its own source, graded by agents. The mem under test is not published; the second run's prompts, answers, pairs and verdicts are. The first run's record was not kept beyond its verdicts.

Reconstruction 2026-07-03 · record

Question
How many tokens does a fresh agent need to rebuild a working picture of a subject from its mem, compared with the conversations that wrote the mem?
Method
A fresh agent read a 287-entity mem through the CLI only and wrote a brief that cites an entity for every claim. Its transcript and the 22 authoring conversations were counted with the same script and tokenizer.
Result
65,161 against 852,773 content tokens, about 1/13.
Limits
No advantage of typing follows. It compares a curated mem with raw research conversations, so it measures curation; the substrate eval, which isolates typing, found none. One run, no variance, and understanding is shown by the brief, not scored. The raw authoring transcripts are withheld; their hashes and token counts are published.

Read-surface headroom pre-registered 2026-08-25 · never run · record

Question
Was the divergence campaign's accuracy loss caused by the typed files or by the engine's read tools?
Method
Five read surfaces over the same frozen corpora, with the campaign's battery, judge and rubric.
Result
None. Three smoke passes found failures in the apparatus. In one, the engine arm never reached the engine, answered with file tools, and still returned a plausible score; a guard now aborts such a run. The full run has not started, and whether it will is open.
Limits
The question stays open, and the divergence accuracy result cannot be assigned to typing or to the tools.

Sizing curve 2026-08-06, re-measured 2026-09-10 and 2026-09-11 · record

Question
What do everyday operations cost as a workspace grows from 500 to 7,500 entities?
Method
cargo run -p xtask -- sizing-curve builds synthetic workspaces through the CLI and times cold commands (median of 3) and warm MCP calls (median of 20) with release binaries on one machine, an Apple M5 Max.
Result
Linear. A cold command costs one workspace load, 371 ms at 7,500 entities. Warm reads stay under 2 ms, except the overview at 19 ms for 7,500 entities.
First measurement
On 2026-08-06 the same harness found the cold cost growing faster than linear: 5,647 ms at 7,500 entities. That curve stood for five weeks. On 2026-09-10 a profile put 96% of the boot time in reading each entity through a freshly opened repository tree; the fix, one tree walk per mem, landed the same day and shipped in 0.20.0. The old curve stays in the document as a dated record.
Limits
Absolute times hold for one machine and synthetic content only. The figures are from engine 0.20.0, and no CI job re-measures them.

The proof folder also holds a count from 2026-06-11: 79% of 153 drift findings closed, with a median of about 12 minutes, over the project's own mem-repo. That mem-repo is private, no outside party has reproduced the count, and the mechanism it measured was replaced on 2026-07-10, so nothing on this page rests on it.

§7HistoryHow the engine got here, dated.
§7History

How the engine got here, dated.

Before the public repository

From the private record: these dates come from the project's private repository and records and cannot be checked from outside.

  • Feb 2026
    Development begins, part-time.
  • 2026-03-18
    First commit of the private repository. It already describes a JavaScript engine with an MCP server of 17 tools, a schema package, a Claude Code plugin and a desktop app.
  • 2026-04-12
    A rewrite in Rust begins; it has 160 test functions on its first day.
  • 2026-04-13
    The Rust engine is compared tool by tool with the JavaScript engine on a small real mem: 7 of 10 tools give identical output, and 3 differences are documented. The JavaScript engine is retired the same day.
  • 2026-04-18
    The MCP tool list is cut from 21 to 15 in two steps.
  • 2026-04-30
    1,298 test functions.
  • May 2026
    The storage layer is rebuilt. No commit from 2026-05-23 to 2026-06-07; a planned launch date, 2026-05-31, passed in that gap.
  • 2026-06-12
    The name Memstead replaces the working names.

The public line

Checkable at github.com/memstead/memstead.

  • 2026-07-01
    The public repository starts with one commit of 562 files and a fresh history. That night the unit noun becomes "mem", with no alias kept for the old one.
  • 2026-07-02
    0.1.0, with binaries for macOS, Linux and Windows and 2,347 test functions. It was tagged 71 minutes before the documented quickstart landed, and 0.2.0 shipped it on 2026-07-04.
  • 2026-07-13
    The engineering decision record becomes public as a mem, with 41 entries.
  • 2026-07-20
    0.4.0 rewrites VISION.md to drop a read-side claim that the project's own substrate eval had falsified.
  • 0.5.0
    Never cut. The number was skipped so that the engine and the Claude Code plugin, already at 0.5.0, share one version.
  • 2026-08-19
    0.9.0 is cut and never published; its content ships in 0.10.0 on 2026-08-23.
  • 2026-08-23
    0.10.0 adds the seeded adversarial tests and the libFuzzer tier. The two tiers found 3 parser defects for that release and 11 more by 0.12.0.
  • 2026-09-09
    0.19.0 consolidates: one build instead of two.
  • 2026-09-10
    0.20.0 makes loading a mem-repo linear in its size.
  • 2026-09-30
    0.22.0: the CLI stops naming a registry, and the installer moves to memstead.com.

23 published releases from 2026-07-02 to 2026-10-08, and 3,716 test functions in the source this page was built from. Read that as a cadence, not an age: expect changes between releases.

What was removed, and when

  • 2026-04-13
    The JavaScript engine (private record).
  • 2026-04-18
    6 of 21 MCP tools (private record).
  • 2026-07-11
    memstead stats, replaced by memstead status (0.3.0). The same day, the plugin's hooks that committed into the user's repository: "The user's project repo is exclusively the user's business."
  • 2026-07-20
    A claim in VISION.md that an agent reading typed specs "understands a domain immediately" (0.4.0).
  • 2026-08-18
    The native macOS app. Its binding crate left the workspace in 0.10.0.
  • 2026-08-23
    The six memstead_workspace_* MCP tools (0.10.0): workspace policy belongs to the operator, not to the agent it constrains.
  • 2026-09-05
    The npm package of the WebAssembly build.
  • 2026-09-09
    The second build flavour with its 212 cfg sites, and the converters for two retired binding formats (0.19.0).
  • 2026-09-30
    The CLI's built-in registry host (0.22.0). The registry service was stopped the same day (private record).

The list records removals only. Commands and tools were added along the way: the source this page was built from has 93 CLI commands and 21 MCP tools.

Every release

Versions and dates are read from CHANGELOG.md at every build; each line is a one-sentence summary of that version's entry. 23 published releases, and 0.9.0, cut and never published. Latest: v0.23.0, 2026-10-08.

0.23.02026-10-08
Closes a command injection through memstead fetch refspecs and a race where two processes could both write one memmemstead pull --all restores a mem-repo from its backup, and an installed mem now travels with the workspace by its content identity.
0.22.02026-09-30
The engine names no registry any moreinstall, publish and login take one only when you point the CLI at it, login learns its OAuth app from that registry, the installer moved to memstead.com, and the engine's commits carry memstead.com author and committer addresses.
0.21.02026-09-27
Statically linked Linux binaries for both architectures, so a container without glibc runs the engine from a pinned releasea mem's check records travel with its pushed branch on a ledger ref, so an export made on another machine seals them; and the owner's side of a hosted proposal path, mem fork --remote --adopt, mounts a contributor's branch from a plain git remote. Beside it: a proposal merge that rejects everything still lands its record, and a plan step with a gate closes only on a check recorded in a checker's role.
0.20.02026-09-10
A mem-repo boot is linear in the mem sizethe git-branch backend reads a whole mem in one tree walk, so a 7,500-entity workspace boots in under 0.4 s, where a profile of the old boot on the sizing corpus measured 6.2 s, and the sizing curve is re-measured on the fixed engine. Beside it: a sealed .mem carries a provenance record for every entity, prune proposes and never merges (the guarantee vocabulary is gone), and projection advance refuses to drop an authored exclusion or to advance over anchors that still drift.
0.19.02026-09-09
One build instead of twothe engine ships as a single build with the git-branch backend always on, the retired split's names and the migration paths for retired binding formats are gone, and every help text, tool description and public page describes the tree as it is. Underneath: search --json carries the same hit shape as the MCP envelope, a server started before its first mem now mounts it without a restart, the binding-intent check reads only relationship-shaped tokens, the boot no longer panics without a data directory, and the frontmatter splitter reads every section the way the generator writes it, closing the gap two fuzz inputs found.
0.18.12026-09-03
Fixes for the two problems the first outside tester of 0.18.0 hit on the documented patha mem installed from the registry into a quickstart workspace now resolves its sealed schema from the archive itself instead of refusing, and a fresh cargo add of the published crates compiles again, with the broken tinyvec release held off by a resolver constraint.
0.18.02026-09-03
A released binary can be told apart from a local build of the same versiona clean tagged build reports bare semver while every other build keeps its +g<sha>, so the plugin's capability gate stops reading a pre-release dev build as capable and its record follows the binary across an upgrade. Around that repair land the bundle of engine fixes it shipped with: a short entity id names its missing mem prefix instead of failing on an empty one, create --from --mem stops dropping the flag, the health coverage line reports the verdict it actually polices, a completed schema migration re-stamps the version marker, the lite schema skeleton renders every legality flag, and a bare projection verify writes nothing while coverage marks the artifacts excluded on purpose.
0.17.02026-09-02
The maintenance report names what is overdue, and two built-in schemas get new versionsproject@0.5.0 puts milestones on the due axis and engineering@0.4.0 sanctions the dated in-place amendment on decisions. Around them: memstead push --all publishes the whole mem-repo, mem membership follows reload-before-operation, an unreadable anchors sidecar is one typed condition on every surface, export redacts private patterns in the archive's provenance, health gains the vital_signs axis and a --mem filter, and the check that nobody approves their own work compares who executed a step, not who wrote its criterion.
0.16.02026-09-02
An entity can change its type in placememstead retype keeps the id, the file and every incoming edge, validates the sections against the target type with a report-all refusal, and re-checks every edge against the target's relationship pins. Beside it: export --root --via renders one chain of the graph, check records carry a structured finding and accept an open x- kind, url anchors become observable through observer-supplied rows, schema migrate rewrites an authoring package's retired keys into the current schema language, and /sync --sweep walks a list of mems in order.
0.15.02026-09-01
A second maintenance skill repairs how a mem is cutthe new /remodel skill repairs what a mem IS (one home entity per obligation, substance in its declared sections) where /sync repairs what entities say, and the sync skill adopts the benchmark campaign's disciplines. The measured frictions land too: check --from batches verdicts in one boot, export carries anchors, a section takes several patches per call, and sections_unset closes a section, with unwritten optional sections now absent instead of scaffold headings.
0.14.02026-08-29
The entity type has one field name everywhere, and a plan can refuse a status changethe entity envelope serves entity_type everywhere (the retired spelling is gone, not aliased), the mem config's format is modeled and gated, the planning schema gains gated status transitions with a gates brief that renders every transition's standing, verify learns --fail-on-inconclusive, and an undeclared cross-schema wiki-link now warns instead of silently staying prose.
0.13.02026-08-28
Every report says what it examinedtwo wire spellings converge (one edge shape on every input; commit_sha becomes write_id and stops posing as a change cursor), semantic conformance becomes a recordable schema-bound check, quarantined mems can no longer disappear from status or type, health's human rendering serves the findings it gathers, and a fleet of new gates holds descriptions to the code that backs them.
0.12.02026-08-24
Eleven parser defects found by the long fuzz tier are fixedeleven cases where parsing a mem's markdown and generating it back changed the document, each traced to the CommonMark referee and the engine's own reconstruction reading a line differently, each now pinned by its triggering input in the shared corpus. Alongside them, the two problems the first sealed test of the install path found: export --format mem and publishing work on every workspace quickstart creates, and every page that teaches an install says to restart the agent session.
0.11.02026-08-24
Anchors drift on meaning, not on formattingthe first three preparations decide what counts as a change in a source, entity-load-bearing (a notes-only edit no longer drifts a dependent's anchor), dated-entries (a chronological file delivers as stamp-ordered units), and code-map (a code file's anchor hashes its interface digest, measured at 4.6% of the raw source on a 214-file corpus).
0.10.02026-08-23
Schemas can state more kinds of rules, and a fuzzing tier guards the parsersconditional edge requirements, reachability obligations, acyclic relation sets, aggregate signals, and grounded labelling over a declared attack set. A new adversarial fuzzing tier guards the three trust-boundary parsers and already found and fixed three parser defects.
0.9.02026-08-19Cut, never published. Its content, including the removal of the native macOS app's binding crate, shipped in 0.10.0.
0.8.12026-08-18
Every edge in the entity envelope states its direction and a read can include incoming edgesthe CLI's --json reads carry the trust origin; folder mems can be re-attached.
0.8.02026-08-15The HTML export renders declared section headings, docs pages name the revision they were built from, and each bootstrap receipt states its workspace shape and one limit.
0.7.02026-08-14
Three of four published mems could not be installed until memstead install staged the schema each archive carrieshelp texts now name the refusals a newcomer met unannounced.
0.6.02026-08-10
Titles become display text, fields and sections are optional unless marked required, and schema validation reports every violation at oncememstead due and export --format html arrive.
0.4.02026-07-20
VISION drops a read-side claim the project's own substrate eval had falsifiedbreaking: each pipeline becomes one versioned binding record; folder mems join cross-process change detection.
0.3.02026-07-11
The projection-pipeline releasea versioned binding replaces the ingest config store, anchors record which source artifact an entity describes, and memstead status replaces memstead stats. Breaking.
0.2.02026-07-04Ships memstead quickstart and memstead schema new, which 0.1.0 missed by 71 minutes, plus the git transport commands fetch, pull, push, branch-reset and remote-add.
0.1.02026-07-02
First tagged releasethe schema layer, the in-memory store, the folder and git-branch backends, the memstead CLI and the memstead-mcp server, with binaries for macOS, Linux and Windows.

The decision record

The reasons behind the engine's design are public as a mem: engineering/ in the repository holds 187 decisions, principles and memos, with superseded ones kept beside their successors. Each entry is a markdown file, and the folder's README says how to mount it and query it with the engine.

§8FilesYour mems stay markdown in your git, readable without Memstead.
§8Files

Your mems stay markdown in your git, readable without Memstead.

A folder mem is a folder of markdown files in your project. Memstead never commits to your repository; you version the files with your own git, on your terms.

A mem-repo is a git repository the engine writes: one branch per mem, one commit per change. Plain git reads it: git -C mem-repo show <mem>:<file>.md. memstead push sends a mem's branch to a git remote you configure. Inside another repository, mem-repo init adds mem-repo/ to that repository's .gitignore.

Either way the files read without Memstead: YAML frontmatter, level-two sections, a relationships list. Schemas are YAML files, and a sealed .mem file is a zip archive. Leaving Memstead means keeping the files.

What can change before 1.0. APIs, schemas, file formats, CLI flags and MCP wire shapes may change without notice, and the library crates on crates.io carry no API promise. A retired format can lose its converter: 0.19.0 removed the one for two retired binding formats, whose files now refuse to load and name the command that re-creates them. The changelog labels breaking changes as such; 0.22.0 has two. To hold a version still, pin it at install: curl -sSf https://memstead.com/install.sh | sh -s -- --version <tag>.

Security. Report a vulnerability to security@memstead.com, never as a public issue. The policy promises an acknowledgement within 7 days and triage within 14, with coordinated disclosure usually 30 to 90 days after triage; fixes go to the latest tagged release. No advisory had been published by 2026-09-30, so these times have no track record yet. A mem you install from someone else is untrusted input: the engine withholds its schema's instruction prose and tags every entity it serves as third-party, but it cannot stop an agent from acting on the text. The full policy is SECURITY.md.

Licence. The engine, the CLI, the MCP server and the .mem format are MIT or Apache-2.0, at your option. The Claude Code plugin is MIT.