npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bartolli/kmd

v0.17.2

Published

Knowledge-markdown CLI + MCP server. One binary for vault sync, validate, and the wiki-mcp agent tools.

Readme

kmd — knowledge-markdown

kmd is a knowledge system for AI agents, built on Open Knowledge Format primitives: plain markdown, YAML frontmatter, a controlled vocabulary. What it adds is timing. The right context reaches the agent at the right moment, and costs nothing the rest of the time.

A cold session gets its orientation in one prime call: current focus, invariants, what to read. search returns ranked candidates, never page dumps. Hooks steer the agent at the exact event where a rule applies: a reminder on the prompt that needs it, a gate on the tool call that would break it, validation on the write that touched the vault. Rules that would otherwise sit in instruction files, paying tokens on every request, fire only when they matter.

The vault stays plain markdown in git, Obsidian-compatible. Works with Claude Code, Codex, and Kiro. No database to run.

npx @bartolli/kmd --help

Quick start

Two setups. Pick one, or use both; they compose.

A global vault. One personal wiki serving all your projects:

npx @bartolli/kmd init ~/wiki-vault --set-default

--set-default records the vault in ~/.kmd/config.yaml. Every kmd command and MCP server on this machine now finds it without configuration.

A project vault. The repo carries its own knowledge:

cd my-repo
npx @bartolli/kmd init --local

This scaffolds my-repo/vault/ plus a .kmd/ state home. Every command run inside the repo resolves this vault automatically, and it wins over the global default. Nothing else to configure.

Then, either way:

kmd validate   # deterministic checker, no LLM
kmd sync       # vault → SQLite index

An existing vault. When the engine moves ahead of a vault scaffolded earlier — a new kind, a new template — bring it to the starter:

kmd init --upgrade            # report the delta; exit 1 when behind
kmd init --upgrade --apply    # append the missing pieces; nothing you wrote is touched

Where things live

| Thing | Where | Nature | |---|---|---| | Vault | wherever you put it (~/wiki-vault, <repo>/vault/) | yours: markdown + vault.yaml, git-tracked, canonical | | Index | ~/.kmd/db/{vault-key}/index.db, or <repo>/.kmd/db/ for project vaults | disposable: kmd db reset deletes it, kmd sync rebuilds it | | Machine config | ~/.kmd/config.yaml | default_vault, written by kmd init --set-default or kmd config set | | Project config | <repo>/.kmd/config.yaml | committed, repo-relative paths; .kmd/config.local.yaml is the personal, gitignored override | | Hook state | ~/.kmd/state/ or <repo>/.kmd/state/ | session dedup markers; survives kmd db reset |

A project vault's index and state live in the repo. Delete the repo and they go with it.

How kmd finds your vault

One resolution order, used by the CLI, the MCP server, and the hooks. First hit wins:

  1. An explicit path argument: pins that vault, beats everything.
  2. The project: nearest ancestor with .kmd/config.local.yaml, .kmd/config.yaml, vault/vault.yaml, or a vault.yaml with a .kmd/ directory beside it.
  3. --default-root <path>: a configured default the project may beat.
  4. $WIKI_VAULT.
  5. default_vault from ~/.kmd/config.yaml.

The project signal is the working directory: the shell's for CLI commands, the session's for hooks, KMD_PROJECT_DIR for MCP servers. When something resolves to the wrong vault, run kmd config. It prints the vault and which rank won.

Teams commit .kmd/config.yaml with a repo-relative vault: path or a ${VAR} expansion. Absolute paths belong in the gitignored config.local.yaml.

Commands

kmd init [<dir>] [-y] [--set-default]   scaffold a vault; --set-default records it as the machine default
kmd init --local [-y]                   project vault at <git-root>/vault/ with a .kmd/ state home
kmd init --upgrade [<vault-root>] [--apply]
                                        report the vault's delta against the starter, exit 1 when behind; --apply writes it, additive only
kmd validate [<path>]                   deterministic vault checker
kmd sync [<vault-root>]                 vault → SQLite index (validates first, aborts on errors)
kmd mcp [<vault-root>] [--default-root <path>]
                                        stdio MCP server
kmd config [<vault-root>]               print resolved vault, index path, winning rank
kmd config <set|get|unset> default_vault [<path>]
kmd db reset [<vault-root>]             delete the vault's index
kmd resource <uri> [<vault-root>]       print wiki://authoring, wiki://templates, or wiki://template/{domain}/{kind}
kmd prime <scope> [<vault-root>] [--task <text>]
kmd search <query> [<vault-root>] [--scope <s>] [--kind <k>] [--limit <n>]
                                        CLI mirrors of the MCP surface, for harnesses that read no resources
kmd hook <prompt|pretool|posttool|stop|session-start> [--default-root <path>] [--scope <s>] [--harness <h>] [--explain|--dry-run]
                                        harness gate engine (see Hooks)

