sens-io/memobranch

memobranch

Git-native, auditable long-term memory for AI agents

Uncategorizedagent-memoryai-agentsdeepseek-harness
MemoBranch Logo

MemoBranch

Memory that branches with your agents.

English · 简体中文

Auditable, searchable, portable long-term memory for AI agents

Markdown is the source of truth · Git tracks every change · LLMs provide optional enhancements

Why MemoBranch • Capabilities • Quick Start • Web Console • Architecture • DeepSeek Harness • MCP • Operations


MemoBranch is a local-first long-term memory layer designed for AI agents and production use cases. It organizes conversational evidence, candidate knowledge, and canonical memories into a human-readable Markdown Wiki, with Git providing versioning, attribution, rollback, and cross-machine synchronization.

Inspired by OpenKnowledge's Git + LLM Wiki approach, MemoBranch is an independent implementation and includes none of its source code. Development follows the OpenSpec workflow: proposal → specs → design → tasks → implementation → verification. Acceptance status for each capability is determined by the verification record for the corresponding version.

Core design constraint: The LLM Wiki follows Karpathy's method: continuously compile and maintain interconnected, source-backed knowledge—not just vector search. Incremental cross-source compilation, explicit answer filing, and semantic Lint have passed local functional acceptance and isolated independent review. See the core design and criterion-by-criterion verification record. Local acceptance does not establish GitHub-hosted CI results, real-model quality, or production release validation.

[!IMPORTANT] An LLM is not a source of truth. Capture, review, Git versioning, recovery, Chinese/English retrieval, and DeepSeek Harness and MCP integration remain fully functional without a model API.

For the journey from raw sources to a maintained knowledge network, see the Ingest / Query / Lint guide: inspect a multi-page plan before explicitly applying it. Ordinary queries are read-only; answer filing and Lint repairs require separate authorization. Model-driven compilation, question answering, and semantic analysis require a chat model; structural checks and the existing memory workflows do not.

💡 Why MemoBranch

Agent memory is often just a vector database, leaving basic questions unanswered: Where did this information come from? Why is it trustworthy? Who changed it? How are conflicts handled?

MemoBranch turns memory into a governed knowledge chain:

flowchart LR
    A[Conversations / Tool Results / Human Input] --> B[Evidence<br/>Immutable Sources]
    B --> C[Candidate<br/>Pending Review]
    C -->|Approve / Consolidate| D[Wiki Memory<br/>Canonical Knowledge]
    C -->|Insufficient Evidence / Conflict| E[Review Queue<br/>Human Review]
    D --> F[Lexical + Semantic + Graph<br/>Hybrid Retrieval]
    F --> G[Agent Context<br/>Permission-Filtered Context]
    D --> H[Git History<br/>Attribution / Rollback / Sync]
Common questionHow MemoBranch handles it
“Where did this memory come from?”Every canonical memory retains evidence references and Git history
“What if new information conflicts with existing knowledge?”It enters the review queue instead of silently overwriting existing knowledge
“Can an agent declare itself an administrator?”No. Identity and permissions are determined by server-side configuration
“Can secrets end up in Git or a vector database?”Sensitive content is envelope-encrypted, logical keys use opaque paths, and protected content is excluded from indexes and generated files
“What if the process crashes halfway through a write?”A write-ahead transaction journal supports exact rollback or complete replay
“Can I still search if the model API goes down?”Retrieval falls back to deterministic Chinese/English lexical search

✨ Core Capabilities

CapabilityDescription
📚Git-native WikiMarkdown is authoritative; every logical change has an attributed Git commit
🕸️Cross-source knowledge compilationRules and catalogs guide incremental maintenance of source, entity, concept, synthesis, comparison, and query pages; multi-page changes commit atomically
💬Source-backed answers and filingNavigate before reading pages, bind answers to actual cited revisions, and preserve source restrictions and uncertainty when explicitly saving
🧭Structural and semantic maintenanceStructural checks work without a model; models propose evidence-backed maintenance suggestions, with separate authorization required for repairs
🧾Evidence-driven memoryevidence → candidates → wiki, preserving sources, confidence, conditions, and revision chains
🛡️Server-side access controlAuthorize by permission, scope, sensitivity, and tenant before reading content
🔐Policy-driven envelope encryptionPer-record DEKs and AES-256-GCM for any sensitivity level selected by policy, with cryptographic erasure
🔎Hybrid retrievalCJK/English lexical search, optional embeddings, Wiki link expansion, and incremental indexing
🔄Remote Git synchronizationAhead/behind/diverged states, fast-forward updates, regular merges, conflict aborts, and controlled pushes
🧯Crash recoveryJournal multi-file writes before atomic replacement; automatically roll back or replay on startup
🔌CLI + agent pluginsCLI, MCP, and a native DeepSeek Harness plugin share stable errors and least-privilege contracts
📈Production observabilityA single-instance maintenance service, /healthz, Prometheus /metrics, and redacted audit logs
🧩OpenSpec-driven developmentTraceable proposals, specifications, designs, tasks, verification evidence, and archives

