Archivum documentation

Local-first memory for coding agents: plain files you own, a background “dream” pass using your own LLM key, review before anything changes.

Quickstart

Archivum is local-first memory for coding agents. Everything lives as plain files on your machine; there is no account and no hosted service. Requires Node 22 or newer.

  1. Run init. It detects Claude Code (~/.claude) and Codex (~/.codex or codex on your PATH) and wires up whatever it finds.
Shell
npx archivum init

What init changes

  • Claude Code: merges a SessionStart and a Stop hook into ~/.claude/settings.json (created if missing). Before the first change it backs the file up to settings.json.archivum-bak. Existing hooks are never removed and running init twice does not add the hooks twice. It also registers the MCP server with claude mcp add archivum -- npx -y archivum-cli mcp, or prints that exact command if the claude binary is not found.
  • Codex CLI: runs codex mcp add archivum -- npx -y archivum-cli mcp, or prints the command and the [mcp_servers.archivum] TOML if codex is not found.
  • Nothing else. Preview with npx archivum-cli init --dry-run; limit it with --claude-code or --codex.

Your first session

Start your agent as usual, inside a project directory. At session start the hook injects a small digest of that project's memory (empty at first, so nothing is injected). The agent can call the MCP tools such as remember and recall. When the session stops, the hook saves the transcript, with secrets scrubbed, to your Archivum home as a pending transcript. You can also add notes yourself:

Shell
archivum remember "Run tests with npm run test:unit, not npm test"
archivum recall "how do I run the tests"
archivum status

Dream

Once a few sessions have piled up, consolidate them into the wiki. Dreaming uses your LLM key (see Dreaming).

Shell
export ANTHROPIC_API_KEY="sk-ant-..."
archivum dream

It prints how many transcripts and notes it selected plus a rough token estimate, then asks Proceed? [y/N]. Nothing is written to your live wiki yet: the result is a proposal.

Review and apply

Shell
archivum proposals
archivum diff
archivum apply        # or: archivum reject

apply writes each changed file to the live wiki, but skips any file you changed since the dream started (and lists it). Every write is a version you can restore.

Concepts

The design is inspired by Anthropic's article The components of agent memory. Archivum is an independent project and is not affiliated with Anthropic; this page makes no claims about benefits beyond what is described here.

The four layers

LayerWhat it isWhere
TranscriptsAppend-only record of a session (user, assistant, tool events), secrets scrubbed. Raw material for dreaming.transcripts/<id>.json
NotesShort memories added by an agent (remember) or you (archivum remember).notes.jsonl
WikiSmall linked markdown files, organised by dreaming and editable by you, with an _index.md table of contents.wiki/
ContextThe top layer: the index, kept small and injected at session start (about 4,096 characters by default; the Claude Code hook caps it at 10,000).wiki/_index.md

Space = project

Memory is partitioned into spaces. A space is chosen by --space X, otherwise $ARCHIVUM_SPACE, otherwise the cwd's folder name (characters outside A-Za-z0-9_.- become -, at most 64 characters, fallback default). In practice one project is one space and projects do not see each other's memory.

What lives where

  • Everything is under $ARCHIVUM_HOME (default ~/.archivum) on your disk.
  • Your agent only sees memory through the digest the hook injects and the MCP tools.
  • Only archivum dream sends anything to an LLM, using the provider you configured.

On-disk layout

Per space, under <home>/spaces/<space>/:

Layout
wiki/                 your live markdown pages; /quillon-tests.md is wiki/quillon-tests.md
  _index.md           the index (the context digest)
transcripts/          one file per recorded session
notes.jsonl           one note per line
history/              a copy of every page each time it changed, plus a log
proposals/<id>/      each dream's staged wiki, waiting for your review

Folders inside wiki/ are allowed. All writes are atomic (temp file then rename).

Edit by hand or commit to git

The live wiki is ordinary markdown. Open it in your editor, fix a page, delete one, or run git init inside wiki/ and commit it. Hand edits are safe: if you change a page after a dream started, apply sees the page has changed and skips it rather than overwriting you. Changes made outside the CLI are not recorded in the history log; only writes made by apply, restore and write are.