kmd --help is canonical for flags; this list names the surface.

MCP server

Two tools, deliberately few:

  • prime(scope, task?) returns an orientation briefing: identity, primer, active decision records, current plan, vocabulary, most-linked pages, recent activity, cross-scope links. Pass task and it adds the top-ranked relevant pages, weighted so a page naming the concept in its title outranks pages that merely mention it.
  • search(query, scope?, kind?, limit?) returns ranked candidates {path, title, kind, summary, score}. Never page bodies; the agent opens files itself.

Templates are served as MCP resources at wiki://template/{domain}/{kind}, and the authoring guide at wiki://authoring.

All of it is also a CLI: kmd prime <scope>, kmd search <query>, and kmd resource <uri> run an in-process client of the same server, so a harness whose agent cannot read MCP resources (CoCo, Kiro) still reaches the authoring guide and templates from a shell.

Registration:

{
  "mcpServers": {
    "wiki": {
      "command": "npx",
      "args": ["-y", "@bartolli/kmd", "mcp", "--default-root", "/absolute/path/to/vault"]
    }
  }
}

--default-root keeps the resolution order live: a project that carries its own vault wins automatically. Passing the path as a bare positional instead pins that one vault unconditionally. Use it only when that is what you want.

Skills

The wiki-sdd plugin ships a complete spec-driven development loop that reads and writes the vault. Each is a slash command ($name on Codex):

| Skill | What it does | |---|---| | /wiki | wires a project to the wiki; local-vs-global vault setup; brings an existing vault to the starter; the hub for everything below | | /intent | interview that sharpens intent and scaffolds a scope: index, primer, glossary, lazy ADRs | | /to-stories | turns the working conversation into a thin plan plus user stories with Gherkin scenarios | | /triage | moves stories through needs-triage → ready-for-agent / ready-for-human / wontfix | | /to-issues | slices stories into vertical tracer bullets; mirrors to GitHub or GitLab when configured | | /tdd | implements one ready-for-agent slice, red-green-refactor, and ticks its checkbox | | /retro | three questions, any time drift is suspected; routes the answers into intents and story Decisions, never a story | | /handoff | closes the session: status sweep on approval, Story Index reconcile, the primer under budget — gated on a fresh retro | | /to-triggers | turns a prose rule into a tested vault trigger: you own the intent, it owns the regex | | /signal-dense | canonical-vocabulary register for long agentic threads |

The working loop: /intent → /to-stories → /triage → /to-issues → /tdd per slice → /retro whenever drift is suspected → /handoff to close. /wiki is the on-ramp; /to-triggers joins whenever a rule proves it should be a gate. The same skills render for all three harnesses below.

Harness integration

Claude Code

The repo is a plugin marketplace. The wiki-sdd plugin wires everything: the MCP server, all five hook events, and the nine skills.

claude plugin marketplace add bartolli/kmd
claude plugin install wiki-sdd@kmd

Project vaults resolve automatically: the plugin passes the project directory to the server. No per-project files.

Codex

codex plugin marketplace add bartolli/kmd
codex plugin add wiki-sdd@kmd

Hooks are project-aware out of the box. The MCP server needs one line of help, because Codex gives plugin MCP servers no workspace signal (openai/codex#37903). Add to your shell profile:

codex() { KMD_PROJECT_DIR="$PWD" command codex "$@"; }

Now every Codex launch carries its project directory, and prime/search follow project vaults exactly as on Claude Code. Details: codex adapter README.

Kiro

Kiro installs the shared source as an Agent Plugins package: plugins/src/wiki-sdd carries plugin.json, the skills, and the wiki server's mcp.json. Import the folder as a power from the Powers panel; the package README has the steps. Both Kiro seats (IDE and CLI) read the same power.

Manual wiring

No plugin, any harness that supports command hooks. Install globally first. Hooks spawn per event, and a global install keeps the spawn fast:

npm i -g @bartolli/kmd
{
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command",
        "command": "kmd hook prompt --default-root /absolute/path/to/vault" }] }
    ],
    "PreToolUse": [
      { "hooks": [{ "type": "command",
        "command": "kmd hook pretool --default-root /absolute/path/to/vault --harness claude" }] }
    ],
    "PostToolUse": [
      { "matcher": "Write|Edit|Bash",
        "hooks": [{ "type": "command",
        "command": "kmd hook posttool --default-root /absolute/path/to/vault --harness claude" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command",
        "command": "kmd hook stop --default-root /absolute/path/to/vault" }] }
    ],
    "SessionStart": [
      { "hooks": [{ "type": "command",
        "command": "kmd hook session-start --default-root /absolute/path/to/vault" }] }
    ]
  }
}

--harness claude emits Claude Code's decision JSON on tool events. Without it the output is a neutral JSON contract. Kiro IDE wires the prompt event with --harness kiro-ide.

Hooks

