Skip to content

planailabs/memvault

Repository files navigation

memvault

Local-first, peer-to-peer knowledge base with a content-addressed block store, knowledge graph, full-text search, and MCP integration.

Download binaries

Freshly built by our GitLab CI: » Download

Quick start (CLI)

# Store a note
memctl put "Meeting notes from today" --title "Meeting 2026-05-04" --tag "project:acme"

# Search
memctl search "meeting"

# Add entities and link them
memctl graph add person --prop name=Alice
memctl graph add project --prop name="Project X"
memctl graph link <alice-id> <project-id> works_on

Quick start (MCP)

# Add to Claude Code — local mode, talks to the redb file directly
claude mcp add memvault -- memvault-mcp --db ~/.local/share/memvault/blocks.redb

Run /mcp inside Claude Code to verify the connection, then just talk to it:

> Store a note in memvault: the staging DB password rotates every 90 days, tag it ops:staging
> Search memvault for everything we know about the api gateway
> Add Alice and the payments service to the knowledge graph and link her as maintainer
> What did I save about the acme project last week?
> Attach this PDF to memvault and extract its text

See MCP server below for HTTP mode, all flags, and manual .mcp.json configuration.

Quick start (cluster)

Note

Clustering is optional — a single node works fully standalone. Run memctl genesis to start a cluster; add peers whenever you want replication across machines.

# Node A — create the cluster and start a node
memctl genesis
memctl daemon --listen /ip4/0.0.0.0/tcp/4001

# Node A — issue a single-use join token (keystore-only, works while the daemon runs)
memctl token issue --node-role node --label node-b
# → mvjoin1:...

# Node B — join with the token, then start a node pointed at node A
memctl cluster-join mvjoin1:...
memctl daemon --bootstrap /ip4/<node-a-ip>/tcp/4001
# cluster-join stashes the token; the daemon redeems it automatically
# over /join/1.0 once the nodes connect

Blocks now sync both ways. Try it:

# Node B — write a document
memctl put "Deploy notes for the api gateway" --title "Deploy 2026-07-05" --tag "project:gateway"

# Node A — it syncs over
memctl search "gateway"
memctl list --limit 5

# Grow the knowledge graph — entities and edges sync like any other block
memctl graph add service --prop name=api-gateway
memctl graph add person --prop name=Alice
memctl graph link <alice-id> <service-id> maintains
memctl graph query <alice-id>

# Check cluster health — peer count should show the other node
memctl status

Architecture

memvault stores everything as content-addressed blocks in a single redb database file (blocks.redb). Secondary indexes (by tag, author, time, bucket, causal links, provenance) are derived from the blocks and can be rebuilt at any time with memctl repair-index.

Three types of objects live in the store:

Type ID format Example
Document doc:<hex> Notes, memos, any text with frontmatter
Entity entity:<hex> Knowledge graph nodes (person, project, concept, skill, ...)
File file:<hex> Files stored as UnixFS DAGs (IPFS-compatible)

Any object can link to any other via typed, weighted edges. An edge from a document to an entity, or from a file to another file, works the same way.

Layered on top of blocks and edges:

  • Buckets — every write is scoped to a bucket. Agents get their own default bucket; capability grants control who can read or write which bucket, and buckets can be merged into a canonical one (a read/ACL alias overlay — nothing is moved or re-signed).
  • VFS — a per-bucket virtual filesystem: directories, paths, and tree views over any node, with a node mountable at multiple paths.
  • Views — saved tag filters for scoping queries.
  • Skills — graph entities that aggregate instruction docs and resource files by typed edges, hydratable to disk as a SKILL.md bundle.
  • Cross-cluster shares — federation via share proposals between clusters, approved or rejected through an inbox/outbox flow.

MCP server

The MCP server (memvault-mcp) exposes memvault to LLM agents via the Model Context Protocol over stdio.

Two modes

Local mode — direct access to a redb file, no daemon needed (takes priority when --db is set):