[!NOTE] MemoBranch is a local service with one tenant per vault. The local Web console provides structured management, not arbitrary file editing. It does not include a hosted control plane, multi-tenant database, distributed write consensus, or automatic semantic conflict resolution.

🚀 Quick Start

Development branch preview: Easier setup, approved-context recall, Wiki before/after review and correction, plus 37 reproducible evaluation cases, are available from the current source branch. These additions have not been published to npm yet. Existing npm installation instructions below still refer to the released package.

Requirements

  • Node.js 20 or later
  • Git available on PATH

Installation

Install the published package from npm; no source checkout or build is required:

npm install -g memobranch
memobranch --help

For a pinned installation, use npm install -g memobranch@1.1.0. The package provides memobranch and memobranch-mcp, plus the equivalent aliases amem and amem-mcp used in the examples below.

From Source (Development)

git clone https://github.com/sens-io/memobranch.git
cd memobranch
npm ci
npm run build
npm link

Create Your First Memory in 60 Seconds

# 1. Initialize a vault
amem init ~/my-agent-memory --name personal-agent --json

# 2. Capture raw evidence
amem capture "Please remember: respond concisely in Chinese by default" \
  --root ~/my-agent-memory \
  --scope user \
  --sensitivity internal \
  --json

# 3. Create a candidate for review
amem propose "The user prefers concise replies in Chinese." \
  --root ~/my-agent-memory \
  --key "Reply language and style" \
  --kind preference \
  --scope user \
  --confidence 0.95 \
  --explicit \
  --json

# 4. Consolidate into canonical Wiki memory according to policy
amem consolidate --root ~/my-agent-memory --json

# 5. Search and generate agent context
amem search "How does the user prefer responses?" --root ~/my-agent-memory --json
amem context "How should I reply to this user?" --root ~/my-agent-memory

Check vault health:

amem doctor --root ~/my-agent-memory --json

🏗️ How It Works

System Architecture

flowchart TB
    Agent[AI Agent / Human] --> CLI[CLI]
    Agent --> MCP[MCP Server]
    Agent --> DSH[DeepSeek Harness Plugin]

    CLI --> Policy[Identity & Policy]
    MCP --> Policy
    DSH --> Policy
    Policy --> Vault[Memory Vault]

    Vault --> TX[Transaction Journal]
    Vault --> Crypto[Envelope Encryption]
    Vault --> Search[Hybrid Search]
    Vault --> Git[Shadow Git Repository]

    TX --> Files[(Markdown Wiki)]
    Crypto --> Files
    Search --> Index[(Derived Index)]
    Git --> Remote[(Optional Git Remote)]

    Vault --> Ops[Maintenance Service]
    Ops --> Health["/healthz"]
    Ops --> Metrics["/metrics"]
    Ops --> Audit[(Redacted Audit)]

Vault Layout

vault/
├── agent-memory.json       # v2 configuration
├── AGENTS.md               # Agent usage constraints
├── .gitignore              # Keep .amem runtime state out of an enclosing Git repository
├── evidence/               # Immutable raw evidence
├── candidates/             # Candidates awaiting review
├── wiki/                   # Canonical memory
├── MEMORY.md               # Non-confidential resident cards (generated)
├── INDEX.md                # Non-confidential catalog (generated)
├── log.md                  # Git audit summary without document bodies
└── .amem/
    ├── git/                # Shadow Git metadata
    ├── keys.json           # Wrapped data keys, excluded from Git
    ├── transactions/       # Write-ahead transaction journals
    ├── search-index.json   # Rebuildable lexical index, excluded from Git
    ├── embeddings.json     # Rebuildable vector cache, excluded from Git
    ├── audit.jsonl         # Structured, redacted audit log
    └── metrics.json        # Bounded counters and gauges

Memory Governance Rules

  • evidence/ is append-only raw evidence; stable hashes prevent duplicate capture.
  • candidates/ holds extracted knowledge awaiting review. Conflicting or low-confidence content is not automatically promoted to canonical memory.
  • wiki/ contains only reviewed canonical memory and is the authoritative source for retrieval and context generation.
  • A procedure requires at least two pieces of evidence by default.
  • All evidence references, promotion/supersession relationships, and managed document IDs undergo cross-file integrity checks.
  • Different content with the same scope + kind + key creates an explicit conflict.
  • Ordinary retrieval excludes conflicted records. Rejecting the last conflicting candidate restores the original canonical memory.
  • LLM-extracted content inherits the evidence's scope, and its sensitivity can only increase, never decrease.
  • forget is an auditable revocation that preserves history; erase additionally destroys the local wrapped data key.

