Skip to content

Repository files navigation

KVT

KVT is a git-backed knowledge vault service for OKF-style markdown bundles. It keeps the canonical knowledge in plain markdown files, maintains a derived SQLite search index, commits every write to git, and exposes the vault through REST and MCP.

What It Does

  • Stores concepts as bundle-relative .md files with YAML frontmatter.
  • Initializes and maintains a vault-local git repo.
  • Regenerates service-owned index.md files.
  • Validates documents against optional _ontology.yaml rules.
  • Indexes documents in SQLite with FTS5, links, frontmatter fields, and optional vector state.
  • Serves REST endpoints and MCP tools for search, read, write, edit, delete, validate, history, and push operations.
  • Uses optimistic concurrency through content hashes (base_hash) so stale writes are rejected with the current content.

Markdown files are the source of truth. .kvt/index.db and other runtime state are derived artifacts.

Requirements

  • Go 1.25+
  • Git
  • Optional: Docker and Docker Compose
  • Optional: external embedding/rerank services for vector search and LLM reranking

Quick Start

Build the CLI:

go build -o kvt ./cmd/kvt

Initialize a vault:

mkdir -p ./vault
./kvt init --vault ./vault --defaults

Start the service:

./kvt serve --vault ./vault --addr :8200

Write a concept:

curl -sS http://localhost:8200/concepts \
  -H 'content-type: application/json' \
  -d '{
    "path": "notes/hello.md",
    "content": "---\ntype: Note\ntitle: Hello\n---\nHello from KVT.\n",
    "validation_mode": "advisory"
  }'

Read it back:

curl -sS http://localhost:8200/concepts/notes/hello.md

Validate the vault:

./kvt validate --vault ./vault

Vault Layout

A typical vault looks like this:

vault/
  .git/
  .kvt/
    config.yaml
    index.db
  _ontology.yaml
  _howto.md
  index.md
  notes/
    hello.md
    index.md

Important files:

  • _ontology.yaml: optional type and frontmatter validation rules.
  • _howto.md: optional vault-specific house rules surfaced through kvt_howto, the MCP resource, and the MCP prompt.
  • index.md: service-owned directory listing. Do not hand-edit it.
  • .kvt/config.yaml: runtime config generated by init --defaults.
  • .kvt/index.db: derived SQLite index.

Concept paths must be bundle-relative, lowercase, forward-slash separated markdown paths such as people/alice.md. Paths may not use absolute paths, .., spaces, or unsafe segments.

Ontology

_ontology.yaml defines allowed concept types, required fields, optional fields, shallow field constraints, and path rules.

Example:

types:
  Person:
    required: [title, description]
    optional: [email, github]
  System:
    required: [title, description]
  Incident:
    required: [title, severity, status]
    fields:
      severity: {enum: [low, medium, high, critical]}
      status: {enum: [open, investigating, resolved]}
      affects: {ref: System}
rules:
  - path: people/**
    type: Person
  - path: systems/**
    type: System
unknown_types: warn

Writes default to strict validation. Use validation_mode: "advisory" when you want KVT to commit a document and return warnings instead of rejecting advisory issues.

CLI

kvt init --vault <path> --defaults
kvt serve --vault <path> [--config <path>] [--addr :8200]
kvt reindex --vault <path> [--config <path>]
kvt validate --vault <path> [--config <path>]
kvt push --vault <path> [--config <path>] [--remote origin] [--branch main]
kvt version

--vault can also be supplied by KVT_VAULT.

REST API

All responses are JSON. If auth.api_keys is configured, pass Authorization: Bearer <key>.

Method Path Purpose
GET /health Health, git status, summary, push status
GET /summary Counts, vector status, embedding backlog, push status
POST /search Hybrid search
POST /grep Exact indexed content lookup
GET /concepts List concepts by type, path prefix, or field filter
POST /concepts Create or replace a concept
GET /concepts/{path} Read a concept
PATCH /concepts/{path} Exact string edit
DELETE /concepts/{path} Delete a concept
GET /history/{path} Paginated file history and diffs
GET /log Paginated vault git log
GET /types Ontology schemas and per-type counts
POST /validate Whole-vault validation
POST /push One-shot git push

List, grep, log, and history responses include cursors and obey limits.max_response_chars.

GET /concepts/{path} supports 1-based inclusive line ranges:

curl -sS 'http://localhost:8200/concepts/notes/hello.md?start_line=1&end_line=10'

Malformed, negative, or reversed line ranges return 400.

Request-Scoped Access

REST and MCP calls can include an optional request-scoped access object to narrow which vault paths the operation may read or write:

{
  "access": {
    "read_globs": ["public/**"],
    "write_globs": ["drafts/**"],
    "deny_globs": ["secrets/**"]
  }
}

GET routes use repeated query params:

?read_glob=public/**&deny_glob=secrets/**

Missing access preserves normal unrestricted behavior. Present but empty access denies read/write access. deny_globs wins over allow globs. * and ? stay within one path segment; ** may cross path separators. This is request sandboxing, not authenticated server-side ACLs.

MCP

KVT registers fixed kvt_ tool names:

  • kvt_summary
  • kvt_howto
  • kvt_search
  • kvt_grep
  • kvt_list
  • kvt_read
  • kvt_types
  • kvt_log
  • kvt_history
  • kvt_write
  • kvt_edit
  • kvt_delete
  • kvt_validate

There is intentionally no MCP push tool.

By default, server.mcp_transport is stdio. Set it to streamable-http in .kvt/config.yaml to expose MCP at /mcp through the same HTTP server. Streamable HTTP MCP is protected by the same Bearer auth middleware as REST when auth.api_keys is configured.

Configuration

kvt init --defaults writes .kvt/config.yaml with search, git, server, and response-limit defaults:

search:
  fusion: rrf
  fts_weight: 0.5
  vec_weight: 0.5
  rerank: true
  rerank_top_k: 10
git:
  branch: main
  remote_name: origin
  push: "off"
  debounce_interval: 5m
  author_name: kvt
  author_email: kvt@local
server:
  http_port: 8200
  mcp_transport: stdio
limits:
  max_response_chars: 16000

Optional sections can be added when needed:

embedder:
  type: openai-compatible # or ollama
  base_url: http://localhost:11434
  model: nomic-embed-text
  dimensions: 768
  api_key_env: EMBEDDER_API_KEY

llm:
  base_url: http://localhost:8000/v1
  model: reranker-model
  api_key_env: LLM_API_KEY

search:
  fusion: rrf
  fts_weight: 0.5
  vec_weight: 0.5
  rerank: true
  rerank_top_k: 10

git:
  branch: main
  remote_name: origin
  push: off # off, on_change, or debounced
  debounce_interval: 5m
  author_name: kvt
  author_email: kvt@local

server:
  http_port: 8200
  mcp_transport: stdio # or streamable-http

auth:
  api_keys: ["local-secret"]

Vector search degrades to FTS-only when sqlite-vec or the configured embedder is unavailable. Health and summary responses report vector status and embedding backlog.

Docker

Initialize the mounted vault first:

mkdir -p vault
docker compose run --rm kvt init --vault /workspace --defaults

Then start the service:

docker compose up --build

The compose file mounts ./vault at /workspace and publishes port 8200.

Development

Run the main verification commands:

go test ./...
go vet ./...
go build ./cmd/kvt

Smoke-test init with the built binary:

tmp=$(mktemp -d)
./kvt init --vault "$tmp" --defaults
rm -f ./kvt

Current Scope

VISION.md describes the broader product direction. The current implementation is documented in docs/verification/full-scope-audit.md, including scoped deviations. Notable current limits:

  • kvt_summary is operational rather than a pretty tree view.
  • Tags and arbitrary frontmatter values are stored through kb_fields, not dedicated kb_docs.tags columns.
  • kvt reindex performs an in-place forced reconcile rather than a temp database atomic swap.
  • kvt_list supports type, path-prefix, and generic field filters; arbitrary order_by and type-aware sorting are not implemented.
  • kvt_grep is FTS-backed exact indexed lookup, not raw-file regex grep.
  • init --defaults is deterministic; there is no interactive questionnaire.

About

KVT is a git-backed knowledge vault service for OKF-style markdown bundles

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages