Vault Tools
vault_list
Section titled “vault_list”List projects or browse files within a project.
# List all projectsvault_list()
# Browse files in a projectvault_list(project="my-project")
# Browse a subdirectoryvault_list(project="my-project", path="30-architecture")
# Glob pattern filteringvault_list(project="my-project", pattern="adr-*")Without project, lists all vault projects with file counts and shortcuts. With project, lists files and directories (directories first, then files). With pattern, recursively finds all matching files.
Scope resolution
Section titled “Scope resolution”Projects are organized in scopes — top-level vault directories. By default, Hive ships with four scopes:
| Scope | Directory | Purpose |
|---|---|---|
projects |
10_projects/ |
Personal projects |
work |
50_work/ |
Work: products, clients, tickets, development |
agents |
80_agents/ |
AI-agent inboxes — each subdirectory is a first-class project |
meta |
00_meta/ |
Cross-project patterns and templates |
Use scope:slug syntax to target a specific scope: vault_list(project="work:hydra3d-plus").
Hierarchical scopes: The work scope (and any scope) supports nested directories. If a slug isn’t found as a direct child of the scope directory, Hive searches recursively using breadth-first search. For example, work:hydra3d-plus resolves to 50_work/20-products/hydra3d-plus/ automatically.
Use explicit paths with / to skip BFS: work:20-products/hydra3d-plus.
Without a scope prefix, Hive auto-scans all scopes in order — first match wins.
vault_query
Section titled “vault_query”Read sections or files on demand.
vault_query( project="my-project", section="context", # context | tasks | roadmap | lessons path="", # arbitrary path (overrides section) max_lines=200, # 0 = unlimited include_metadata=False # prepend frontmatter summary)Section shortcuts map to files:
context→00-context.mdtasks→11-tasks.mdroadmap→10-roadmap.mdlessons→90-lessons.md
Use path for arbitrary files: vault_query(project="my-project", path="30-architecture/adr-001.md")
Use project="_meta" to access 00_meta/ (cross-project patterns).
vault_search
Section titled “vault_search”Full-text search across the vault with optional ranking and recent-changes mode.
# Standard keyword searchvault_search( query="authentication", max_lines=100, type_filter="", # filter by frontmatter type status_filter="", # filter by frontmatter status tag_filter="", # filter by frontmatter tag use_regex=False # treat query as a regular expression)
# Ranked search (relevance scoring)vault_search(query="deployment", ranked=True, max_results=5)
# Recent changes (last N days)vault_search(since_days=7, project="my-project")
# Restrict search to a scopevault_search(query="LVDS", scope="work")
# Lesson reinforcement ranking (HIVE-97)vault_search(query="timeout", rank_by="reinforcements") # most-read firstvault_search(query="timeout", rank_by="confidence") # highest decayed confidencevault_search(query="timeout", rank_by="hybrid") # α=0.7 BM25 + 0.3 confidenceStandard mode: Returns matching lines grouped by file, with metadata headers. When use_regex=True, the query is compiled as a Python regular expression (case-insensitive).
Ranked mode (ranked=True): Scores results by status weight (active > draft > archived), recency, and match density. Returns top results with metadata and matching lines.
Recent mode (since_days > 0): Combines git history with frontmatter created dates to find files changed in the last N days. Optional project filter.
Scope filter (scope): Restricts the search to a single scope (e.g. "work", "projects"). Works in all three modes. Without scope, searches the entire vault.
Lesson-rank mode (rank_by != "bm25"): Filters matches to 90-lessons.md only and ranks by the chosen usage signal — every surfaced lesson is incremented once per call. hybrid blends BM25 (α=0.7) with confidence (1−α=0.3). Unknown rank_by values return a clear error rather than silently falling back to BM25.
vault_ask
Section titled “vault_ask”Ask a natural-language question and get an answer grounded in your vault, with source citations. Optional — disabled until a semantic backend is configured. For keyword or regex lookups, use vault_search instead.
vault_ask(question="Why did we choose PostgreSQL over MySQL?")question is the only parameter. Use question, not query or prompt.
Enabling it: install the [semantic] extra (pip install 'hive-vault[semantic]') and set HIVE_EMBED_BASE_URL and HIVE_EMBED_MODEL (plus HIVE_EMBED_API_KEY if the endpoint needs one) to an OpenAI-compatible embeddings endpoint. A hosted service and a local runtime are configured the same way; Hive names no provider. See Configuration → Setting Up Semantic Q&A.
Behaviour by state:
- No
HIVE_EMBED_BASE_URL: returns a short how-to-enable message and never errors. Base installs are unaffected and pay no cost — no index is built and nothing is embedded on write. - Endpoint set but the
[semantic]extra is missing: returns the install instruction. - Enabled,
HIVE_SYNTH_MODELempty: embeds the question, searches the index, and returns the top 5 most relevant vault sections with their source file, heading and similarity score. No LLM call is made. - Enabled,
HIVE_SYNTH_MODELset: sends those sections to the chat model (same endpoint and key as the embeddings) and returns a synthesized answer that cites[source: path/to/file.md]for each claim. The model is instructed to answer only from the retrieved sections and to say so when the answer is not there. If the synthesis call fails for any reason,vault_askfalls back to the retrieved sections instead of erroring.
# vault_ask: 'Why did we choose PostgreSQL over MySQL?'
### 1. 30-architecture/adr-005.md — 'Context' (score: 0.82)> We evaluated PostgreSQL and MySQL for the primary store...The index: built lazily on the first call, persisted in an index/ directory next to HIVE_DB_PATH, and updated incrementally when vault_write or vault_patch changes a file. Changing HIVE_EMBED_MODEL triggers a rebuild. An empty question returns vault_ask: provide a non-empty question.
session_briefing
Section titled “session_briefing”Load a project’s working context in one call — the tool to run at the start of a session.
# List the available projectssession_briefing()
# Load one projectsession_briefing(project="my-project")project is the only parameter; there is no days argument — the briefing window is fixed.
Without project, returns the list of available projects with a hint to pass project=<slug>. With project, assembles one response (replacing three or four manual calls):
## Active Tasks— the project’s tasks file, truncated to 50 lines## Recent Lessons— the last 30 lines of its lessons file## Recent Vault Activity— the last 5 git commits in the vault## Project Health— file count and, when any, the number of stale files (older thanHIVE_STALE_THRESHOLD_DAYS)
Adaptive ordering: Active Tasks and Recent Lessons are ordered by how often you have read each section in earlier briefings, tuned by HIVE_RELEVANCE_ALPHA, HIVE_RELEVANCE_DECAY and HIVE_RELEVANCE_EPSILON; with no history, tasks come first. Activity and health always come last. If relevance tracking times out, the briefing still returns with a note that it is showing the default section order.
An unknown project returns a not-found message rather than an empty briefing.
vault_health
Section titled “vault_health”Server identity, health metrics, drift detection, and usage statistics.
# Health report for all projects (always includes the ## server identity block)vault_health()
# Validate a specific projectvault_health(project="my-project", checks=["frontmatter", "stale", "links"], max_issues=50)
# Include usage statisticsvault_health(include_usage=True, usage_days=30)
# Include runtime metadata (uptime, registered tools, worker usage)vault_health(include_runtime=True)Identity block (always-on, ~5 lines): Prepended to every successful response so MCP hosts and operators can answer “which hive-vault version is serving this session?” without leaving the conversation.
## server- version: 1.15.0- python: 3.12.10- vault_path: /home/me/Projects/knowledge- backends: {"worker": true, "worker_reachable": "unprobed"}- started_at: 2026-05-21T20:33:20+00:00Backends are reported as presence booleans only — API keys are never embedded. worker is true when a worker endpoint is configured (a base URL is set). That says nothing about whether it answers: worker_reachable is always "unprobed" here, so call worker_status to probe it.
Health report (default): Per-project file count, total lines, stale files (>180 days, configurable via HIVE_STALE_THRESHOLD_DAYS), section coverage. Also detects duplicate directory names within hierarchical scopes and warns which path BFS will resolve to.
Validation (checks parameter): Drift detector for common issues:
- frontmatter: Missing or malformed YAML frontmatter, missing required fields (id, type, status), unparseable dates
- stale: Active files not modified in
HIVE_STALE_THRESHOLD_DAYS(default 180) - links: Broken
[[wikilinks]]pointing to nonexistent files
Issues are categorized as [error] or [warning] with file path and description.
Usage stats (include_usage=True): Tool call counts by tool and project, with estimated token savings.
Runtime block (include_runtime=True, opt-in): Dynamic diagnostics layered after the report — uptime in seconds, count + names of MCP tools currently registered (sanity check that no module failed to register), and the worker usage snapshot (request_count, total_tokens, period). Independent of include_usage; both can stack in one call.
git_repo reports whether the vault is a git repository at all. It is what makes the two blocks below it readable: without a repository uncommitted is permanently null and a commit_queue depth that never falls is the expected state rather than a stalled reconciler. The server also warns about this at startup.
Two blocks there report on deferred commits. commit_queue gives depth, last_flush_age_s and tick_s — the depth is only interpretable against the tick that is supposed to be clearing it, so a stalled reconciler shows up as a depth that outlives several ticks. uncommitted gives count and oldest_age_s for vault paths still awaiting a commit; null there means git could not answer, which is a different answer from 0. The two overlap mid-tick, and that is truthful — a queued path really is uncommitted on disk.
Deferred commits (ACK semantics)
Section titled “Deferred commits (ACK semantics)”Breaking change — ships in a major release. A successful vault_write or vault_patch no longer means a commit exists.
The commit moved off the write path. A write lands on disk, its path is queued, and a reconciler thread drains the queue into one commit per tick (HIVE_COMMIT_TICK_S, default 5s) rather than one commit per write. Commit rate is now a function of the tick instead of write volume, which is what lifts the throughput ceiling: git commits against one repository serialize, so the only way to go faster is to commit less often.
| You want | Pass |
|---|---|
| The previous synchronous behaviour | commit=True — commits before returning |
| The default | nothing — queued, committed on the next tick |
| To flush early | vault_commit |
What the default guarantees is narrow, deliberately: the write reached disk before its path was queued. Everything after that is best-effort. A tick may legitimately produce no commit at all (see obsidian-git integration), and a process killed before its tick leaves the path on disk uncommitted.
commit=False no longer means “stay uncommitted until I flush” — it is now an alias for the default. The indefinite-deferral mode is removed, not preserved. What it existed for — batch many writes, pay for one commit — is what the queue now does automatically and without configuration.
Nothing recovers a missed commit automatically. An orphaned path waits for the next write to that vault, an explicit vault_commit, or an external committer. It stays visible the whole time under uncommitted in vault_health(include_runtime=True) — count plus the age of the oldest. That report is the recovery signal rather than a nicety, so note that count: null means git could not answer, which is not the same answer as count: 0.
vault_write
Section titled “vault_write”Create, append, or replace vault files with frontmatter validation. The commit is deferred to the next tick; pass commit=True to commit synchronously before returning.
# Append to an existing filevault_write( project="my-project", section="lessons", content="New lesson learned...", operation="append" # default)
# Replace an entire file (requires valid frontmatter)vault_write( project="my-project", section="context", content="---\nid: my-project\ntype: project\nstatus: active\n---\n\nNew content.", operation="replace")
# Create a new file with auto-generated frontmattervault_write( project="my-project", path="30-architecture/adr-005.md", content="# ADR-005: PostgreSQL\n\n## Context\n...", operation="create", doc_type="adr" # used in generated frontmatter)- append: Adds content to the end of an existing file
- replace: Replaces the entire file. Requires valid YAML frontmatter with
id,type,status - create: Creates a new file. Auto-generates frontmatter with
id,type,status: draft,created: today
All three operations defer their commit to the next reconciler tick. The file is on disk when the call returns; git status shows it dirty until the tick fires. Pass commit=True to commit before returning, flush early with vault_commit, or let an external committer (e.g. obsidian-git auto-commit) take it — see Deferred commits for the full contract and Configuration → Recommended configuration for durability.
vault_patch
Section titled “vault_patch”Surgical find-and-replace in a vault file.
# Single replacementvault_patch( project="my-project", path="30-architecture/adr-001.md", find="status: draft", replace="status: accepted")
# Multiple replacements (applied in sequence)vault_patch( project="my-project", path="11-tasks.md", patches=[ {"find": "- [ ] Task one", "replace": "- [x] Task one"}, {"find": "- [ ] Task two", "replace": "- [x] Task two"}, ])Replaces exactly one occurrence of find with replace. Rejects ambiguous matches — if find appears more than once, the operation fails with an error asking for more context. Uses 3-pass cascading match: exact → body-only → whitespace-normalized. The commit is deferred to the next tick, same contract as vault_write; pass commit=True to commit synchronously.
vault_commit
Section titled “vault_commit”Flush the working tree into one git commit, without waiting for a tick.
vault_commit(message="vault: end-of-session checkpoint")Stages everything dirty in the vault (git add -A) and creates a single commit. Returns the new SHA, a clean-tree notice if nothing is dirty, or a human-readable error. Best paired with the obsidian-git plugin (see Configuration → Recommended configuration).
This is the only path that sweeps the whole working tree, and that is deliberate: it stages edits hive never made, including your own work in progress. A human asking for a flush has consented to that; a timer has not, which is why the reconciler only ever commits paths it queued itself. It is also the remediation for anything the report under vault_health shows as uncommitted, since nothing clears those automatically.
vault_delete
Section titled “vault_delete”Delete a single file from the vault. Destructive — only on explicit user request. Recoverable from git history.
vault_delete( project="my-project", path="30-architecture/adr-005.md", commit=True, # default: stage + commit the deletion idempotency_key="" # optional at-most-once token)Removes one file and commits the deletion, so it stays recoverable via git revert / git show. Files only — directories are rejected. A non-existent path is an error, unless idempotency_key is set, in which case a retry against an already-removed file is a no-op success.
vault_delete is the one write tool that did not move to deferred commits. It opts out of the queue entirely and always commits synchronously, because coarser commit granularity is exactly what would weaken its recoverability guarantee: a delete and a recreate inside one tick collapse into a single state, leaving nothing to git revert back to.
capture_lesson
Section titled “capture_lesson”Capture lessons inline, batch-extract from text, or look up existing lessons by keyword.
# Inline capture (structured, single lesson)capture_lesson( project="my-project", title="Root cause was stale cache", context="Debugging deploy failure", problem="Service returned 500 after deploy", solution="Clear Redis cache after config changes", tags=["deploy", "cache"] # optional)
# Batch extraction (worker-powered, multiple lessons)capture_lesson( project="my-project", text="We found that the cache was stale after deploy...", min_confidence=0.7, max_lessons=5)
# Lookup mode — surface existing lessons by keyword (HIVE-97)capture_lesson( project="my-project", find="cache", rank_by="reinforcements", # or "confidence", "hybrid" max_lessons=5)Inline mode (no text, no find): Appends a structured entry to 90-lessons.md with date, context, problem, and solution. Never creates the file: if the project has no 90-lessons.md it writes nothing and returns an error naming where the lesson belongs instead — the repository’s docs/lessons/ for a project that moved its lessons there, 00_meta/patterns/ for a cross-project lesson. Deduplicates by title. Auto-commits to git. Each inline write also seeds a baseline row in the reinforcement table at confidence=0.7.
Batch mode (text provided): Sends the text to the configured worker model, which extracts structured lessons (title, context, problem, solution, tags, confidence). Lessons above the confidence threshold are written to 90-lessons.md with deduplication and seeded in the reinforcement table. The missing-file check runs before the worker call, so a refused capture costs no inference.
Lookup mode (find provided): Greps lesson headings (codeblock-aware) for the keyword, ranks the matches by rank_by (default reinforcements), increments each surfaced lesson once, and returns the top max_lessons. Single-tool symmetry: capture_lesson writes lessons AND queries them.
When to use: Immediately after discovering a bug root cause, architectural insight, or debugging trick — don’t wait until session end. Use find= to recover past lessons by topic.