OpenKnowledge — agent guidance
OpenKnowledge (OK) is a markdown-CRDT collaboration platform exposed via MCP. This skill is the single source of OK agent guidance. Every rule below is a MUST unless marked otherwise.
Depth lives in — one level deep; load a reference when its task comes up.
Skill version tracks
@inkeep/open-knowledge-server
.
cat ~/.ok/skill-state.yml
shows what's installed.
needs
>= 0.4.0; if it errors
,
npm install -g @inkeep/open-knowledge
.
Setup (not connected yet?). If the
tools aren't available in your client, this project isn't wired up on this machine — see
for the rung ladder (approve
→
CLI → optional desktop app) and the canonical quickstart.
TL;DR — the 90% case
- Reads: for one doc, for a directory (folder defaults + template menu), for literal, for ranked retrieval. Native / only on source code ( / / …), never on in-scope / .
- Writes:
write({ document: { path, content } })
for a new or full-replace doc; edit({ document: { path, find, replace } })
for a body find/replace; edit({ document: { path, frontmatter } })
for a frontmatter merge-patch ( deletes a key). removes, moves/renames. Body find/replace is body-only. Pass a one-line (≤80 chars, user-facing outcome) on every content write.
- Preview / open a doc — determine your ONE surface FIRST (once per session). Stop at first match: or set → you're inside OpenKnowledge (desktop terminal / in-app agent panel) → (switches the window the user is already looking at); never paste a URL into your reply here · in-app browser (Claude Code Desktop's Browser pane, Cursor, Codex) → , then open/navigate it to the doc · else plain CLI → . opens a doc or folder (auto-detected); for a skill. The field is a route id, not your open mechanism. Don't to confirm edits. Full Step-0 procedure + per-surface how-to: .
- Knowledge layers: capturing a source (ingest), synthesizing findings (research), promoting a decision (consolidate) — procedures, not tool calls; there is no tool. Ingest ships here (
references/ingest-and-sources.md
); research + consolidate come with the pack. Layer model + packs: references/starter-packs.md
.
- Direct questions: a plain business question ("which customers…", "what did we decide about…") routes to / + a cited chat answer — no "research" keyword needed. Persist only when durable + multi-doc + not already covered, and offer first. See .
- Authoring or improving a skill ("write/make a skill", "improve this skill", "turn this into a skill"): STOP and invoke the
open-knowledge-write-skill
skill — it owns scope choice (project vs global), the SKILL.md contract, evaluation, and install; don't improvise here. Author through the target (), never a raw path document. Skills are REAL folders under the editor dirs' ( · · · · · ): ONE is the source, the rest are managed copies/symlinks. Read and edit via the tools (, ) — they route to the source. Never hand-edit a non-source copy: unedited copies refresh from the source, and editing one forks it into its own skill that stops refreshing.
Tool index — 21 tools (router; the MCP tool descriptions carry each tool's full contract)
- Reads — (primary; read-only ///… plus frontmatter/backlink/history enrichment; one command or one pipe, not a shell), (ranked BM25 + recency), (doc versions), (
kind: backlinks|forward|dead|orphans|hubs|suggest
, or an array for one call), (search + read: → skills.sh; omit to LIST managed (Project + Global); READs one — by +, never path), (resolved config), (authoring forms + starters + theme tokens; for JSX schemas), (browser preview URL on demand), (GitHub-substrate share URL; read-only, errors without a GitHub remote), (markdown-lint violations: for one doc, omit for the project; with auto-fixes fixable rules in place — attributed, live in the preview; the rest need /), (every lint violation + broken internal link in one read-only report, by source file with lines; scopes; for link VALIDATION use this, not ).
- Writes — four native CRUD verbs, polymorphic over / / / / (pass EXACTLY ONE target, nested under its address key): (create/overwrite; authors a skill as a REAL folder at the project's default skill home — live immediately for that folder's agent), (body find/replace/frontmatter merge-patch; no asset), (remove), (move/rename, rewrites referrers; a skill also takes / for Project↔Global — history resets, re-). Output mirrors the input key; the preview envelope (, ) stays top-level. Plus (WHERE a lives: / locations additively — editor ids, , or custom roots; + re-form ONLY the locations named; moves the real folder. The source folder IS the skill — no "uninstall everywhere"; a skill dies only via ), (acquire a skill-dir into 's locations; scripts never run), (named version), and (roll back). A folder's frontmatter is open-shape and self-only (does NOT cascade); templates are what new docs start with.
- Conflicts — (), (write a resolution + commit; destructive). See
references/conflict-resolution.md
.
Self-correcting on misuse: constraints JSON Schema can't express ("exactly one target", "
needs a
", body-XOR-frontmatter) return
with a one-line corrective shape. Read it and retry with that shape; don't guess.
Tools NOT in OK MCP (your host's):
,
,
,
, native
/
/
/
. The STOP rule governs which you may use on in-scope markdown.
STOP — native tools on in-scope /
Route every in-scope markdown read and write through OK's MCP tools — never your host's native file tools. Native
/
/ direct
on in-scope markdown bypasses the CRDT and loses agent attribution in the shadow repo; native reads skip frontmatter, backlinks, shadow-repo activity, and project git history that OK returns for every matched file. When this workspace has OpenKnowledge MCP configured, do
not use native file tools on markdown paths inside the content directory. The ban covers every common rationalization:
- Native / / on in-scope / — the original case.
- / / on dirs containing in-scope markdown — use /
exec("find … -name '*.md'")
/ . Native returns bare names; returns frontmatter, backlink counts, and recent activity. shows hidden entries (, ) without the / noise.
- Glob patterns that target markdown (, , , ) — use with or .
- Dispatching the Explore / general-purpose subagent for markdown-heavy exploration — subagents use native tools internally and bypass OK. Do markdown exploration yourself via / . Subagents remain appropriate for source-code exploration.
- Native / on in-scope markdown inside — is in-scope; treat its / like any other KB file.
- / / on skill folders to discover or read a skill — skills are addressed by +, not by path (a skill can live in any editor dir, the hub, or a custom root, with copies elsewhere). Use the tool.
Not seeing is NOT the escape hatch. Wiring, labels, and tool visibility vary by client; some (notably Codex) defer MCP tools behind lazy discovery. Registration is the test, not top-level-symbol visibility — run tool discovery for
first. Detail:
.
Escape hatch. Native
/
/
on
/
is allowed
only when, after running tool discovery (above), no OpenKnowledge MCP server is registered for this project,
or immediately after you actually invoked an MCP call and it failed — then begin a user-visible sentence with
OpenKnowledge MCP unavailable:
. "Not registered" is a conclusion you may only reach after tool discovery turned it up empty — never from the initial tool list alone. Never use the hatch because you skipped your client's MCP path, didn't see
as a top-level tool, didn't run tool discovery, or rationalized the skill wasn't necessary.
Source code and non-markdown files (
,
,
, …): native
/
/
always.
Reads — examples
- Read a file: — contents + full enrichment.
- List a directory: — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir, the folder's own // + . Prefer over plain .
- Literal search:
exec("grep -rn <term> <dir> | head -5")
— matches + enrichment on matched files.
- Ranked search: — title boost + body BM25 + recency; use when picking the best doc, not when listing every occurrence.
Writing
Call
/
as soon as you have content (route through MCP per the STOP rule).
Persist incrementally — the knowledge base IS your checkpoint (MUST). On any multi-step or long-running task — a research sweep, a multi-source synthesis, a batch of docs — write completed work to the KB as you finish each unit: per section, per source, per doc. Never hold finished findings only in your context waiting for one final write at the end. A rate limit, crash, or context compaction mid-task discards everything still unwritten; work already persisted survives, and you resume by reading the doc back. Create the target doc early (skeleton + frontmatter), then
each section in as it firms up.
Pass a on every content write (SHOULD) — a one-line (≤80 char) user-facing note; it becomes the timeline entry.
Reach for visual structure (Callout,
, table,
) where it carries the point better than prose; call
as you draft. Advisory write-warnings, MDX authoring, delete/move mechanics, and visual authoring:
+
references/components-and-visuals.md
+
references/media-and-assets.md
.
Grounding — every factual claim needs a source (MUST)
KB docs are factual artifacts: every claim traceable, and the source lives inside the knowledge base, not on the public web.
Ingest is a procedure, not a tool — binary-vs-text classification, SSRF-safe fetch flags, size + executable gates, wrapper frontmatter — in
references/ingest-and-sources.md
. Read it before your first capture; a naive fetch-and-paste skips every gate.
- Closed loop. External sources are pulled in by the ingest procedure, then cited locally. A bare inside a KB doc is not a citation — it is a TODO meaning "still needs ingesting". The chain only works if every leaf is a local doc.
- Every factual claim MUST cite its source at the point of claim. No unsourced speculation.
- Web sources → fetch the page (host / ), ingest it, then cite the path:
[source name](./path/to/source.md)
(the local doc carries ). Inline is a chat affordance, not a KB one.
- Self-fetched counts. A URL YOU fetched to ground a claim gets the same ingest — no inline-URL downgrade.
- Internal cross-refs → link the OK doc holding the authoritative claim; that doc cites its own sources (chains terminate in preserved local docs).
- No evidence? Search and ingest the result, OR mark , OR don't write the claim. Do NOT fabricate — unsourced speculation rots into untraceable tribal lore.
Linking — standard markdown links (MUST)
Link every noun-phrase that names another document —
[text](./relative/path.md)
— and link liberally.
Every link must resolve to a doc that exists by the time you're done (a same-pass forward-reference you create later in the pass is fine; for one that genuinely won't exist, leave the mention as plain prose + a tracked task). Never backtick a link (
is a bug) and never use HTML
.
Read on every / response: means all links resolve; a populated list names each broken + ( / / ) — fix them in a follow-up . is the authoritative end-state link check (the editor's red-underline is slug-tolerant and lies, so trust the tool). External web sources are NOT inline body links (see Grounding). Full rule set + the
legacy note:
.
Folders, frontmatter, templates
Every
/
needs YAML frontmatter —
+
required,
recommended. Two
opt-in, nested folder mechanisms: folder frontmatter (
<folder>/.ok/frontmatter.yml
— the folder's own open-shape properties; self-only, does NOT cascade into child docs) and templates (
— what new docs start with). Most folders have NO
. A doc's frontmatter is exactly its own on-disk YAML. Structural model + the full pre-write checklist:
references/folder-model.md
. Template authoring + folder editing:
references/template-authoring.md
. Frontmatter-vs-body edit rules:
references/doc-editing.md
.
- Read the folder before writing (MUST). Before creating/editing docs in a folder, call once per folder per session — it returns the folder's // + . Skipping it lands docs that violate folder discipline. (If a folder has no frontmatter AND no templates AND the repo has substantial content elsewhere, it isn't onboarded — run
references/onboard-existing-repo.md
first.)
- Use a template when one fits (MUST). Instantiate via
write({ document: { path, template } })
; inherited templates count. Skip only when none match or the user asked for free-form (note why in chat). Create templates proactively when a shape recurs.
- When recurring per-doc properties emerge (MUST). Writing the same frontmatter on multiple siblings → bake those starting values into a template (). Folder frontmatter does not cascade values into docs.
Conflict-aware writes
Projects with GitHub sync may carry docs in merge-conflict state; mutating calls against them return RFC 9457
urn:ok:error:doc-in-conflict
(409). Detect proactively —
returns
lifecycle: {status, reason} | null
; on
switch to the
+
flow. Full flow:
references/conflict-resolution.md
.
Anti-patterns — the top offenders
| Task | Don't | Do |
|---|
| List / find / read markdown | // | / / |
| Explore a markdown-heavy dir | (bypasses OK) | / yourself |
| Reference another doc | (backticked) or HTML | |
| Embed an image | , a / URL, hot-link | save locally + 
|
| Factual claim in a KB doc | prose with no citation, OR inline | ingest the source (references/ingest-and-sources.md
), cite the local path |
| Confirm an edit landed | / verification loop | trust the CRDT tool response |
| Delete a markdown doc | / native deletion | ( first if risky) |
| Write in an unfamiliar folder | straight to | first |
Full table:
references/anti-patterns.md
.
Knowledge layers — the shape most KB work takes
Three recurring practices, not tool calls — each a full procedure that ships as skill guidance.
| Layer | When | Procedure |
|---|
| ingest | Preserve a shared URL/PDF/file verbatim, or you fetched a URL to ground a claim (binary sources preserved, not scraped). | references/ingest-and-sources.md
— ships here, §Grounding depends on it |
| research | Investigate / compare / synthesize sources → article + . | skill |
| consolidate | A decision was made → canonical source-of-truth with a chain. | skill |
Research and consolidate arrive with
ok seed --pack knowledge-base
.
Without that pack you do not have those procedures — don't improvise one; do the work as an ordinary grounded
, or offer to seed it (
ok seed --pack knowledge-base --dry-run
shows what it would add).
Don't chain silently: let the user drive ingest → research → consolidate, and a procedure's STOP gates override session-level "don't stop to ask" hints. After any turn that changes KB content, check for a
and follow its contract (
references/cadence-and-logs.md
). Interleave a multi-doc batch so the preview shows narrative progress.
Onboarding a repo that already has content:
references/onboard-existing-repo.md
. Layer model + packs:
references/starter-packs.md
.
Server lifecycle
If
/
returns
"Hocuspocus server is not running"
, run
(via Bash) and retry. Never fall back to native
/
for in-scope markdown.
Scope recap
OK looks for documents under the resolved
(runtime:
config({ key: 'content.dir' })
);
and
(at root or any folder depth) define exclusions.
Every / under not excluded is an OpenKnowledge document — including under
,
,
. Folder metadata + templates live in nested
, not in
.
Working in a git worktree? Pass the worktree's absolute path as
on your OK tool calls once — it sticks for the session, so reads, writes, and the preview all target that worktree.