open-knowledge — Claude Code skill: working in a markdown CRDT base
Tells the agent how to work inside an OpenKnowledge project: reading, searching, editing and linting markdown through MCP tools.
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a claude-codeWhat open-knowledge does
OpenKnowledge is a markdown knowledge base with CRDT sync, exposed over MCP. The open-knowledge skill spells out the contract an agent follows there: which tools to call, how to link documents, and how folders and templates are laid out. It ships with ok init, so finding it in a project means that project is already wired to OpenKnowledge.
The core rule is blunt. In-scope markdown goes through OK's MCP tools, never the host's native file tools. Read with exec and cat, ls or grep; retrieve with search; create with write; change in place with edit. Native Read and Grep stay for source code only. Each tool carries its own input schema, and a malformed call comes back as isError: true with a one-line corrective shape — read it and retry rather than guessing.
Before previewing anything, work out your surface once per session. With OK_DESKTOP_TERMINAL or OK_HOSTED_AGENT set, open a doc with ok open <name>, which switches the window the user already has. Otherwise the same command works from a plain CLI, and an in-app browser pane takes preview_url instead. Note that previewUrl is a route id, not your open mechanism — mixing the two up sends you down the wrong path. Some steps shell out to the ok CLI, so the skill won't run end to end without it.
What it helps with
- read and edit markdown documents through MCP instead of native file tools
- pull up the right document with ranked search across the workspace
- create a doc from a template and place it in the right folder
- check content rules and internal links before publishing
- open a document in the browser without pasting a localhost URL
Example prompts for the agent
- read
docs/overview.mdand summarize what it says - search the workspace for everything on customer onboarding and answer with citations
- add an install section to
guides/setup.mdand lint it
How to install open-knowledge
1Skills CLI (Vercel)
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a claude-code2Manually: put the files in place
~/.claude/skills/open-knowledge/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/open-knowledge/
1Skills CLI (Vercel)
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a codex2Manually: put the files in place
.agents/skills/open-knowledge/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a cursor2Manually: put the files in place
.cursor/skills/open-knowledge/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install inkeep/open-knowledge-skills open-knowledge2Manually: put the files in place
.github/skills/open-knowledge/SKILL.md1Skills CLI (Vercel)
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a gemini-cli2Platform CLI
gemini skills install https://github.com/inkeep/open-knowledge-skills --path skills/core/open-knowledgeManually: put the files in place
.devin/skills/open-knowledge/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about open-knowledge
How do I install open-knowledge in Claude?
Run npx skills add inkeep/open-knowledge-skills --skill open-knowledge -a claude-code. The skill lands at ~/.claude/skills/open-knowledge/SKILL.md.
What does open-knowledge do?
It tells the agent how to operate inside an OpenKnowledge project: which MCP tools handle reading, searching, editing and linting markdown, how documents link to each other, and how the browser preview works.
What do I need for the skill to work?
An agent host with the OpenKnowledge MCP server configured — ok init wires the agents it detects on your machine. Some steps shell out to the ok CLI, and hosts that take an uploaded skill bundle rather than reading a project directory are covered by ok cowork.
Source text
SKILL.md · MIT
---
name: open-knowledge
description: "Authoritative agent-runtime contract for working inside an OpenKnowledge project — a markdown-CRDT knowledge base exposed over MCP. Use whenever reading, listing, searching, editing, or linting any `.md` or `.mdx` file in the project, and before any `mcp__open-knowledge*` tool call (`exec`, `search`, `write`, `edit`, `lint`, and the rest). Installed by `ok init`, so its presence means this is an OpenKnowledge project and it governs every markdown file here. Covers the read/write tool surface, grounding and linking rules, folder/template conventions, the live browser preview, and the rule that OK's MCP tools — never native file tools — handle in-scope markdown."
compatibility: "Any agent host with the OpenKnowledge MCP server configured; `ok init` wires the agents it detects on your machine. Some steps shell out to the `ok` CLI. Hosts that take an uploaded skill bundle instead of reading a project directory (Claude Desktop, Cowork, claude.ai) are covered by `ok cowork`."
metadata:
author: "Inkeep"
repository: "https://github.com/inkeep/open-knowledge-skills"
---
# 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 `references/*.md` — 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. `ok seed` needs `@inkeep/open-knowledge` >= 0.4.0; if it errors `unknown command`, `npm install -g @inkeep/open-knowledge`.
> **CLI name.** Commands here use Stable's `ok` (`open-knowledge`) and `~/.ok/`. With OpenKnowledge Beta, use `ok-beta` (`open-knowledge-beta`) and `~/.ok-beta/` instead; `preview_url`'s `okOpenCommand` already names the right one.
> **Setup (not connected yet?).** If the `mcp__open-knowledge*` tools aren't available in your client, this project isn't wired up on this machine — see [`references/setup.md`](references/setup.md) for the rung ladder (approve `.mcp.json` → `ok start` CLI → optional desktop app) and the canonical quickstart.
## TL;DR — the 90% case
1. **Reads:** `exec("cat …")` for one doc, `exec("ls -A …")` for a directory (folder defaults + template menu), `exec("grep …")` for literal, `search` for ranked retrieval. Native `Read` / `Grep` only on source code (`.ts` / `.py` / …), never on in-scope `.md` / `.mdx`.
2. **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 (`null` deletes a key). `delete({ document })` removes, `move({ from, to })` moves/renames. Body find/replace is body-only. Pass a one-line `summary` (≤80 chars, user-facing outcome) on every content write.
3. **Preview / open a doc — determine your ONE surface FIRST (once per session).** Stop at first match: **`OK_DESKTOP_TERMINAL` or `OK_HOSTED_AGENT` set** → you're inside OpenKnowledge (desktop terminal / in-app agent panel) → `ok open <name>` (switches the window the user is already looking at); never paste a `localhost` URL into your reply here · in-app browser (Claude Code Desktop's Browser pane, Cursor, Codex) → `preview_url`, then open/navigate it to the doc · else plain CLI → `ok open <name>`. `ok open <name>` opens a doc or folder (auto-detected); `--skill <name>` for a skill. The `previewUrl` field is a route id, **not** your open mechanism. Don't `preview_screenshot` to confirm edits. Full Step-0 procedure + per-surface how-to: `references/preview.md`.
4. **Direct questions:** a plain business question ("which customers…", "what did we decide about…") routes to `search` / `exec` + a cited chat answer — no "research" keyword needed. Persist only when durable + multi-doc + not already covered, and *offer* first. See `references/corpus-qa.md`.
5. **Authoring or improving a skill** ("write/make/improve a skill", "turn this into a skill"): STOP and invoke **`/open-knowledge-write-skill`** for scope (project/global), contract, evaluation, and install. Author through `write({ skill })`, never a document path. Skills are real folders under editor `skills/` dirs (`.claude` · `.cursor` · `.codex` · `.github` · `.opencode` · `.pi` · `.agents`): one source plus managed copies/symlinks. **Read/edit via `skills` and `edit({ skill })` — they route to the source.** Never hand-edit a non-source copy: recorded, unedited copies refresh from the source when the skill watcher runs or the server starts, so a source edit can precede the refresh. Editing a copy directly forks it and stops refresh.
## Tool index — 19 tools (router; calling contracts live in tool descriptions and input schemas)
- `exec` — read files and directories with document context.
- `search` — retrieve ranked workspace matches.
- `links` — inspect link relationships and suggestions.
- `lint` — check content rules and apply automatic fixes.
- `audit` — validate content rules and internal links.
- `write` — create or replace content.
- `edit` — change content or metadata in place.
- `delete` — remove content.
- `move` — rename or relocate content through managed operations.
- `install` — manage skill source and editor locations.
- `import` — acquire a skill folder without running scripts.
- `history` — inspect document, folder or skill versions.
- `skills` — discover, list or read skills by name and scope.
- `checkpoint` — save a named version.
- `restore_version` — restore a document or skill version.
- `palette` — discover components and authoring forms.
- `config` — read resolved configuration.
- `preview_url` — get the browser preview URL.
- `share_link` — get a GitHub-backed sharing link.
**Read `ran`** on successful lint/audit results: a family absent from `ran` was not checked, and `[]` means no checks were selected. For link VALIDATION use audit; links reports relationships and raw dead-link state. Caveats: `references/linking.md`.
Skill placement is separate from skill content: the source folder IS the skill, and removing an installed copy does not delete the skill. For a Project↔Global move, history resets; only what the destination level can host re-projects; the rest is removed at source, returned as `droppedLocations` (success: re-add with install). Read the returned outcome before recovery. A folder's frontmatter is open-shape and self-only (does NOT cascade); templates are what new docs start with.
**Self-correcting on misuse:** constraints JSON Schema can't express ("exactly one target", "`find` needs a `replace`", body-XOR-frontmatter) return `isError: true` with a one-line corrective shape. Read it and retry with that shape; don't guess.
Tools NOT in OK MCP (your host's): `preview_start`, `preview_screenshot`, `WebFetch`, `WebSearch`, native `Read` / `Grep` / `Glob` / `Edit`. The STOP rule governs which you may use on in-scope markdown.
## STOP — native tools on in-scope `.md` / `.mdx`
**Route every in-scope markdown read and write through OK's MCP tools — never your host's native file tools.** Native `Edit` / `sed` / direct `Write` 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 `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.
- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls -A …")` / `exec("find … -name '*.md'")` / `exec("cat …")`. Native returns bare names; `exec` adds frontmatter, backlinks, and recent activity. `-A` shows hidden entries without `.`/`..`.
- **Glob patterns that target markdown** — `exec` expands file operands (`cat specs/*.md`); quoted patterns and a command's own pattern (`find -name`) stay literal.
- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — a subagent may start without this skill loaded and then read markdown with its native tools, bypassing OK. Do markdown exploration yourself via `exec` / `search`. Subagents remain appropriate for **source-code** exploration.
- **Native `Read` / `Grep` on in-scope markdown inside `.ok/`** — `.ok/` is in-scope; treat its `.md` / `.mdx` like any other KB file.
- **`ls` / `cat` / `find` on skill folders to discover or read a skill** — skills are addressed by `name`+`scope`, not by path (a skill can live in any editor dir, the `.agents/skills/` hub, or a custom root, with copies elsewhere). Use the `skills` tool.
**Not seeing `exec` 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 `open-knowledge` first. Detail: `references/setup.md`.
**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` 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 `exec` as a top-level tool, didn't run tool discovery, or rationalized the skill wasn't necessary.
**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.
## Writing
Call `write` / `edit` 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 `edit` each section in as it firms up.
**Pass a `summary` on every content write (SHOULD)** — a one-line (≤80 char) user-facing note; it becomes the timeline entry. **Reach for visual structure** (Callout, `mermaid`, table, `html preview`) where it carries the point better than prose; call `palette` as you draft. Advisory write-warnings, MDX authoring, delete/move mechanics, and visual authoring: `references/writing.md` + `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`](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 `[source](https://...)` 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 `WebFetch` / `WebSearch`), ingest it, then cite the path: `[source name](./path/to/source.md)` (the local doc carries `source_url:`). Inline `[source](URL)` 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 `(TODO: needs source)`, 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. To point at one section of a long doc, in chat replies too, link `./path.md#heading-slug`. **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 (`` `[text](./foo.md)` `` is a bug) and never use HTML `<a>`. **After every `write`/`edit`, read `brokenLinks`: fix reported `href`s; `[]` means all links resolve unless `brokenLinkSuppression` withheld reserved-log findings (not yours to repair) or a `link-check-deferred` warning says nothing was checked yet (the server was still starting or busy with other writes; that doc is re-checked only by a later write/edit of it or an `audit`, which may time out while the server is still starting).** `audit` is authoritative; its same marker carries the same meaning. External web sources are NOT inline body links (see Grounding). Full rule set, slug rule + the `[[Page]]` legacy note: `references/linking.md`.
## Folders, frontmatter, templates
Every `.md` / `.mdx` needs YAML frontmatter — `title` + `description` required, `tags` recommended. **OKF projects (`okf` pack) are the exception:** pack rules win — a non-root `index.md` carries NO frontmatter (the `frontmatter-reserved-index` lint warns on any key), `log.md` needs none, and concept docs need only a non-empty `type`; `title`/`description` are optional there. 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 (`<folder>/.ok/templates/` — what new docs start with). Most folders have NO `.ok/`. 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 `exec("ls -A <folder>")` once per folder per session — it returns the folder's `title`/`description`/`tags` + `templates_available`. 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 (`write({ template })`). Folder frontmatter does not cascade values into docs.
## Write outcomes
For every write result, read `outcome` and follow `nextStep` (`references/conflict-resolution.md` has each outcome's move): never repeat a write that landed (`merged-first`, `both-kept`, `projection-held`), and when a refusal says `nextStep: none`, nothing you send changes it: tell the user which file and what the result says, and carry on.
## Anti-patterns — the top offenders
| Task | Don't | Do |
| --- | --- | --- |
| List / find / read markdown | `Bash: ls`/`Glob: **/*.md`/`Read: foo.md` | `exec("ls -A …")` / `exec("find …")` / `exec("cat …")` |
| Explore a markdown-heavy dir | `Agent(Explore)` (bypasses OK) | `exec`/`search` yourself |
| Reference another doc | `` `[text](./p.md)` `` (backticked) or HTML `<a>` | `[text](./p.md)` |
| Embed an image | `<img>`, a `localhost`/`preview_url` URL, hot-link | save locally + `` |
| Factual claim in a KB doc | prose with no citation, OR inline `[src](https://…)` | ingest the source (`references/ingest-and-sources.md`), cite the local path |
| Confirm an edit landed | `preview_screenshot` / verification loop | trust the CRDT tool response |
| Delete a markdown doc | `Bash: rm` / native deletion | `delete({ document })` (`checkpoint()` first if risky) |
| Write in an unfamiliar folder | straight to `write` | `exec("ls -A <folder>")` 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 → `status: provisional` article + `sources:`. | `/research-with-sources` skill |
| **consolidate** | A decision was made → canonical source-of-truth with a `supersedes:` chain. | `/consolidate-notes` 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 `write`, 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 `log.md` 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`.
## Capabilities beyond this skill
OK does more than this skill describes, and it changes between releases. Not covered here? Read rather than guess:
- **Docs** — <https://openknowledge.ai/docs>
- **Source** — <https://github.com/inkeep/open-knowledge>
## Scope recap
OK looks for documents under the resolved `content.dir` (runtime: `config({ key: 'content.dir' })`); `.gitignore` and `.okignore` (at root or any folder depth) define exclusions. **Every `.md` / `.mdx` under `content.dir` not excluded is an OpenKnowledge document** — including under `specs/`, `reports/`, `docs/`. Folder metadata + templates live in nested `<folder>/.ok/`, not in `.ok/config.yml`. **Working in a git worktree?** Pass the worktree's absolute path as `cwd` on your OK tool calls once — it sticks for the session, so reads, writes, and the preview all target that worktree.
© Inkeep · MIT · inkeep/open-knowledge-skills