memvault-mcp --db ~/.local/share/memvault/blocks.redb

HTTP mode — talks to a running daemon, authenticated with an enrolled agent identity (every request carries a JWT signed with the agent's ed25519 key):

memvault-mcp --url http://127.0.0.1:8401 --identity-dir ~/.local/share/memvault/agents/claude

Configuration

Flag Env var Default Description
--db MEMVAULT_DB -- redb path (local mode, bypasses HTTP)
--url MEMVAULT_URL http://127.0.0.1:8401 Daemon API URL (HTTP mode)
--identity-dir MEMVAULT_IDENTITY_DIR <data-dir>/identity/ui_agent Agent identity dir (HTTP mode)
--default-tags MEMVAULT_DEFAULT_TAGS -- Comma-separated scope:label tags
--default-visibility MEMVAULT_DEFAULT_VISIBILITY internal internal, federated, or public
--agent-id MEMVAULT_AGENT_ID derived from pubkey Display label for the agent's default bucket

Agent enrollment (HTTP mode)

An agent identity is created by redeeming a join token against a running daemon:

# On the cluster: issue an agent token
memctl token issue --agent-role agent-host --label claude

# On the agent host: exchange it for a credential
memvault-mcp enroll --server http://127.0.0.1:8401 --token mvjoin1:... --agent-id claude
# → credential written to <data-dir>/agents/claude/

# Run the MCP server with that identity
memvault-mcp --url http://127.0.0.1:8401 --identity-dir <data-dir>/agents/claude

Agent roles: agent-host, auditor, service, admin. Every write an agent makes without an explicit bucket lands in its own agent bucket, derived from its ed25519 pubkey.

MCP tools (62)

Documents & tags:

Tool Description
memvault_put Store a document with optional title and tags
memvault_get Retrieve a document by hex-encoded doc ID
memvault_search Full-text search across docs, entities, and files
memvault_list List recent documents, optionally filtered by tag
memvault_list_all List all nodes (docs, entities, files), optionally filtered by view
memvault_doc_history Operation history for a document
memvault_retract Soft-delete any node (creates a tombstone)
memvault_tag / memvault_untag Add / remove scope:label tags on any node
memvault_get_tags Effective tags for a node

Files:

Tool Description
memvault_upload_file Upload a local file by absolute path
memvault_read_range Read a byte range from a file
memvault_extract_text Extract text from PDF, DOCX, HTML, Markdown
memvault_file_info Manifest metadata (name, MIME type, size)
memvault_pin / memvault_unpin Pin / unpin against garbage collection

Knowledge graph:

Tool Description
memvault_graph_add Create an entity (person, project, concept, ...)
memvault_get_entity / memvault_list_entities Fetch one / list entities
memvault_graph_link Link two entities by hex ID
memvault_graph_query List all edges for an entity
memvault_traverse Walk the graph from any node up to a max depth

Cross-type linking:

Tool Description
memvault_link Link any two nodes: entity:<hex>, doc:<hex>, file:<hex>
memvault_edges List all edges (in + out) for any node
memvault_unlink Remove an edge by ID

VFS (memvault_vfs_*): ls, tree, resolve, find, mkdir, link, unlink, mv — organise nodes into a per-bucket directory hierarchy; a node can be mounted at multiple paths, and unlinking never deletes the underlying node.

Skills (memvault_skill_*): publish, list, get, rename, delete, link_resource, unlink_resource, hydrate — bundle instruction docs and resources as a skill entity and materialize it to disk as a SKILL.md bundle.

Buckets & agents (memvault_bucket_*, memvault_agent_rename): list, create, get, rename, archive, merge, unmerge, merges, grants_list — manage bucket scoping, merge overlays, and capability grants.

Views (memvault_view_*): list, create, update, delete — saved tag filters.

Cross-cluster shares (memvault_share_*): inbox, outbox, decide — review and approve/reject federation proposals (two-step: preview with confirm: false, then commit).

Export, status & audit:

Tool Description
memvault_export Export a single node to a temp file
memvault_export_vault Export the whole vault (or a filtered subset) to a directory or tar
memvault_status Block count, doc count, peer count, uptime
memvault_audit Query the audit log, optionally by op kind

Adding to Claude Code

Option 1: Project-scoped (recommended) — add to .mcp.json in your project root:

{
  "mcpServers": {
    "memvault": {
      "command": "memvault-mcp",
      "args": ["--db", "/home/user/.local/share/memvault/blocks.redb"],
      "env": {
        "MEMVAULT_DEFAULT_TAGS": "agent:claude"
      }
    }
  }
}

Option 2: Via CLI — project scope by default, --scope user for all projects:

claude mcp add memvault -- memvault-mcp --db /home/user/.local/share/memvault/blocks.redb
claude mcp add --scope user memvault -- memvault-mcp --db /home/user/.local/share/memvault/blocks.redb

HTTP mode (when a daemon is running — enroll first, see above):

{
  "mcpServers": {
    "memvault": {
      "command": "memvault-mcp",
      "args": ["--url", "http://127.0.0.1:8401"],
      "env": {
        "MEMVAULT_IDENTITY_DIR": "/home/user/.local/share/memvault/agents/claude"
      }
    }
  }
}

After adding, restart Claude Code or run /mcp to verify the server is connected. You should see 62 tools available under the memvault_* prefix.

First use — initialize the database if it doesn't exist yet:

memctl genesis

memctl CLI

Management CLI. Targets a local store via --data-dir (looks for blocks.redb inside) or --db (path to the redb file directly), or a running daemon via --url with an enrolled identity. --agent-id binds writes to an enrolled agent's identity and bucket; --bucket-id targets a specific bucket.

Commands

Run memctl <command> --help for full flags; memctl with no arguments runs a full node (web UI + P2P swarm).

# Documents
memctl genesis                    Initialize a new cluster
memctl put <text> [--title T]     Store a document
memctl get <cid>                  Retrieve a block by CID
memctl search <query>             Full-text search
memctl list [--limit N]           List recent documents
memctl history <doc-id>           Document operation history
memctl retract <cid> --reason R   Soft-delete
memctl doc <links|backlinks|dangling|reindex-links>   Document link tooling

# Knowledge graph & skills
memctl graph add <kind> --prop k=v    Create entity
memctl graph link <src> <tgt> <rel>   Link entities
memctl graph query <from>             Traverse edges
memctl skill <publish|list|get|...>   Manage skill bundles

# Cluster
memctl daemon [--listen A] [--bootstrap A,..]   Run a node (P2P swarm + web/API server)
memctl cluster-join <mvjoin1:...>               Join an existing cluster
memctl token <issue|list|revoke>                Join-token management
memctl agent <enroll|list|...>                  Agent enrollment management
memctl peers / peer-id / status                 Node info
memctl node-attest <pubkey>                     Attest a pre-genesis peer
memctl uncluster                                Detach this node from its cluster

# Buckets, grants & shares
memctl bucket <list|create|merge|...>   Bucket management
memctl grant <...>                      Capability grants
memctl share <...>                      Cross-cluster share proposals

# Import & export
memctl export / export-blocks           Export vault contents / raw blocks
memctl import-files / import-docs       Bulk import

# Maintenance
memctl repair-index               Rebuild all indexes from blockstore
memctl audit [--limit N]          Show audit log
memctl gc                         Garbage-collect unpinned blocks
memctl sigchain / diff-blocks     Inspect trust chain / compare stores

Web UI

The web UI is served by the daemon on port 8401 (by default) and provides:

  • Notes -- create, edit, view with markdown rendering, version history
  • Graph -- interactive force-directed knowledge graph with entity/doc/file nodes, focus mode, and drag-to-rearrange
  • Files -- upload, preview, download, text extraction
  • Skills -- browse and inspect skill bundles
  • Buckets -- bucket status, merges, and capability grants
  • VFS -- browse the virtual filesystem hierarchy
  • Views -- manage saved tag filters
  • Audit -- filterable audit trail with human-readable descriptions
  • Admin -- cluster status, token and agent management

Global search (Ctrl+K or the search button) searches across all node types -- document bodies, entity properties, filenames.

Node references

Cross-type linking uses a unified NodeRef format:

entity:a1b2c3d4e5f6...    # 32-byte hex entity ID
doc:9f8e7d6c5b4a...       # 32-byte hex document ID
file:4a5b6c7d...          # hex-encoded manifest CID

These work everywhere: MCP tools (memvault_link, memvault_edges), the REST API (/api/v1/links), and the web UI's quick-link forms. The legacy attachment: prefix on old edges is still understood on read.

Storage layout

~/.local/share/memvault/
  blocks.redb           # Primary block store + all indexes (incl. cluster ID)
  text_index.json       # Full-text search index cache (auto-rebuilt if stale)
  identity/             # Node identity: libp2p key + keystore.mvks (admin key, pinned genesis, tokens)
  identity/ui_agent/    # Local agent credential used by the web UI
  agents/<agent-id>/    # Enrolled agent credentials (private_key.pem, attestation, agent.json)
  trust/                # Trust anchors
  extraction.toml       # Optional media extraction config (see below)

Media extraction

Beyond plain text extraction (always on), the daemon can transcribe audio (Whisper via candle), OCR images (ocrs), and pre-render document pages with a selectable text layer (hayro + pdfplumber) — all as sandboxed WASM plugins running in background jobs after upload. Results are cached as annotation blocks and sync across the cluster like any other block; a node without a capability still serves results produced by peers.

Everything is configured in <data_dir>/extraction.toml (path overridable via MEMVAULT_EXTRACTION_CONFIG). Every option is optional — with no file at all, PDF/image page rendering works out of the box and transcription/OCR report unavailable until models are provisioned:

# Directory mapped read-only into plugin sandboxes as /models.
models_dir = "/var/lib/memvault/models"
# Office→PDF conversion (docx/odt/pptx/…): autodetects `soffice` on PATH.
#libreoffice_path = "/usr/bin/soffice"

[render]                  # PDF/image page pre-rendering
#enabled = false
dpi = 144                 # raster resolution
max_pages = 200           # hard cap per document
page_batch = 8            # pages per sandbox call (bounds guest memory)

[whisper]                 # audio transcription
model_dir = "whisper-small"   # relative to models_dir; unset = disabled
language = "auto"
max_duration_secs = 7200

[ocr]                     # image OCR + scanned-PDF text layers
#enabled = false
detection_model = "ocrs/text-detection.rten"
recognition_model = "ocrs/text-recognition.rten"

[limits]                  # per-plugin sandbox bounds (wall-clock, no fuel)
audio_timeout_ms = 900000
ocr_timeout_ms = 120000
pdfrender_timeout_ms = 300000
memory_max_pages = 40960  # 64 KiB wasm pages (2.5 GiB)

Model provisioning (no auto-download — models are explicit):

<models_dir>/
  whisper-small/          # any candle-compatible Whisper model dir
    config.json
    tokenizer.json
    model.safetensors
  ocrs/
    text-detection.rten   # from the ocrs project's released models
    text-recognition.rten

Disabling a capability (unset prerequisites or enabled = false) means: uploads don't queue the op, reads report unavailable with a reason, and nothing is cached as a failure — enabling it later takes effect on the next read with no cleanup.

Index rebuild

If search results are missing or indexes seem corrupt:

memctl repair-index

This does a two-phase rebuild:

  1. Clears and rebuilds all store secondary indexes (BY_TAG, BY_AUTHOR, BY_TIME, etc.) from the raw blocks
  2. Rebuilds the full-text search index and saves it to text_index.json

The text index cache includes a format version. When memvault is updated with index format changes, the cache is automatically discarded and rebuilt on next startup.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages