| name | knowledge-base |
| description | Search, navigate, and read a markdown knowledge base — a directory of notes, docs, or a wiki — via an auto-built knowledge-graph index over documents, their sections, and the wikilinks between them, retrieving the right slice instead of grepping and reading whole files. Use when working in a folder of markdown — setting up or maintaining a knowledge base, finding or retrieving content, summarizing it, or answering questions grounded in the notes. |
ki — Usage
Trigger When
Reach for ki whenever the work involves a directory of markdown (notes, docs, a wiki, a "second brain") — it's your default read/search tool there:
- Set up / maintain a knowledge base on a folder (index it, keep it in sync).
- Search / find across the corpus — "what did I write about X?", "find the note on Y."
- Navigate / summarize — "what's in this vault?", its structure or coverage.
- Get / read specific sections or documents without opening whole files.
- Answer questions grounded in the user's notes/docs.
- Vault-wide / structural / inference questions — what's load-bearing, how things connect.
Rule of thumb: any time you'd otherwise grep / cat / read across a folder of .md, use ki instead.
Do Not Use When
- The source isn't markdown and isn't being converted —
ki indexes .md only (see the note under On First Use).
- Source code or non-prose — use
grep / ripgrep / editor tooling; ki models prose structure (headings, links), not code.
- A single known file or quick one-off read where indexing isn't worth it — just
Read it.
What ki is
A command-line tool that builds a queryable knowledge graph index over a directory of markdown. It parses each .md into its documents, sections, and the wikilinks between them, stores that structure in Neo4j, and exposes fast search, navigation, and retrieval over it — so you can find and read the right slice of content without opening and scanning whole files.
Why use ki
It's faster and far cheaper in tokens than raw file ops over a markdown corpus. Instead of grepping and reading entire files into context, you query an index and pull just the sections you need — structure (headings, containment, links) is preserved, so retrieval is targeted. See Usage for the specific jobs it beats file ops at.
Key Terms
- Knowledge base — a directory of markdown you want to search and navigate as a connected whole. Becomes a vault once
ki indexes it.
- Vault — a directory
ki has marked (.ki/vault.yaml) and indexed. The unit of indexing and sync; identified by a slug uri, and bound to one profile.
- Profile — a named Neo4j database (connection + credentials in
config.yaml) that holds the graphs for one or more vaults. A privacy/isolation boundary (e.g. personal vs work).
- Index — the knowledge graph in Neo4j (documents, sections, links) built from a vault's markdown. Rebuilt with
ki index.
- URI — the address of a vault / document / section in the index. Copy it from
ki outline or search results and feed it into ki get / ki outline. URIs are hierarchical paths, so trim a trailing segment to get an ancestor — no query needed (drop /h2 → parent section, the whole #… → owning doc, /foo.md → folder).
config.yaml — ~/.config/ki/config.yaml; holds profiles + credentials. Does not track vaults — Neo4j does.
On First Use In Session
The user is generally thinking about one directory: set up a knowledge base on it, or use the one that's there. Both intents funnel through the same job — get that directory to a READY vault, then use it. The only branch that matters is how far along the directory already is.
A vault is a directory marked with .ki/vault.yaml, which records the vault's uri and the profile (Neo4j database) it's bound to:
uri: my-notes
profile: personal
description: "..."
Only the profile name is stored (credentials stay in config.yaml), so this file is safe to commit. This binding is how the vault knows its own profile without ever prompting the user.
ki indexes .md files only. Convert non-markdown sources (PDF / docx / HTML) to markdown first — pandoc, markitdown, or read + transcribe — into a folder the user picks (ask once, reuse it), then ki index.
Step 0 — ki installed?
ki --help
Step 1 — Point at the directory
- Default: the current directory.
- User names a path →
cd there.
Step 2 — Get the directory to READY
Run ki status. It resolves in layers and reports the first blocking state — each layer needs the one above it to pass:
- Disk marker (no Neo4j needed) — is there a
.ki/ here?
- Neo4j reachability —
ki status -v attempts a connection to the bound profile and classifies the result (you don't know this until you try).
- Graph state — only knowable once Neo4j is reachable.
Act on the reported state, then re-run until READY:
| State | How ki status knows | Action |
|---|
NOT_A_VAULT | no .ki/ on disk | Setting up. List profiles (ki profile list — from config.yaml, no Neo4j needed); user picks one to bind — never default (personal/work boundary). None yet → references/configure-profile.md. Then ki index . --profile <p> --description "..." |
NEO4J_DOWN | connect → ServiceUnavailable (nothing listening) | start it → references/neo4j-troubleshoot.md |
NEO4J_UNRESPONSIVE | connect hangs / times out | container up but not ready, or wedged → wait, then references/neo4j-troubleshoot.md |
AUTH_ERROR | connect → authentication failure | profile credentials wrong → references/configure-profile.md (re-enter creds) — not a restart |
NOT_INDEXED | reachable, but no :Vault node | ki index . (profile already bound) |
STALE | indexed, but the set or content-hash of .md files no longer matches the graph | ki status -v shows which files drifted; ki index . to resync (see Re-Indexing) |
READY | indexed + in sync | done — start using it (Usage) |
Layers 1–2 work even when Neo4j is down (that's how ki status reports the Neo4j rows at all). The graph rows below require a reachable Neo4j.
Edges:
- Bound profile missing from
config.yaml (renamed / cloned to another machine) → surface to user; add it with ki configure or re-bind by re-indexing (ki index . --profile <p>).
- Source dir moved →
cd to the new path and ki index ..
Starting a knowledge base from scratch? If the directory is empty/sparse — the user wants to build a KB, not point at an existing one — or they have no strong layout opinions, see references/structuring-a-knowledge-base.md for a light, link-friendly layout to propose before indexing (inbox + read-only raw/ sources + interconnected LLM-authored pages + outputs/). General guidance — adapt to the user; their conventions win.
Usage
This skill covers when and why to reach for each command; ki <cmd> --help is the source of truth for exact flags. Check it when a flag is unclear rather than guessing — it's read-only and safe to allowlist.
Orient first. Opening a READY vault, map its structure with ki outline <vault uri> before searching — it gives you the shape and the URIs to drill into. Depth defaults to 4; on a large or wide vault that's a lot of context, so start shallow (--depth 1–2) and recurse into the branches you care about (ki outline <folder/doc uri>) rather than rendering the whole tree at once.
In a vault, read files through ki (search/outline/get), not Read/grep/cat — and tell any sub-agents you spawn to do the same (pass them the vault uri).
Search & Retrieve Specific Content
Users rarely ask "find files containing X" — they ask domain questions:
- "How does our auth flow handle token refresh?" (software KB)
- "What did I conclude about GraphRAG indexing cost?" (research KB)
- "Which notes mention the Postgres migration, and what's the rollback plan?"
Two complementary strategies — do both (fan out parallel sub-agents, or run sequentially) and keep the best hits:
-
Structured navigation — start at the table of contents, then drill into promising branches:
ki outline <vault uri> --full --depth 3
ki outline "<folder|doc|section uri>" --depth 2
Best when the question maps to a known area of the vault.
-
Full-text search with semantic expansion — cast a wide net (fulltext over title + content + wikilink aliases + description):
ki search "token refresh" --k 10
ki search works on the vault you're in by default and prints the profile + vault it used. See ki search --help if you need more options.
Queries are Lucene syntax — AND/OR/NOT (or +/-), "exact phrases", () grouping, * wildcards, ~ fuzzy. (query syntax)
Semantic expansion — the index only does lexical matching, so synonyms or semantically relevant content may be missed (e.g. search on "Darth Vader" misses "Anakin Skywalker"). Account for this by rewriting the term to a few alternates you know and running them as extra ki search calls or one OR-form query — either reactively (results look thin: few hits, low-score hits, or no hits) or pre-emptively when you already expect a mismatch:
ki search 'Anakin OR "Darth Vader" OR Vader'
By default ki search searches over both documents and sections. Generally recommended, since documents content in ki is just header/intro while other body goes to sections. But can still narrow node types with --types document|section.
Pull the actual content by URI:
ki get --type full "<uri>" ["<uri>" ...]
Use --type full for whole sections / documents, --type content to get a node's preamble + child pointers and drill further, --type path for metadata only (then read the file yourself). ki get takes only document/section URIs — for a folder use ki outline.
Markdown links to non-md files or external URLs become stub document nodes (metadata only, no content) — they surface in search/outline as link targets because an .md file points at them. Only .md files are actually indexed; ki get on a stub returns just its metadata.
Answer Vault-Wide Questions
Sometimes the question is about the vault as a whole, not a specific slice:
- "What's in this knowledge base? What topics does it cover?"
- "What's load-bearing here — what should I read first to understand it?"
- "If I refactor this, what else will it affect?"
Two strategies:
-
Outline as overview — read ki outline --full as a high-level map of the whole vault to summarize its coverage and structure (adjust --depth and recurse on uris as needed). Follow with ki search/get for any specifics. Best for "what's in here."
-
Reason over the graph (via neo4j-cli) — for counts, aggregates, paths, and structural questions search can't express, query the Neo4j graph directly with neo4j-cli. Reason over the graph; don't translate the question into a query — read the schema, think in nodes / relationships / paths / neighborhoods / centrality, then express that reasoning as Cypher. (neo4j-cli and its installed skills already drive this schema-first, graph-shaped flow — lean on them rather than re-deriving it.)
Connect by credential name, never a password — ki configure / ki profile sync registered each profile as a neo4j-cli credential, so pass --credential <profile> and the secret stays in neo4j-cli's store:
neo4j-cli query :schema --credential <profile> --format toon
neo4j-cli query "<cypher>" --credential <profile> --format json
<profile> is the vault's bound profile — read it from ki profile list or the .ki/vault.yaml profile: field (both non-secret). If --credential reports the name is unknown, run ki profile sync.
- To scope queries to the vault uri (or any folder, document, section therein) know that ki URIs are hierarchical, so filtering
uri with STARTS WITH '<uri>/' filters to the subtree — everything under that vault / folder / document / section. Keep the trailing /: STARTS WITH 'my-notes' would also match the sibling vault my-notes-2.
Making Inferences
Sometimes the user wants analysis, not just retrieval:
- "What are the main themes running through these notes?"
- "How does [X] connect to [Y] — what's the throughline between them?"
- "Pull together everything related to [X] and synthesize where it lands."
- "Where do these notes reinforce or contradict each other on [topic]?"
- "What's underdeveloped — what's referenced a lot but never fleshed out?"
Gather context with ki outline / ki search / ki get, but lean on neo4j-cli (--credential <profile>, schema first — see above) — these questions are about the relationships and aggregates the graph encodes (link paths, co-occurrence, centrality, clusters) that flat search can't surface: shortest path between two docs, most-linked sections, a node's link neighborhood. Scope to a vault or any other subtree with the hierarchical uri STARTS WITH filter noted above.
Adding, Updating & Removing Content (incremental)
When you or the user creates, edits, or deletes a document or folder, sync just that target — fast and incremental, no full rebuild. These are index-only: they never touch the user's files.
ki add <doc|folder path>
ki rm <doc|folder uri/path>
ki add is an upsert — run it on a new file to add it, on an edited file to refresh it. It takes a path, not a uri.
ki rm removes a document or folder (a folder takes its contents with it). It does not remove a whole vault — that's ki drop (see Other Operations) — and it does not remove a bare section (edit the document and ki add it instead). Like git rm --cached, it drops the index entry, not the file on disk.
Renaming or moving: After a file or folder is moved on disk, run ki rm <old> then ki add <new>. Other documents that linked to the old name now have a stale [[old]] link; ki will not rewrite them (it never invents links) — do link sweeps to fix those references in the source, then ki add (or re-index).
Use ki status -v to check what documents & folders need add/rm updates.
Re-Indexing Entire Vaults
Re-indexing entire vaults can become an expensive operations with more documents, but is sometimes necessary as updating/adding/removing individual content pieces may miss other changes made by the user (or accidentally by you).
After significant changes or refactors to knowledge base content
Run ki status (add -v to see exactly which files drifted); if it reports STALE with many drifts, run ki index . — preferably in a sub-agent.
STALE/READY is markdown-only — not bulletproof. It does not notice changes to linked non-markdown attachments (PDFs, decks, images captured as stub nodes), and a vault indexed with a non-default --max-file-size can skew the diff. So READY guarantees the markdown is in sync, not necessarily every attachment. When in doubt — or after bulk/attachment changes — a full ki index . is the source of truth.
During indexing, the entire vault is removed from Neo4j then rebuilt to reflect what's on the file system currently. The process can last a couple seconds (for dozens of documents) or a few minutes (for thousands of docs). During re-indexing the vault should not be used for search or answering questions.
Other Operations
ki configure / ki profile list — manage Neo4j connection profiles.
ki vault list — inspect indexed vaults (uri, description).
ki init <path> — (advanced) write .ki/vault.yaml without indexing.
ki drop <vault> — remove a whole vault from the index; typed confirmation. Source files untouched.
ki nuke — reset the entire graph (all vaults); typed confirmation, last resort.
ki skill … — install this skill bundle into other agents.
Anti-Patterns
- Raw file ops on vault content — reading/searching a vault with
Read / grep / cat instead of ki, and spawning sub-agents that default to file reads. Burns the tokens ki exists to save.
- Auto-binding a profile — binding a fresh vault to whatever profile happens to be around (e.g. a stray
$KI_PROFILE) without confirming. ki has no default profile — you must ki index a new vault with an explicit --profile. Profiles are privacy boundaries; confirm the profile once, at first index.
- Full re-index for a small change — running
ki index . (full nuke + rebuild) after editing one file. Use per-target ki add / ki rm; reserve ki index . for bulk edits or refactors.
- Cold-starting Neo4j just to look around — spinning up a stopped profile's instance only to enumerate vaults.
- Switching vault or profile mid-task without confirming — work one vault + one profile per session; confirm any switch with the user.
- Querying a vault while it's re-indexing, or fabricating URIs — copy URIs from
ki outline / ki search; never guess them.