Documentation
Everything you need to run VaultBase.
Quick Start
# Install go install github.com/MimirLLC/vaultbase/cmd/vaultbase@latest # Create and initialize a vault mkdir -p ~/vault vaultbase init ~/vault company # Create your first user vaultbase user create admin@company.com "Admin" "your-password" vaultbase role assign company owner admin@company.com vaultbase permission add company owner folder "/**" "read,write,delete,admin" # Start vaultbase serve --vault=company --addr=0.0.0.0:8990
Open http://localhost:8990 and log in with your email and password.
Installation
From source
git clone https://github.com/MimirLLC/vaultbase cd vaultbase make build ./vaultbase --help
Go install
go install github.com/MimirLLC/vaultbase/cmd/vaultbase@latest
Docker
docker build -t vaultbase . docker run -p 8990:8990 -v ./vault:/vault -v ./data:/data vaultbase
Vault Setup
A vault is a directory of markdown files. Initialize it and register with VaultBase:
mkdir -p ~/vault/engineering ~/vault/sales ~/vault/shared ~/vault/users
vaultbase init ~/vault company
# Creates default roles: owner, admin, editor, viewer, agent VaultBase reads YAML frontmatter for permission matching:
--- tags: [architecture, public] --- # System Architecture Your content here...
Identity Stack
VaultBase loads a three-tier identity stack at the top of every agent briefing, so every session starts with the same shared frame: org values, team conventions, and the current user's preferences. Nothing gets re-taught.
- /vault-context.md — org identity (admin-editable)
- /groups/<name>/context.md — shared team context
- /users/<you>/context.md — personal context (self-writable)
On tenant provisioning, /vault-context.md
and the owner's personal file are seeded with template prompts. Existing files are never clobbered.
Writing identity from an agent
# MCP: scope can be "org", "team:<group>", or "me" vault_identity_set({ scope: "me", mode: "append", content: "Prefers minimal deps. Owns auth and billing." }) # Team-level conventions — synced across every group member vault_identity_set({ scope: "team:engineering", mode: "write", content: "# Engineering\n\nTest-first. 80% coverage bar.\n..." })
What the agent sees in a briefing
L0 — Identity Org: Acme is a B2B compliance platform. Compliance > speed. Team: Engineering — test-first, 80% coverage, no Friday deploys. You: Shane — principal engineer, minimal deps, owns auth + billing. L1 — Recent decisions, pending outcomes, stale alerts, knowledge gaps...
Missing identity files silently drop from the briefing. RBAC still applies — an agent never sees another user's personal context.
Permissions
Three resource types: folder,
file,
tag.
Each permission has an effect: allow
or deny. Deny always wins.
# Folder permissions vaultbase permission add company eng-editor folder "/engineering/**" "read,write" vaultbase permission add company viewer folder "/hr/**" "read" --effect=deny # Tag permissions (frontmatter only) vaultbase permission add company viewer tag "#public" "read" # Per-user folders — {user} expands to email prefix vaultbase permission add company employee folder "/users/{user}/**" "read,write" # shane@co.com → /users/shane/** # alice@co.com → /users/alice/**
Resolution order
- Explicit file-level permission
- Folder-level permission (closest ancestor)
- Tag-level permission (frontmatter only)
- Vault-level role default
- Deny wins at any level
Sync Daemon
Auto-syncs your local vault with the server. No manual push/pull.
# Clone from server vaultbase clone \ --server=https://vk.company.com \ --email=you@company.com \ --password=pass \ ~/.vaults/company # Start daemon vaultbase sync --path=~/.vaults/company # Check status vaultbase status ~/.vaults/company
Offline & Conflicts
Local edits queue to disk the moment they happen. Close your laptop, fly across the country, keep writing — on reconnect the queue drains in order. Never silently drops a change, never blindly last-write-wins.
How the queue works
# Persisted at ~/.config/vaultbase-editor/sync-state.json
{
"baselines": {
"/policies/pricing.md": {
"hash": "a1b2...",
"content": "..."
}
},
"pending": {
"/policies/pricing.md": {
"content": "...your local edit...",
"baseHash": "a1b2...",
"baseContent": "...the version you diverged from...",
"queuedAt": 1712504400000
}
}
} Push protocol
Every write carries the base_hash
the client started from. The server compares it against the current server version:
- base_hash matches → accept, return new hash, baseline advances
- base_hash stale → reject, return server content + hash for 3-way merge
- no-op (content already matches) → accept silently
- force: true → override after client-side merge
3-way merge
On conflict, the client runs a line-level 3-way merge against the captured base.
Clean merges push back automatically with force: true.
Dirty merges write standard conflict markers to the live file:
<<<<<<< local Discount authority up to 15% for annual contracts. ||||||| base Discount authority up to 10% for annual contracts. ======= Discount authority up to 12% for annual contracts. >>>>>>> server
Conflict UI
The editor surfaces conflicts in three places:
- Amber badge in the titlebar with the count of unresolved files
- Warning dot next to conflicted files in the sidebar file tree
- An in-editor banner with Keep mine, Use server, and Open server version actions
The original server version is always saved next to the file as
<path>.conflict-<ISO>.md
so nothing is ever lost. Clearing the markers auto-clears the conflict state on your next save.
Live Events (SSE)
GET /api/events
is a Server-Sent Events stream that broadcasts file and trace changes the moment
they're accepted. Every subscriber gets an RBAC-filtered view — you only
receive events for files your role can read.
Subscribe
# EventSource doesn't support custom headers — pass the token as a query param
const es = new EventSource(
"https://your-server/api/events?token=vk_..."
);
es.addEventListener("file_updated", (msg) => {
const ev = JSON.parse(msg.data);
// { path, hash, actor, time }
});
es.addEventListener("file_deleted", (msg) => { /* ... */ }); Event types
- connected — sent once after authentication succeeds
- file_updated — file was written or overwritten
- file_deleted — file was deleted
Behaviour
- 25-second heartbeat keeps the connection alive through nginx and other proxies
- Slow subscribers get events dropped rather than blocking the broadcaster
- The editor uses SSE for live updates, falling back to 10s polling if the stream drops
- When an SSE update arrives for a file you have pending edits on, the next drain hits the conflict path proactively
Context Graph
VaultBase captures not just knowledge but the reasoning behind decisions. Every decision an agent or human makes becomes a searchable precedent for future decisions.
Agent reads docs → makes decision → creates trace
↓
trace links to inputs,
policies, and reasoning
↓
Next agent faces similar situation → searches precedent
→ finds past decisions with outcomes
→ makes better-informed decision
→ creates new trace → graph grows Decision Traces
A decision trace is a markdown file that records why a decision was made.
Create a trace (CLI)
vaultbase trace create --vault=company \ --type=pricing \ --summary="8% discount for Acme annual renewal" \ --decision=approved \ --reasoning="Within agent authority per pricing-v3 §4.2" \ --input="/sales/acme.md:primary" \ --input="/policies/pricing-v3.md:governing" \ --policy="pricing-v3 §4.2: up to 10% for annual" \ --tag=pricing --tag=discount --tag=acme
Create a trace (MCP)
trace_create({
type: "pricing",
summary: "8% discount for Acme annual renewal",
decision: "approved",
reasoning: "Within agent authority per pricing-v3 §4.2...",
inputs: [
{ path: "/sales/acme.md", role: "primary" },
{ path: "/policies/pricing-v3.md", role: "governing" }
],
policies_applied: ["pricing-v3 §4.2: up to 10% for annual"],
tags: ["pricing", "discount", "acme"]
}) Search precedent
# CLI vaultbase trace precedent --type=pricing "annual contract discount" # MCP trace_find_precedent({ type: "pricing", context: "annual discount" })
Record outcomes
vaultbase trace outcome dt-2026-04-05-777 \ --status=successful \ --notes="Contract renewed for 2 years. Revenue maintained."
Intelligence Features
Get a context packet before starting any task. Returns recent decisions, pending outcomes, knowledge gaps, and stale document alerts.
vaultbase briefing --vault=company --task="pricing request"
# or MCP: vault_briefing({ task_context: "pricing request" }) When you create a decision trace, VaultBase automatically checks for contradictory prior decisions and returns warnings. The trace is still created — the warning is informational.
VaultBase tracks searches that return zero results. Over time, patterns emerge: "refund policy" searched 7 times with no results = missing document.
vaultbase gaps --vault=company
# or MCP: vault_gaps() Track revision levels for policies, ISO procedures, and controlled documents. Decision traces referencing outdated revisions are flagged.
vaultbase revision record /policies/pricing.md --vault=company --rev=v4 \
--summary="Increased discount authority"
vaultbase revision stale dt-2026-04-05-777
# → Is stale: pricing.md revised to v4 since this decision AI Agent Access
Agent runs in a synced vault directory. Reads/writes files directly. Zero overhead. The agent doesn't need to know VaultBase exists.
Static .skill.md bundles scoped to a role. Drop into CLAUDE.md includes. Low context cost.
Dynamic search and queries. Permission-scoped. For remote agents or large vaults where local files are impractical.
MCP Server
Vault content (read-only)
- vault_list — list files (permission-filtered)
- vault_read — read a file
- vault_search — full-text search (FTS5 BM25)
- vault_query — query by tag or path pattern
Context graph
- trace_create — record a decision with inputs, policies, reasoning
- trace_find_precedent — find similar past decisions
- trace_update_outcome — record what happened after a decision
- trace_search — search traces by type, tag, actor, outcome
Intelligence & briefings
- vault_briefing — identity stack + recent activity + gaps + stale alerts
- vault_gaps — queries that returned zero results, ranked by frequency
- vault_doc_revision — record a new document revision
- vault_revision_history — full revision history for a document
- vault_stale_check — flag traces citing outdated revisions
Identity (L0 context)
- vault_identity_set — write/append an identity file at scope org, team:<group>, or me
Knowledge write-back
- vault_learn — write a new learning, insight, runbook, or FAQ
- vault_update_doc — update an existing document with reason (auto-records revision)
- vault_index — re-index the vault for search
Admin
- admin_list_users, admin_create_user
- admin_list_roles, admin_create_role, admin_assign_role
- admin_add_permission, admin_list_permissions
- admin_create_apikey, admin_audit_log
Configuration
{
"mcpServers": {
"vaultbase": {
"url": "http://your-server:8990/mcp",
"headers": {
"Authorization": "Bearer vk_your_api_key"
}
}
}
} Skill Files
vaultbase pull-skills --vault=company --role=engineering-agent -o ./skills/ # Output: engineering-agent.skill.md # Contains only files the role can read # Include in CLAUDE.md or Cursor rules
Knowledge Write-Back
Agents don't just read from the vault — they write back to it. Every conversation that produces knowledge should be captured.
Write a learning
# MCP: write new knowledge
vault_learn({
path: "/learnings/pricing-insights.md",
content: "# Pricing Insights\n\nMost customers accept 5-8%...",
category: "insight",
source: "Q1 pricing review"
}) Update an existing document
# MCP: update with correction
vault_update_doc({
path: "/policies/pricing.md",
content: "...updated content...",
reason: "Agent authority increased from 10% to 15%"
})
Categories: learning,
correction,
insight,
runbook,
faq.
Write mode: write (new/overwrite) or
append (add to existing).
Docker
docker build -t vaultbase .
docker run -d \
--name vaultbase \
-p 8990:8990 \
-v /path/to/vault:/vault \
-v /path/to/data:/data \
vaultbase
# Initialize inside container
docker exec vaultbase vaultbase init /vault company --db=/data/vaultbase.db
docker exec vaultbase vaultbase user create admin@co.com "Admin" "pass" --db=/data/vaultbase.db CLI Reference
vaultbase init <path> <name> Initialize a vault vaultbase serve --vault=<name> Start the server vaultbase login <email> <password> Get an API key vaultbase user create/list Manage users vaultbase role list/assign/revoke Manage roles vaultbase permission add/list Manage permissions vaultbase apikey create/list Manage API keys vaultbase vault list List vaults vaultbase vault files --vault=<name> List files vaultbase vault read --vault=<name> Read a file vaultbase vault search --vault=<name> Search content vaultbase vault query --vault=<name> Query by tag/path vaultbase pull-skills Generate skill files vaultbase clone --server=<url> Clone vault vaultbase sync --path=<path> Start sync daemon vaultbase status [path] Sync status