Skip to content

Repository files navigation

kb-engine

A Claude-maintained, self-syncing knowledge base engine for code teams. It targets code knowledge: conventions, decisions, gotchas, recipes, glossary terms, and repo inventory. It is not a PARA or second-brain note system.

The engine ships two parts that stay separate:

  • Engine - the scripts, hooks, presets, and skill that live in this repo.
  • Content - a standalone git repo (or submodule) scaffolded by the engine and owned by your project.

Install

Option A: Claude Code plugin (primary)

/plugin marketplace add larstonder/kb-engine
/plugin install knowledge-base

This registers the engine as a plugin: it wires the five lifecycle hooks automatically (via hooks/hooks.json, resolved through ${CLAUDE_PLUGIN_ROOT}) and adds the /kb slash command used to scaffold content (below).

To develop against a local checkout instead, point the marketplace at the directory: /plugin marketplace add ~/path/to/kb-engine. (Prefer the GitHub source for normal use: a local directory source copies untracked files into the plugin cache.)

Option B: install.sh (non-plugin fallback)

./install.sh --project <project-dir>

This copies hooks/, lib/, and skills/knowledge-base/ under <project-dir>/.claude/kb-engine/ and merges the hook entries into <project-dir>/.claude/settings.json. Re-running is idempotent.


Set up a content repo

With the plugin installed, run the /kb slash command from inside the project you want a KB for:

/kb init <kb-dir> --preset general|monorepo [--mode standalone|submodule|inrepo] [--branch <branch>] [--auto-commit|--no-auto-commit]
/kb sync
/kb doctor

/kb wraps the bundled CLI (the plugin doesn't put kb on your PATH). If you installed via install.sh or a plain clone instead, call the CLI directly from the engine repo, passing --project:

./bin/kb init <kb-dir> --preset general|monorepo \
            [--categories a,b,c] \
            [--mode standalone|submodule|inrepo] \
            [--branch <branch>] \
            [--auto-commit|--no-auto-commit] \
            --project <project-dir>
./bin/kb sync --project <project-dir>
./bin/kb doctor --project <project-dir>

init creates the category folders, copies content-template files (CONVENTIONS.md, INDEX.md, BACKLOG.md, README.md, .gitignore, .gitattributes), vendors the validators into <kb-dir>/.kb/bin/, installs the git pre-commit hook (standalone/submodule only), and writes .kbconfig in the project root. sync re-vendors the validators and re-installs the pre-commit hook after an engine update. doctor checks dependencies, config, kb.json validity and version, vendored validators, and git state. The lifecycle hooks no-op in any project without a .kbconfig, so the KB only becomes active once init has run (and from the next session start).


How the content repo is stored

Three modes are available, selected via --mode at kb init time:

  • standalone (default) - kb init runs git init on <kb-dir>, making it a self-contained repo. init does not add a remote.
  • submodule - <kb-dir> is a git submodule, i.e. still its own repo, mounted in the parent project.
  • inrepo - the KB is plain files tracked inside your main project repo. See below.

Local-only (no remote)

A standalone KB works with no remote at all. Commits are recorded locally each session; the Stop hook's push and the SessionStart fast-forward simply no-op (logged, exit 0). Add a remote whenever you want syncing:

git -C <kb-dir> remote add origin <url>
git -C <kb-dir> push -u origin <branch>   # one-time; afterwards the hooks pull/push automatically

Nesting it inside an existing project

If <kb-dir> lives inside another git repo (e.g. .knowledge/ in your app), the KB is a nested repo: the parent repo sees it as a single embedded entry (git won't recurse into it). The engine does not modify the parent's .gitignore, so add the KB dir there yourself to keep the parent clean:

echo '<kb-dir>/' >> .gitignore   # in the PARENT project

inrepo: KB tracked inside your main project repo

--mode inrepo places the KB as plain files inside your application's own git history - do not gitignore it.

At Stop, the hook commits only the KB directory via a scoped pathspec commit (git commit -- <kb-relative-paths>). It never pushes and never pulls: the KB rides your normal branch workflow.

Caveat: with AUTO_COMMIT=true, KB commits land on whatever branch you have checked out, so they interleave with your feature work and ride along in PRs. If that is undesirable, set AUTO_COMMIT=false (the default for inrepo) and commit the KB dir yourself.

The engine does not install a pre-commit hook in inrepo mode (there is no separate .git to hook). Validation still runs at Stop. To validate KB entries on your own commits, wire <kb-dir>/.kb/bin/validate.sh into your project's pre-commit hook.


Configuration

Two config files are involved.

.kbconfig (project root)

Written by kb init. Read by every hook and kb sync at runtime.

KB_DIR=".knowledge"   # relative (or absolute) path from project root to the content repo
MODE="standalone"     # standalone | submodule | inrepo
AUTO_COMMIT="true"    # true | false; default true for standalone/submodule, false for inrepo
BRANCH="main"

AUTO_COMMIT

Universal knob that controls what the Stop hook does with KB changes:

  • true - Stop commits the KB. For standalone/submodule it then pushes to the remote; for inrepo it commits but never pushes.
  • false - Stop validates only; no staging or committing. You commit the KB yourself.

Defaults: true for standalone and submodule, false for inrepo.

Override at init time:

kb init <dir> --mode inrepo --auto-commit      # force true
kb init <dir> --mode standalone --no-auto-commit  # force false

kb.json (content repo root)

Written by kb init from the chosen preset. Defines the category schema and enables/disables the opt-in checks.

{
  "version": 1,
  "categories": [
    { "name": "glossary", "type": "glossary" },
    { "name": "decisions", "type": "decision",
      "extraFields": [{ "name": "status", "allowed": ["active", "superseded"] }] }
  ],
  "checks": {
    "frontmatter": true,
    "wikilinks": false,
    "ghostLinks": false,
    "graphConnectivity": false
  },
  "staleMonths": 3
}

Presets

Preset Categories Checks enabled
general glossary, conventions, decisions, recipes, gotchas frontmatter only
monorepo glossary, conventions, decisions, recipes, gotchas, repos frontmatter + wikilinks + ghostLinks + graphConnectivity

Use --categories a,b,c to override the category list from a preset.


Lifecycle hooks

All hooks guard on .kbconfig and exit 0 immediately if the project has no KB configured.

Event Hook Behaviour
SessionStart kb-pull.sh Fast-forwards the content repo to origin/<branch>. Skips silently if offline, dirty tree, or local commits are ahead.
SessionStart kb-stale-sweep.sh Flags entries whose updated frontmatter date is older than staleMonths.
Stop kb-capture-checkpoint.sh Once per session, blocks the stop with a self-check nudge when no KB changes have been made.
Stop kb-auto-push.sh Validates staged entries; quarantines invalid ones; commits and pushes the clean remainder.
PostToolUse(Read) kb-log-read.sh Logs a consult entry to .usage.log when Claude reads a KB entry file. De-duplicates per session.

Validators

The entry validator (validate.sh) and opt-in checks (check-wikilinks.sh, check-ghostlinks.sh, check-graph.sh) are vendored into <kb-dir>/.kb/bin/ at init and sync time. The git pre-commit hook in the content repo calls validate.sh so entries are checked locally before any commit, without requiring the engine repo to be on PATH.

Validation reads category types, allowed extra-field values, and enabled checks directly from kb.json. No hardcoded category names.

validate.sh uses a plain generated git pre-commit hook (not lefthook or any external hook manager).

Strict YAML parsing uses ruby or python3 when available; falls back to grep-based parsing otherwise.


Dependencies

  • bash (>= 3.2)
  • jq
  • git
  • python3 or ruby (optional - for strict YAML frontmatter parsing; falls back to grep)

Repository layout

bin/kb                        # init and sync CLI
content-template/             # files copied into every new content repo
hooks/                        # five lifecycle hook scripts + hooks.json
hooks/hooks.json              # plugin hook wiring (uses ${CLAUDE_PLUGIN_ROOT})
lib/                          # config.sh, gitops.sh, validate.sh, check-*.sh,
                              #   template.sh, precommit.tmpl
presets/general.json          # preset: code team, frontmatter check only
presets/monorepo.json         # preset: multi-repo, all checks enabled
skills/knowledge-base/        # SKILL.md + scripts/log-consult.sh
.claude-plugin/plugin.json    # plugin metadata
.claude-plugin/marketplace.json
install.sh                    # non-plugin install path
tests/                        # test_*.sh + run.sh

License

MIT - see LICENSE. Copyright (c) 2026 Lars Tønder.

About

Claude-maintained, self-syncing knowledge base engine for code teams (Claude Code plugin).

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages