Skip to main content
Glama
README.md
# mnemo

[![test](https://github.com/cniackz/mnemo/actions/workflows/test.yml/badge.svg)](https://github.com/cniackz/mnemo/actions/workflows/test.yml)

**Portable memory for AI agents. Plain Markdown files that you own, that any agent can read.**

Every assistant now remembers you. None of them let you leave with it. Your
preferences, your context, the way you like work done, all of it lives inside
one vendor's product, in a shape nobody else can read, and switching tools means
starting over as a stranger.

mnemo is the opposite bet: your memory is a folder of Markdown files on your
disk. One fact per file. An index at the top. A small CLI and an MCP server so
any agent can read and write it, and no agent can hold it hostage.

```
~/.mnemo/
  mnemo.json
  MEMORY.md                        <- generated map of everything
  memories/
    prefers-metric-units.md
    short-pr-titles.md
    kettle-billing-rewrite.md
```

## Quickstart

No dependencies. Node 20 or newer.

```bash
npx @cniackz/mnemo init
npx @cniackz/mnemo recall "pull request"
```

From a clone it is the same tool, spelled `node bin/mnemo.js <command>`:

```bash
node bin/mnemo.js init

node bin/mnemo.js remember short-pr-titles \
  --type feedback \
  --desc "pull request titles stay under 50 characters" \
  --body "Detail belongs in the body. Why: the title becomes the squash commit."

node bin/mnemo.js recall "pull request"
```

There is a complete synthetic store in [`examples/demo-store`](examples/demo-store)
to poke at before you put anything real in one:

```bash
node bin/mnemo.js list --store examples/demo-store
node bin/mnemo.js recall "billing" --store examples/demo-store
```

## Bring what you already have

Most people already keep notes. `import-dir` reads a directory of ordinary
Markdown, tolerates frontmatter it did not write, and falls back to the first
line of prose when a file carries no metadata at all.

```bash
mnemo import-dir ~/notes --recursive --dry
mnemo import-dir ~/notes --recursive
```

`--dry` reports and writes nothing. `--split` is the flag that matters for hand
kept notes: a single file holding many entries under `## ` headings becomes one
memory per heading, which is the shape the format wants, and which stops one
long file from winning every search by length alone.

```bash
mnemo import-dir ~/notes/lessons --split --type x-lesson
```

Nothing is overwritten. A name already present in the store gets its parent
directory prepended, and whatever still cannot be placed is printed instead of
dropped in silence.

## Give it to your agent

mnemo ships an MCP server, so any client that speaks MCP gets five tools:
`recall`, `remember`, `forget`, `list_memories`, `get_memory`.

Claude Code:

```bash
claude mcp add mnemo -- node /path/to/mnemo/bin/mnemo.js mcp --store ~/.mnemo
```

Anything else that takes an MCP config file:

```json
{
  "mcpServers": {
    "mnemo": {
      "command": "node",
      "args": ["/path/to/mnemo/bin/mnemo.js", "mcp", "--store", "/home/you/.mnemo"]
    }
  }
}
```

The same store can be mounted by several agents at once. They are all just
reading files.

## The format

Full spec: [SPEC.md](SPEC.md). It fits on one page on purpose.

```markdown
---
name: short-pr-titles
description: pull request titles stay under 50 characters, detail goes in the body
type: feedback
created: 2026-07-31
updated: 2026-07-31
tags: [git, review]
---

Keep pull request titles under 50 characters.

**Why:** the title is what shows up in the release notes and the squash commit.

Related: [[review-hour]]
```

Four core types, `user`, `feedback`, `project`, `reference`, plus any custom type
you prefix with `x-`. Links are `[[slug]]` and are allowed to dangle, because
writing `[[not-yet-written]]` is a useful way to mark a memory worth having.

Unknown frontmatter keys are preserved on rewrite. A tool that does not
understand a field is not allowed to drop it, which is what makes it safe for
two different implementations to share one store.

## Commands

```
mnemo init [--name <label>]         create a store
mnemo remember <name> [options]     create or update one memory
mnemo recall <query> [--limit n]    search
mnemo list [--type <type>]          list everything
mnemo show <name>                   print one memory
mnemo forget <name>                 delete one memory
mnemo index                         regenerate MEMORY.md
mnemo validate                      check the store against the spec
mnemo export [--out <file>]         dump the whole store as one JSON document
mnemo import <file>                 rebuild a store from that document
mnemo import-dir <dir>              bring in Markdown notes you already have
mnemo mcp                           run the MCP server on stdio
```

`--store <dir>` points at a store other than `$MNEMO_HOME` or `~/.mnemo`.
`--json` makes any command machine readable.

## The one guarantee

```bash
mnemo export --out brain.json
mnemo import brain.json --store ./somewhere-else
diff -r ~/.mnemo/memories ./somewhere-else/memories   # no output
```

Export then import reproduces every memory byte for byte. It is a test in the
suite, not a promise in a README. If that ever breaks, the project has failed at
the only thing it claims.

## Why files

- **Readable in fifty years.** Markdown and a text editor. No schema migration.
- **Sync is already solved.** `git push`, a bucket, a synced folder. Pick one.
- **Diffable.** You can see what your agent decided to remember about you, in a
  pull request, and disagree with it.
- **Greppable.** Recall is ranked search, but `grep -r` still works, and that
  matters on the day the tooling is broken.
- **Yours.** Deleting a memory is `rm`. No account, no request form, no export
  queue.

## Design rules

1. Plain files. If the tooling disappears, the memory survives.
2. One fact per file. Splitting is cheap, merging is expensive.
3. Derived data is disposable. `MEMORY.md` and any future index rebuild from the
   memories alone.
4. Offline first. Recall works with no model, no network, no server. Embeddings
   are allowed on top, never instead.
5. Vendor neutral. No field in the spec names a model or a product.

## Status

`0.1`, early, and the format is the part meant to outlive this code. The spec is
versioned separately from the implementation for that reason. If you write
another implementation, the conformance bar is in [SPEC.md](SPEC.md) section 6,
and a store written by yours has to survive a round trip through this one.

Issues and pull requests welcome, especially: a second implementation in another
language, adapters for other agent runtimes, and arguments about the format
while it is still cheap to change.

```bash
npm test
```

## License

MIT. Use it, fork it, embed it in a product, take your memory with you.

Maintenance

ActivitySlowing
ResponsivenessNo issues