History and restore

Each history entry has an operation (create, update, delete, rename, restore) and an actor (user, dream:<id> or restore).

Shell
archivum history
archivum history /quillon-tests.md
archivum restore /quillon-tests.md --version 3

CLI reference

One binary, archivum. Output is human-readable text. Install nothing: npx archivum-cli <command> works, or install the package globally.

init

FlagMeaning
--claude-codeConfigure Claude Code only.
--codexConfigure Codex only.
--allConfigure every supported client, detected or not.
--dry-runPrint the actions without changing anything.
--home DUse D as the Archivum home.

With no client flag, init configures every client it detects.

mcp, hook, log

  • archivum mcp [--space X]: stdio MCP server (see MCP server).
  • archivum hook session-start|stop: Claude Code hook entry points, reading hook JSON on stdin (see hooks).
  • archivum log [--file F | -] [--source S] [--id ID]: append a transcript from a JSON file or stdin, either {"events":[...]} or a bare array of events, for agents without hooks. Each event is {"role":"user|assistant|system|tool","content":"...","name"?,"ts"?}.
  • archivum import omp [--dir D] [--session FILE] [--all] [--since DATE] [--space S]: store omp sessions as transcripts. omp keeps sessions as JSONL under ~/.omp/agent/sessions (override with --dir or OMP_SESSIONS_DIR). By default it imports the sessions whose working directory is the current one; --all takes every session (each into the space named after its working directory) and --session takes one file. It is idempotent: the omp session id is the transcript id, so importing again after a session grew updates the same transcript and puts it back to pending. Thinking blocks are dropped, tool output is clipped to 4,000 characters, and known secret patterns are redacted.

remember, recall, context, status

Shell
archivum remember "text"
archivum recall "query" --limit 5
archivum context --max-chars 4096
archivum status

status prints the counts of notes, wiki pages and transcripts (pending and dreamed), proposals, the home path and the space.

dream

FlagMeaning
--budget TOKENSToken budget for the run. Refuses to start when the estimate exceeds it (the message suggests --since, --max-inputs or a larger budget). Default 3,000,000.
--instructions "..."Extra guidance for the organizer, e.g. what to prioritise.
--since DATEOnly transcripts whose updated_at is at or after DATE (2026-11-01 or a full ISO timestamp). A bad date exits 2.
--max-inputs NAt most N transcripts, 1 to 200. Default 50.
--if-dueDream only when due (see below). Tune with --min-pending N (default 3), --idle-minutes M (default 10) and --cooldown-hours H (default 6).
--yesSkip the Proceed? [y/N] prompt (required when there is no TTY).
--dry-runShow the selection and estimate only.
--applyApply right after a successful, non-partial run. Off by default.

Selects the oldest pending transcripts (at most 50, or the --max-inputs value, and 6,000,000 characters) and unconsolidated notes (at most 300).

--if-due is for schedulers. It exits 0 after printing one line, not due: <reason>, unless at least --min-pending transcripts are pending, the newest transcript was last updated at least --idle-minutes ago and the last dream (the newest proposal) is at least --cooldown-hours old. When due it behaves like a normal dream: --yes is still required without a terminal and the result is still a proposal to review.

proposals, diff, apply, reject

FlagMeaning
archivum proposalsList proposals.
archivum diff [id]Plain-text diff of the latest (or given) proposal against the current live wiki.
archivum apply [id] [--force]Write the proposal to the live wiki. Without --force, files changed since the dream started are skipped and listed.
archivum reject [id]Discard a proposal.

restore, history, retention

FlagMeaning
archivum restore <path> [--version N]Restore a wiki file from history.
archivum history [path]List history entries.
archivum retention [--days 30]Delete transcripts dreamed more than N days ago. Also runs at the end of dream and apply with the 30-day default.

doctor

archivum doctor [--space X] [--json] is a read-only health check. It prints one line per check, PASS, WARN or FAIL, with a hint where there is something to do, and exits 0 unless a check fails (then 1). With --json it prints an array of {name, status, detail, hint}. It makes no network call and never prints your API key (only set or missing).

CheckWhat it looks at
nodeNode 22 or newer (FAIL otherwise).
home$ARCHIVUM_HOME exists and is writable, or can be created (FAIL otherwise).
space filesEvery transcripts/*.json, the lines of notes.jsonl and history/log.jsonl, state.json and proposals/*/proposal.json parse. FAIL with the count of unreadable ones.
claude hooksWhen ~/.claude exists, settings.json has SessionStart and Stop commands containing archivum hook (WARN otherwise).
mcp (claude), mcp (codex)Only if the binary is on PATH: <bin> mcp list (5 second timeout) mentions archivum. A failure is a WARN.
llm configProvider is anthropic or openai (FAIL otherwise); key set; openai notes the default base URL and needs both models; anthropic notes the default models. A missing key or model is a WARN. Not tested against the network.
pending workPending transcripts and proposals awaiting review.

Troubleshooting

  • Start with archivum doctor. It tells you which file is unreadable, which hook is missing and what the LLM configuration lacks.
  • A FAIL on space files means a file in the space is damaged. Archivum skips unreadable records instead of crashing, but cannot repair them: restore the named file from a backup or delete it.
  • A WARN on claude hooks or mcp: run archivum init again (it is idempotent).
  • A dream that says the estimate is above the budget: use --since DATE or --max-inputs N to dream fewer inputs, or raise --budget.
  • To dream on a schedule (cron, Task Scheduler) run archivum dream --if-due --yes. See dream.

Common flags, exit codes, environment

--space X selects the space for the commands that act on one. A missing API key or model for dream exits with code 2 and a message saying what to set; hook always exits 0. Other failures exit non-zero with a message on stderr.

VariableMeaning
ARCHIVUM_HOMEStorage root. Default ~/.archivum.
ARCHIVUM_SPACESpace name when --space is not given.
ARCHIVUM_LLM_PROVIDERanthropic (default) or openai (any OpenAI-compatible endpoint).
ARCHIVUM_LLM_API_KEYAPI key. Falls back to ANTHROPIC_API_KEY (anthropic) or OPENAI_API_KEY (openai).
ARCHIVUM_LLM_BASE_URLEndpoint base URL. For openai the default is http://localhost:20128/v1.
ARCHIVUM_ANALYZER_MODELModel for analyzers. Default claude-haiku-5-5 for anthropic; required for openai.
ARCHIVUM_ORGANIZER_MODELModel for the organizer. Same defaults as above.
ARCHIVUM_DEBUGSet to 1 to print hook errors to stderr.

Examples

Shell
# preview what init would do
npx archivum init --dry-run

# a one-off dream with a smaller budget and a hint
archivum dream --budget 500000 --instructions "Focus on build and test commands" --yes

# log a transcript from an agent without hooks
cat session.json | archivum log - --source my-agent --id session-42

# review, then apply
archivum diff
archivum apply

MCP server

archivum mcp is a stdio MCP server (newline-delimited JSON-RPC 2.0, protocol 2025-06-18). It logs to stderr only. The space comes from ARCHIVUM_SPACE or the working directory, or --space.

ToolArgumentsPurpose
remembercontent, metadata?Save a short note. Secrets are scrubbed.
recallquery, limit?Search notes and wiki (BM25); returns kind, title, snippet, score.
contextmax_chars?The short digest of this project's memory.
forgetidDelete one note (never wiki pages).
list_noteslimit?The newest notes with their ids.
read_documentpathRead one wiki page.
search_documentsquery, limit?Search wiki pages only.
list_documentsprefix?List wiki pages with size and description.
related_documentspathPages this page links to (flagging broken links) and pages that link to it.
document_historypathWhen a page changed and who changed it (you or a dream).
memory_statusnoneCounts, what is waiting to be dreamed, proposals awaiting review, last dream.
list_proposalsnoneDream proposals and their state.
show_proposalid?The diff of a proposal, so the agent can summarise it for you.

