@jalkarna/archiva
v0.1.5
Published
Git-native decision memory for AI coding agents.
Downloads
688
Maintainers
Readme
Archiva
Git-native decision memory for AI coding agents.
Every agent session starts cold. It doesn't know why that auth check is there, which approaches were tried and dropped, or that the team explicitly decided against the obvious solution two months ago. Archiva stores those decisions beside the code so agents can read them before touching anything.
It runs as a CLI and MCP server. Tools like Claude Code, Codex, Cursor, and other MCP-capable agents can call why before editing a file and write_decision after making a meaningful choice.
Why agents need it
Git remembers what changed. It doesn't remember why.
That gap causes predictable problems:
- the next session reopens the same problem from scratch
- deliberate constraints look like accidental complexity
- rejected approaches get tried again
- ADRs drift away from the code they describe
- multi-agent work loses the thread between handoffs
Archiva stores reasoning in .decisions/ beside the code, indexes it by source anchors, and exposes it through archiva why, archiva history, archiva lint, and MCP tools.
What it does
Decision records live in your repo, versioned with the code they describe, queryable by file and anchor. The design is intentionally repo-native: no daemon, no hosted service, no account.
Archiva keeps full decision detail available when an agent asks for it, while .dmap files provide compact startup context for session hooks.
How it compares
Most AI memory tools are broad recall systems. They store preferences, notes, conversations, embeddings, graph entities, or whole session traces so an agent can remember more across tools.
Archiva is deliberately narrower: it stores why a specific piece of code exists. The unit of memory is not a chat message or semantic note. It is a decision record attached to a source file, anchor, line range, fingerprint, and supersession chain.
| Tool category | What it is good at | How Archiva is different |
|---|---|---|
| Supermemory | Cross-app personal memory through a hosted memory API and MCP server. | Archiva is repo-local and git-native. It does not try to remember everything about the user; it records engineering decisions beside the code. |
| OpenMemory / Mem0 | Project-scoped coding preferences and automatically retrieved agent context. | Archiva does not infer broad preferences. It captures explicit implementation rationale, rejected alternatives, and decision history for code anchors. |
| ICM | A full memory runtime with hybrid search, temporal decay, hooks, and many MCP tools across editors. | Archiva is small and purpose-built: no vector DB, no semantic memory engine, no global recall layer. It is a decision log and drift checker for repositories. |
| Basic Memory | Markdown knowledge management, notes, search, and project knowledge bases. | Archiva is structured around code files and anchors, with .dlog and .dmap files that can be linted, re-anchored, and committed with source changes. |
| Zep / Graphiti MCP and graph memory tools | Temporal knowledge graphs, entity relationships, semantic retrieval, and evolving context. | Archiva avoids building a general knowledge graph. It answers a narrower question agents hit constantly: "what decision explains this code, and what should I not repeat?" |
| ADRs and docs | Human-written architecture records and design notes. | Archiva is closer to the code path agents actually touch. Decisions are queryable by file/anchor, can be marked stale when fingerprints drift, and can be superseded over time. |
Archiva is best used alongside broad memory tools, not necessarily instead of them. Use a general memory layer for user preferences, session summaries, and cross-project recall. Use Archiva for code-level decision provenance that should move with the repository.
Features
- Decision memory for agents: tools can ask why code exists before changing it
- Rejected alternatives preserved: failed approaches stop getting rediscovered every session
- Code-anchored rationale: decisions attached to functions, classes, exports, and blocks, not brittle line numbers
- Low-context session hints: agents load compact
.dmapentries instead of full YAML logs - Local-first: no account, daemon, or hosted service
- MCP-native: works with any MCP-capable agent using a stdio server
Install
npm install -g @jalkarna/archiva
archiva --versionRequires Node.js 20 or newer.
Quick start
archiva initFor Claude Code, also register the MCP server:
claude mcp add -s local archiva -- archiva mcpAgents can then call Archiva through MCP:
- before editing, call
why - after a meaningful implementation choice, call
write_decision - when checking drift, call
ghost_check
The intended loop:
read map -> ask why -> edit code -> write decision -> lint driftUsage
Initialize a project
archiva initCreates:
.decisions/.claude/settings.jsonwith Archiva hooks and MCP config- an
AGENTS.mddecision logging instruction block
Decision files are committed with the code by default. For local-only logs:
archiva init --gitignore-decisionsCheck decision health
archiva statusShows decision counts and drift/orphan health across the repo.
Ask why code exists
By line:
archiva why src/auth/session.ts 52By anchor:
archiva why src/auth/session.ts fn:processCheckoutView decision history
archiva history src/auth/session.ts fn:processCheckoutShows the supersession chain for an anchor.
Lint decision state
archiva lintChecks for:
- stale decisions when code fingerprints change
- orphan decisions when anchors disappear
- complex undecided functions
- stale decisions that were not superseded
Safe orphan cleanup:
archiva lint --fixRun the MCP server
archiva mcpStarts the stdio MCP server. You typically don't run this manually; MCP clients launch it from config.
Run hooks manually
Session context injection:
archiva hooks session-startRe-anchor a file after edits:
ARCHIVA_FILE=src/auth/session.ts archiva hooks post-tool-use
# or
archiva hooks post-tool-use src/auth/session.tsMCP configuration
For MCP-capable tools that accept stdio servers:
{
"mcpServers": {
"archiva": {
"command": "archiva",
"args": ["mcp"]
}
}
}For tools that prefer a server object only:
{
"command": "archiva",
"args": ["mcp"]
}archiva init writes the following to .claude/settings.json:
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "archiva hooks session-start" }] }
],
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [{ "type": "command", "command": "archiva hooks post-tool-use" }]
}
]
},
"mcpServers": {
"archiva": { "command": "archiva", "args": ["mcp"] }
}
}MCP tools
write_decision
Records a decision for a file and anchor:
{
"file": "src/auth/session.ts",
"anchor": "fn:processCheckout",
"lines": [42, 67],
"chose": "optimistic locking via version field increment",
"because": "checkout and inventory deduction can race under concurrent carts",
"rejected": [
{
"approach": "SELECT FOR UPDATE",
"reason": "deadlocks under concurrent carts touching the same SKU"
}
],
"expires_if": "inventory service migrates to event sourcing",
"supersedes": "dec_001"
}supersedes is optional. When present, it must reference an existing decision id from why.
why
Reads decision memory before editing:
{
"file": "src/auth/session.ts",
"anchor": "fn:processCheckout"
}Omit anchor to get all decisions for the file.
ghost_check
Checks for stale or orphaned decisions:
{
"file": "src/auth/session.ts"
}File format
For src/auth/session.ts, Archiva writes:
.decisions/src/auth/session.ts.dlog
.decisions/src/auth/session.ts.dmap.dlog is the full YAML decision log. .dmap is a compact spatial map for low-token context injection.
Example .dmap:
42-67:fn:processCheckout
89-94:block:if_version_mismatch:STALEAgent instructions
Archiva works best when agents are explicitly told to use it. Add this to AGENTS.md or your system prompt:
## Decision logging (Archiva)
Before modifying a file, read the decision map injected at session start or call the `why` MCP tool.
After any non-trivial implementation choice, call `write_decision` with:
- `file` and `anchor`
- `chose`
- `because`
- `rejected`
If changing code with an existing decision:
- preserve the decision if the reasoning still holds
- call `write_decision` with `supersedes` if the reasoning changedarchiva init adds a fuller version of this to AGENTS.md.
CI
name: Decision health
on:
pull_request:
push:
branches: [main]
jobs:
archiva:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npx @jalkarna/archiva lintDevelopment
npm install
npm run check
npm test
npm run build
node bin/archiva.js --helpCurrent scope
Supports today:
- TypeScript and JavaScript anchor extraction
- YAML
.dlogfiles and compact.dmapfiles - local re-anchoring
- linting
- Claude Code hooks
- stdio MCP tools
Planned:
- Python anchors
- richer inline
@decisioncomment management - setup docs for more IDEs and agent CLIs
License
MIT