🔍 Search and LLM Enhancements

Basic retrieval requires no model. The system maintains a persistent incremental index of Latin words, Chinese characters, and CJK bigrams, with reproducible rankings for the same vault.

Configure an OpenAI-compatible endpoint to enable automatic extraction, memory-grounded answers, and semantic retrieval:

export AMEM_LLM_API_KEY="..."
export AMEM_LLM_MODEL="gpt-4.1-mini"
export AMEM_LLM_BASE_URL="https://api.openai.com/v1"

amem capture "Please remember: respond concisely in Chinese by default" \
  --extract \
  --root ~/my-agent-memory \
  --json

amem ask "How should I respond?" --root ~/my-agent-memory --json

After setting an embedding model in index.embeddingModel in agent-memory.json:

amem reindex --semantic --root ~/my-agent-memory --json
amem search "Response preferences" --semantic --root ~/my-agent-memory --json

If the vector service is unavailable, requests still return lexical and graph-based results and report semanticStatus: "degraded". Encrypted documents are never sent to the embedding API, even if the encryption policy is later changed.

🔐 Security and Confidential Memory

Envelope Encryption

Before first reading or writing records that require encryption under policy, supply a 32-byte master key. The default policy covers sensitive and secret, and can be extended to internal or public:

export AMEM_MASTER_KEY="$(openssl rand -hex 32)"

amem capture "Confidential content visible only to authorized agents" \
  --root ~/my-agent-memory \
  --sensitivity secret \
  --json

Each confidential record uses a separate data key. Its complete logical metadata and body are authenticated and encrypted with AES-256-GCM. Git-tracked files retain only a minimal, non-sensitive envelope; filenames use opaque IDs, and commit subjects do not contain logical keys.

[!WARNING] Never put AMEM_MASTER_KEY in the repository, configuration, remote URLs, or shell history. In production, provide it through an OS keychain, secret manager, or secure process-level injection.

Key recovery considerations:

  • .amem/keys.json stores data keys wrapped by the master key and is not synchronized through Git.
  • Initialization and subsequent migrations maintain an .amem/ exclusion in the vault's .gitignore, preventing accidental tracking by an enclosing Git repository.
  • Reading confidential memory on another host requires separately and securely transferring both the master key and .amem/keys.json.
  • Losing either makes the corresponding historical ciphertext unrecoverable.
  • erase only guarantees that this vault can no longer decrypt the record. It cannot delete external backups, exported plaintext, or third-party copies.
  • The reason for erase is normalized and stored as a SHA-256 commitment; its plaintext never appears in Git. Legacy recovery records without a reason digest are explicitly marked as unrecorded.
  • Policy-encrypted records are excluded from MEMORY.md, INDEX.md, persistent indexes, vector APIs, audit body content, and metric labels. Recovery journals are encrypted under the same policy.
  • Evidence IDs bind scope, sensitivity, source URI, and body. Remotes may only append evidence, not rewrite or delete existing evidence.

Permission Model

The MCP principal is constructed entirely from the server environment. Callers cannot impersonate another identity or elevate privileges through tool arguments.

PermissionPurpose
readSearch, read, and generate context
writeCapture evidence and create candidates
reviewConsolidate, approve, reject, and revoke
syncInspect remote status and synchronize
maintainRecover, index, check health, and run the service
adminIncludes all permissions and allows cryptographic erasure

Authorization checks scope, maximum sensitivity, and tenantId together, before decryption, scoring, graph expansion, summary generation, or embedding requests. Every non-admin principal must be bound to the tenantId in the vault configuration; only the implicit local administrator may omit it.

🐋 DeepSeek Harness Plugin

MemoBranch integrates directly into DeepSeek Harness's tool registry as a native Cordis plugin, without a separate MCP subprocess. It follows the Harness lifecycle, supports hot replacement when configuration changes, and lets Cordis automatically unregister all tools on unload.

The plugin has been verified with @deepseek-ai/dsh-tools@0.1.2-rc.1. Its declared compatibility range, ^0.1.2-rc.1, includes that prerelease and subsequent compatible stable 0.1 versions.

[!NOTE] MemoBranch itself supports Node.js 20+. The dependency chain of the official @deepseek-ai/dsh@0.1.2-rc.1 requires Node.js 22.19+. Follow the engines declaration of the Harness version you install.

Install from npm

With DeepSeek Harness already installed, add MemoBranch directly to a Harness profile. A separate global MemoBranch installation is not required:

dsh plugin --profile personal-agent add memobranch
dsh --profile personal-agent --dump-config
dsh --profile personal-agent

Install from Local Source

Build MemoBranch, then install the project directory into a Harness profile:

cd /absolute/path/to/memobranch
npm ci
npm run build