All tools are read-only except remember and forget. By design there is no tool to start a dream or to apply a proposal: those spend your tokens or change your wiki, so you do them with the CLI.

It also exposes one resource, archivum://context, with the current context digest.

Claude Code

Shell
claude mcp add archivum -- npx -y archivum mcp

Codex CLI

Either use the command, or add the equivalent to ~/.codex/config.toml (see the Codex MCP docs):

Shell
codex mcp add archivum -- npx -y archivum mcp
TOML
[mcp_servers.archivum]
command = "npx"
args = ["-y", "archivum-cli", "mcp"]

Other clients

Clients that take an mcpServers JSON block, such as Antigravity, Hermes Agent, omp and OpenClaw, generally accept this shape:

JSON
{
  "mcpServers": {
    "archivum": {
      "command": "npx",
      "args": ["-y", "archivum-cli", "mcp"]
    }
  }
}

Where that goes differs per client; see Antigravity, Hermes Agent, omp and Codex.

Compatibility. Checked with the official MCP SDK client and with omp. Claude Code and Codex use their documented configuration formats. Other clients should work with the generic block above; if one does not, check its MCP docs for where the block goes.

Claude Code hooks

archivum init merges these into ~/.claude/settings.json; you can also add them yourself:

JSON
{
  "hooks": {
    "SessionStart": [
      { "hooks": [ { "type": "command", "command": "npx -y archivum-cli hook session-start" } ] }
    ],
    "Stop": [
      { "hooks": [ { "type": "command", "command": "npx -y archivum-cli hook stop" } ] }
    ]
  }
}
  • SessionStart reads the hook JSON from stdin and prints the memory digest as additionalContext so Claude sees it. The output is capped at 10,000 characters. If the space has no context yet it prints nothing.
  • Stop reads the session JSONL at transcript_path, converts it to events, scrubs secrets and saves transcripts/<session_id>.json. If the same session is saved again with new content it becomes pending again. It prints nothing.
  • The space is ARCHIVUM_SPACE if set, otherwise the basename of the hook's cwd.
  • Hooks never fail your session: they always exit 0, and errors go to stderr only when ARCHIVUM_DEBUG=1.

For agents without hooks, log transcripts yourself with archivum log and read context with archivum context or the MCP tools. omp has no hooks of this kind: run archivum import omp (for example before archivum dream) to turn its session files into transcripts.

Dreaming

A dream is a background pass that checks the wiki against recent transcripts and notes, fixes stale or wrong facts (marking dates and staleness), merges duplicates, links pages and keeps _index.md current. Nothing changes in your live wiki until you apply the result.

How a run works

  1. Select. Pending transcripts (oldest first, at most 50 / 6,000,000 characters) and notes not yet consolidated (at most 300). Counts and a rough token estimate are printed and you confirm (or pass --yes). The run refuses if the estimate exceeds the budget.
  2. Stage. The live wiki is copied into proposals/<id>/wiki, and the checksums of your live pages are remembered.
  3. Analyze. One analyzer agent per input reads it against the staged wiki and writes what it learned. Large inputs are split.
  4. Organize. One organizer agent merges duplicates, resolves conflicts, links pages and updates the index.
  5. Propose. The result is saved as a proposal in review state. If the organizer fails after analyzers wrote, the proposal is still kept and marked partial.
  6. Apply or reject. See below.

Providers

You bring the key. anthropic (default) uses the Messages API. openai works with any OpenAI-compatible /chat/completions endpoint that supports tool calling: a hosted provider, a local server, or a router such as 9router.

Shell
# Anthropic (default)
export ANTHROPIC_API_KEY="sk-ant-..."

# any OpenAI-compatible endpoint, e.g. a local router
export ARCHIVUM_LLM_PROVIDER=openai
export ARCHIVUM_LLM_BASE_URL="http://localhost:20128/v1"
export ARCHIVUM_LLM_API_KEY="..."
export ARCHIVUM_ANALYZER_MODEL="your-model"
export ARCHIVUM_ORGANIZER_MODEL="your-model"

Token budgets

Budgets are counted in tokens, not money; check your provider for pricing. The default budget is 3,000,000 tokens. Before running, dream prints a rough estimate from the size of the transcripts and existing wiki. It is an estimate only: actual usage depends on the model and how many turns the agents take. If a run hits the budget it stops with a budget-exhausted status and keeps what was staged for review.

Review first, apply skip rule, restore

  • Dreaming never touches the live wiki. Use archivum diff, then apply or reject. (--apply on dream is opt-in.)
  • apply writes a file only if the live page is still exactly what the dream started from; otherwise it is skipped and listed. --force overrides that.
  • Applying records history, marks the proposal's transcripts dreamed and advances the notes marker.
  • Every applied write is a version: archivum restore <path> --version N.

Security model

  • Transcripts are untrusted data. They are given to the model in a labelled format and the agents are instructed to treat them as data, not instructions. Instructions hidden in a transcript could still influence a model; this reduces that risk, it does not remove it.
  • Document-only tools. Dream agents can only list, read, grep, write, edit, delete and rename wiki documents, and submit. They have no shell and no network access.
  • Secret scrubbing. API keys, bearer tokens, PEM blocks, AWS, GitHub, Slack and Google keys and JWTs are replaced by [REDACTED:<kind>] before transcripts are saved and on every wiki write. Pattern-based scrubbing cannot catch every secret.
  • Review before apply and versioned restore are the final safety net.
Limits. Dreaming quality depends on the model you choose. In our tests on synthetic projects a dreamed wiki answered questions about a long, noisy history far better than raw notes searched by keyword (94% vs 38% with GPT-5.6, 100% vs 38% with Gemini 3.8), but on short histories it only matched them. That says little about your own data, so read the diff before you apply.

Simulation (/try/)

The /try/ page is an interactive demo of memory and dreaming in your browser: a chat with a pretend coding agent, an animated stage showing the analyzer and organizer at work, and a panel with the context, wiki, notes, transcripts and the proposal diff you approve or reject. It never reads or writes your local Archivum files.

  • Recorded (default): a scripted scenario. Nothing is sent anywhere.
  • Live: a real model, paid for by the site, so you need no key. It is rate-limited, and when a limit is hit the page tells you and returns to Recorded. Your messages go to the site and its model provider, so type nothing private. Your own CLI memory never goes through the site.

Privacy

DataLeaves your machine?
Wiki, notes, transcripts, historyNo. They are files in your Archivum home.
MCP tools and hooksNo. They run locally; npx may download the package from the npm registry.
archivum dreamYes, to the LLM endpoint you configured: the selected transcripts, notes and wiki pages. With a local router, that is whatever the router forwards.
The /try/ simulation, Live modeYes, your messages go to this site's server and its model provider. Recorded mode sends nothing.
Archivum itselfNo telemetry, no accounts, no hosted storage.

Secrets are scrubbed before transcripts are stored, but the scrubber is pattern-based. See the privacy notice for the website.

FAQ

Does it cost anything?

Archivum is free. Dreaming spends tokens on your own LLM account; the simulation's Live mode is paid by the site owner within caps.

Do I need an account?

No. There are no accounts, and no hosted storage.

Can I use a model other than Anthropic's?

Yes, set ARCHIVUM_LLM_PROVIDER=openai with any OpenAI-compatible endpoint that supports tool calling. You must name the models.

Will dreaming overwrite my edits?

No. Dreams write to a proposal, and apply skips files you changed since the dream began unless you pass --force. Applied changes can be restored.

How do I remove it?

Delete the Archivum hooks from ~/.claude/settings.json (a backup is at settings.json.archivum-bak), run claude mcp remove archivum or codex mcp remove archivum, and delete the Archivum home folder.

How long are transcripts kept?

Transcripts dreamed more than 30 days ago are deleted by default; change it with archivum retention --days N. Wiki pages and notes are not deleted.

Does it work with my agent?

Claude Code (hooks and MCP) and Codex (MCP) are supported by init. Other MCP clients should work with the generic config but have not all been tested; for agents without hooks use archivum log.