Rules in instruction files cost tokens on every request. A trigger costs nothing until the moment it applies, then delivers the whole rule. Triggers are declared in vault.yaml; kmd hook evaluates them when the harness fires an event.

Five events:

  • prompt: matching triggers inject one context line each, once per session.
  • pretool: gates before a tool runs: inject, warn, or deny with a reason the agent reads.
  • posttool: after a write inside the vault, kmd validate runs; findings return to the agent and the index holds until they are fixed. Clean writes sync silently.
  • stop: a session ending with validation errors is sent back once with the fix list.
  • session-start: a session opening inside a scope's repo gets one orientation line: prime first, plus the backlog band (stale AFK stories, draft intents) and a vault behind the starter when either applies.
triggers_extra:
  my-app:
    - id: retro-before-tag
      on: pretool
      enforce: block
      tool: Bash
      args_match: "\\bgit tag\\b"
      when:                    # precondition: the gate fires only while it is unmet
        name: newer-than
        fresh: ["notes/my-app-retro-*.md"]
        than: ["projects/my-app/ops/release-*.md"]
      reason: "Retro gate: run the retro before tagging."

Prompt triggers match keywords with stemming on word boundaries; intent regexes are the escape hatch. Pretool matchers AND-compose: tool name, args_match regex, files globs. when predicates read your vault's files at call time. The example denies tagging until a retro note postdates the last release note.

You don't write this YAML by hand. The /to-triggers skill interviews your intent, authors the keyword and regex mechanics itself, proves fire and near-miss behavior with a dry run, and writes vault.yaml only after validation passes. You own the rule; it owns the regex.

Declare repo: on a scope and the engine resolves the active scope from the session's working directory:

scopes:
  my-app:
    status: active
    repo: ~/Projects/my-app

Everything fails open. A broken config means one stderr line and no gate work: never a blocked prompt, never a denied unrelated call. Test triggers by hand with kmd hook prompt --explain (a read-only trace; never wire probe flags into hook registrations).

If other Node tooling in your agent loop prints ExperimentalWarning noise, set NODE_OPTIONS="--disable-warning=ExperimentalWarning" in the harness env.

The vault

vault/
├── vault.yaml               # controlled vocabulary, the contract
├── templates/               # frontmatter templates, served as MCP resources
├── projects/{scope}/        # specs, ADRs, plans, stories, intents, scoped notes
├── research/{topic}/        # articles, sources
└── notes/                   # low-ceremony capture

Every page carries YAML frontmatter validated against vault.yaml:

# projects/my-app/adr/adr-sqlite-index.md
---
title: "SQLite for the index"
kind: adr
status: active
tags: [storage]
created: "2025-03-15T09:12:00Z"
updated: "2025-06-01T14:03:27Z"
---

kind selects the template, status tracks lifecycle, and every value must appear in vault.yaml or validation fails. Loading is fail-loud: an invalid vault.yaml stops the server and blocks sync rather than serving drift.

kmd validate runs its deterministic rules, no LLM involved. Among them: dangling-link (every [[wikilink]] resolves), ambiguous-link (a bare [[name]] owned by two files must disambiguate), supersession-reciprocal (an ADR superseding another requires the back-pointer), path-authority (the path, not frontmatter, decides scope and topic), and tag-alias (aliases normalize to canonical tags). Sync refuses to index a vault with errors.

vault.yaml also carries the served pedagogy: the authoring rules agents read at wiki://authoring, custom kinds with their own templates, your methodologies, and the trigger declarations. The full reference with every field and customization pattern: docs/vault-config.md. A complete annotated example: vault.yaml.example.

kmd vs OKF

Same primitives as Open Knowledge Format (markdown, YAML frontmatter, a directory tree), but opinionated where OKF is minimal:

| | OKF | kmd | |---|---|---| | Vocabulary | open: producer picks type values | controlled: vault.yaml defines kinds, scopes, statuses, tags; kmd validate enforces | | Structure | flat: organize however | three domains: projects/ · research/ · notes/ | | Validation | none: format spec only | seventeen deterministic rules, LLM-free; gates sync | | Cross-refs | bundle-relative /path.md | [[wikilinks]]: Obsidian-native, rename-safe, no dangling links | | Agent surface | none | two MCP tools (prime, search) + template resources | | Guardrails | none | prompt reminders and tool gates from vault.yaml | | Infrastructure | n/a | node:sqlite FTS5, zero external services |

Development

Node.js 22+ (node:sqlite) and pnpm 11+.

pnpm install
pnpm -r run typecheck && pnpm -r run test && pnpm lint

The plugin adapters under plugins/{claude,codex,kiro} are build output. Edit the shared source in plugins/src/wiki-sdd/, then render and verify:

pnpm --filter @llm-wiki/render render && pnpm --filter @llm-wiki/render check

A hand-edited adapter copy diverges silently until the next render overwrites it. check asserts every copy matches the rendered output.

License

MIT