dsh plugin --profile personal-agent add /absolute/path/to/memobranch
dsh --profile personal-agent --dump-config
dsh --profile personal-agent

When installing from GitHub, pin a commit:

dsh plugin --profile personal-agent add github:sens-io/memobranch#<commit-sha>

A Git installation builds TypeScript through prepare. With pnpm 10 or later, explicitly allow the memobranch build script in the profile's pnpm-workspace.yaml. This authorizes dependency code to run during installation, so grant it only to trusted, pinned commits.

Configuration

Identity, permissions, tenant, keys, and provider credentials are still injected by the launching process through the AMEM_* environment variables listed below. Models cannot override them through tool arguments. If vaultRoot is empty, it falls back to AMEM_VAULT, then the current working directory.

To override plugin defaults, override the same plugin entry in the profile's cordis.patch.yml:

- id: memobranch-memory
  name: memobranch/deepseek-harness
  config:
    vaultRoot: /absolute/path/to/memory-vault
    defaultScope: project
    defaultSensitivity: internal
    defaultSearchLimit: 8
    defaultMaxContextCharacters: 12000

Schemastery validates configuration at load time. defaultSearchLimit must be within 1..50, and defaultMaxContextCharacters within 500..50000. Invalid configuration prevents all tool registration.

Least-Privilege Tool Set

The plugin limits model-visible tools according to AMEM_PERMISSIONS, while MemoryVault authorizes each operation again at execution time:

PermissionVisible tools
readmemory_context, memory_search, memory_get, memory_version, memory_config, memory_policy, memory_history
writememory_capture, memory_propose
reviewmemory_consolidate, memory_review, memory_forget
adminAll tools, including memory_erase
maintainmemory_doctor, memory_recover, memory_reindex, memory_maintenance
syncmemory_remote_status, memory_remote_sync

All tools declare typed arguments and standardized output through the official defineTool API. write, review, maintain, and sync can each be granted independently: internal reads needed by an operation use that operation's authority without exposing memory_get or memory_search. Scope, sensitivity, and tenant checks remain in force. Automatic synchronization during maintenance additionally requires sync.

Cancellation is isolated per invocation and does not stop model requests belonging to other sessions. Writes waiting for a lock or not yet in the commit phase stop and roll back. Transactions already in the commit phase, recovery, and cryptographic erasure settle safely before returning OPERATION_CANCELLED. If a commit was produced, the error's details.committed lists the operation and commit ID. No extraction or subsequent write starts after cancellation. Plugin unload cancels and awaits cleanup of all calls it owns.

Git commands run for at most 30 seconds by default, configurable through AMEM_GIT_TIMEOUT_MS (1..300000 milliseconds). Cancellation or timeout terminates the associated transport processes. A confirmed successful push is not rolled back locally. If a push is interrupted before confirmation, the remote outcome may be unknown; inspect remote status before retrying. Agents should call memory_context before tasks that need long-term context.

🖥 Web Management

The local management console offers a dashboard, authorized memory/evidence browsing, capture and candidate review, Wiki workflows, configuration, health checks and Git history.

[!NOTE] Available starting with npm version 1.1.0. Install or upgrade, then start the console:

npm install -g memobranch@1.1.0
memobranch web --root /absolute/path/to/memory-vault --port 0

Initialize the vault first with memobranch init /absolute/path/to/memory-vault if needed. Open the printed http://127.0.0.1:<port> URL, then enter the separately printed token. --port 0 selects a free port; a fixed port such as --port 3210 is also supported. Stop with Ctrl+C.

Maintainers: one-command npm release and recovery guide.

  • Memory: filter and paginate records, inspect provenance, capture evidence, propose, approve/reject and revoke memories.
  • LLM Wiki: browse pages, prepare ingestion plans, run read-only queries, explicitly prepare answer-filing plans, run structural/semantic lint and separately approve plans. Edit purpose/rules with revision checks.
  • Configuration: edit non-secret operational settings with administrator authorization and stale-write protection. Identity, tenant, credentials, encryption policy and remote URLs stay outside the browser.
  • Operations: inspect health and history, rebuild the lexical index, recover transactions and explicitly synchronize an already-configured Git remote. Web mode does not start the background maintenance scheduler.

The Chinese-language UI is bundled locally with no CDN dependencies. It binds only to 127.0.0.1, requires a token plus exact Host/Origin checks, and inherits the launching process's AMEM_* identity and access restrictions. Keep the token private; it is held only in page memory and rotates on restart. Desktop/browser refresh requires entering it again. Do not expose this console through a public proxy. Irreversible key erasure remains CLI-only in the Web workflow.

Web requests are capped at 1 MiB, except explicit Wiki plan approval and answer filing (16 MiB). Generated previews are checked against their write-back budget before being returned; oversized wor