pengelbrecht/skills · Archived

repo-wiki

Build and maintain a living, agent-first knowledge base for a git repo — a "repo-wiki" of architecture, decisions, constraints, product context, and glossary that stays trustworthy because staleness is detected by git and tacit knowledge is captured from chats. Use this skill whenever a project's docs are sprawling or out of date, when onboarding context lives only in people's heads, or when the user wants to "set up a knowledge base", "document the architecture", "write an ADR / decision recor…

First seen Jun 15, 2026

Installation

$ npx skills add pengelbrecht/skills --skill repo-wiki

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from pengelbrecht/skills · top by installs.

npx skills add pengelbrecht/skills

Browse all from pengelbrecht/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0
Declared agents claude-code
More metadata
version
0.1.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 25,117 B
  • docs SUMMARY.md 939 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 23 installs

SKILL.md

repo-wiki

A living, agent-first knowledge base that lives in a git repo at repo-wiki/. It stays trustworthy because of two commitments: store only what the code can't regenerate, and capture the reasoning that otherwise dies at the end of every chat. Staleness is detected deterministically by git; tacit knowledge is mined from conversations. Changes are applied directly — git review is the safety net — and significant writes are reported so the human can review or revert. It's apply-and-report, not ask-first.

Full design rationale: see docs/ideas/repo-wiki.md in this repo if present.
This SKILL.md is the operating manual; depth lives in references/.

When to use this skill

  • Setting up a knowledge base for a repo → run kb bootstrap, then follow the

scan → propose → agree → scaffold flow (see below and references/bootstrap.md).

  • Capturing knowledge during/after a session — a decision settled, a constraint

learned, a gotcha hit. This is the highest-value, most frequent action.

  • Checking freshness — which pages drifted from the code (kb status).
  • Catching up on chats the live hook missed (kb catchup).
  • Hollowing out a bloated CLAUDE.md / AGENTS.md into a thin shim.

The two ideas that make this work

  1. Recoverability. Knowledge that can be regenerated from the code (file tree,

API surface, "what the code does") is the fastest-rotting, lowest-value kind — don't persist it; generate it on demand. Persist only the non-derivable: the why, the gotchas, the mental models, the constraints, the product context. (Exception: an expensive-and-hot derivation may be cached as a from-code page that auto-refreshes — see references/pages.md.)

  1. Chat is the primary intake. Most non-derivable knowledge is tacit — it

surfaces in conversation and is then thrown away. Code→docs is the cheap cache; chat→knowledge is the precious, capture-or-lose-forever stream.

If you internalize nothing else: persist only the non-derivable, and mine the chats.

Quickstart — three setup commands

Three composable commands cover setup; pick the one that fits:

Command What it does When to use
kb init Install all hooks + plumbing only — no dirs or INDEX files Any time; order-independent
kb plumbing Install hooks + gitignore only — no dirs Any time; order-independent (same as init)
kb scaffold Create dirs + INDEX files only — no hooks; requires an explicit agreed-set flag After Gate 1 (always — new or existing repo)

The wiki structure is NEVER created automatically. It must be agreed with the user
first (via the scan → propose → agree → scaffold flow). kb init and kb plumbing
are plumbing-only; kb scaffold (with --recommended, --only, or --add) is what
creates the structure, and only after agreement.

init / plumbing — hooks only

python3 scripts/kb.py init        # or: python3 scripts/kb.py plumbing (same effect)

Installs all hooks (SessionStart, UserPromptSubmit/comments, PreCompact, SessionEnd, post-commit) and gitignore entries. Creates repo-wiki/.ingest/. No dirs or INDEX files are created. Idempotent. Run any time — before or after kb scaffold, before or after Gate 1.

scaffold — structure only (requires agreed set)

python3 scripts/kb.py scaffold                                          # prints proposal + agree-first reminder; creates NOTHING
python3 scripts/kb.py scaffold --recommended                            # scaffold recommended CATEGORIES (user accepted default set)
python3 scripts/kb.py scaffold --recommended --add operations           # default set + extra
python3 scripts/kb.py scaffold --only product,decisions --add operations  # agreed custom set

Creates repo-wiki/ + the agreed category folders + INDEX files. No hooks installed. --recommended scaffolds the recommended CATEGORIES when the user accepted the default set as-is. --only <comma-list> restricts the core set; --add <name> appends extra categories (can be combined with either --recommended or --only). Idempotent: never clobbers existing INDEX files. With no flags: creates nothing — prints the recommended proposal + agree-first reminder instead (exit 0).

Use after Gate 1 agreement during the bootstrap flow to scaffold exactly the agreed structure. Then read references/structure.md and seed the obvious pages. A new wiki is small — INDEX.md plus a few real pages — not a tree of empty folders.

Bootstrapping — the universal flow (new or existing repo)

Structure must always be agreed before it is scaffolded — for every repo, new or existing. The bootstrap flow is the entry point for creating a wiki. Run the read-only scan first:

python3 scripts/kb.py bootstrap   # read-only signal report; nothing is written

Then follow references/bootstrap.md for the full interactive protocol. The flow is multi-turn and cannot be compressed into a single command — it requires two human gates:

  • Gate 1 — Agree the MECE structure. Present the recommended category set as an

example proposal adapted to the repo's signals (ops indicators, ADR directory, etc.). State explicitly that it is a proposal; let the user rename, add, or remove categories. Agreement is recorded in the root INDEX.md resolver. Only after Gate 1: run kb scaffold --recommended (if accepted as-is) or kb scaffold --only/--add (if adjusted) to create exactly the agreed folders. No mining begins until Gate 1 closes.

  • Gate 2 — Agree the ingestion scope. For each source (chats, commits, docs, code),

show counts and estimated effort. The user picks which sources to mine and how far back. Mining begins only after Gate 2 closes.

Once both gates close, mining fans out to parallel subagents — one per source type — so a large repo's cold-start is fast and non-blocking. Generated pages are applied directly and the batch is reported, so the human can review the diff and revert any miss (apply-and-report applies end-to-end; the bootstrap import is itself a significant write worth summarizing).

kb init / kb plumbing are order-independent. Run either at any time during the
bootstrap flow (even before Gate 1) to wire all hooks. Neither creates structure.
kb scaffold (with --recommended, --only, or --add) is what follows Gate 1.

Command comparison:

kb init kb plumbing kb scaffold kb bootstrap
What Hooks + plumbing only Hooks + plumbing only Dirs + INDEX only Read-only signal report
Creates structure? No No Yes — after Gate 1 agreement No
Gates None None None Leads into two interactive gates
Mining None None None Parallel subagents (after gates)
Output Hooks + gitignore Hooks + gitignore Agreed folder tree Proposed wiki pages
When Any time (plumbing-only) Any time (plumbing-only) After Gate 1 Any repo with history to mine

Structure (recommended, not prescribed)

MECE at level 1, free below it. Everything is a folder. Every folder has a short INDEX.md (purpose + local convention — never a file listing; that's what ls is for).

repo-wiki/
  INDEX.md         # root: purpose + the MECE resolver + the manual
  product/         # PROBLEM   — who it's for, why, requirements, non-goals, metrics
  glossary/        # LANGUAGE  — ubiquitous language
  architecture/    # SOLUTION  — how it's built; from-code traversal caches
  constraints/     # RULES     — invariants, NFRs, gotchas (what must stay true)
  decisions/       # RATIONALE — choices + rejected paths (NNNN-slug.md)
  # optional: operations/  roadmap/  conventions/
  inbox/           # raw captures awaiting triage
  archive/         # superseded pages (retired, not deleted)

The resolver ("what is the primary subject?") and the disambiguation rules that keep level-1 MECE live in references/structure.md. Read it before filing anything.

Page model — Compiled Truth + Timeline

Every page has a cheap mutable head and an append-only immutable evidence trail:

---
type: constraint
source: canonical          # canonical | from-code | from-doc
covers: [src/billing/**]    # paths this claims about → drift trigger
verified_against: a1b2c3d   # sha at last confirmation
status: active              # active | superseded | archived
---

## Compiled Truth     ← current synthesis; rewritten on change; injected at session start
Billing endpoints must stay <50 req/s — the upstream ledger API rate-limits us.

## Timeline           ← append-only provenance
- 2026-06-13 — captured from chat (session abc); 429s above ~50rps — verified @a1b2c3d

The rule that keeps trust intact: apply directly, then report significant writes — git review is the safety net, so an agent writes the change rather than blocking to ask. A Timeline append is cheap and silent; a new page or a rewritten Compiled Truth is significant — name it in your turn so the human can review or git-revert. The source axis still labels recoverability (from-code can be re-derived by re-reading code; canonical is non-derivable why/intent), which drives freshness — but it no longer gates the act of writing. Full page conventions and the three-way freshness model: references/pages.md.

Capturing knowledge (the core loop)

When a session settles a decision, surfaces a constraint, or defines a term, file it. Use the resolver to pick the folder, the page template (assets/templates/page.md) for the shape, and apply the change directly — then report it if it's significant (a new page or a rewritten Compiled Truth, not a one-line Timeline append). If code is involved, stamp covers: with the relevant paths so the page enters the staleness system already wired in.

The extraction prompts are the heart of thisreferences/extraction.md holds two verbatim prompts: one mines a chat transcript for durable non-derivable knowledge — decisions, constraints, terms, gotchas — even when the session changed no code (a decision reached with zero diff is a first-class keeper); the other reconciles a commit diff (refresh from-code caches + flag canonical drift) and needs no chat. Both first load python3 scripts/kb.py outline so they route and dedup against the actual wiki (real categories + existing pages), not the generic defaults. Both are stingy and apply-and-report. Prompt 1 runs at session-end and inside kb catchup; prompt 2 runs at commit/PR/CI.

Most capture is mechanical: the kb catchup engine mines past sessions so nothing is lost even if you forget to file inline. See references/intake.md.

Write-back on a cache miss is the third capture path (alongside chat triage and code-synthesis): when an agent needs project knowledge the wiki lacks, it resolves it (reads the code, asks the user, or web-searches) and then adds a page so the next agent doesn't re-derive it — only when the knowledge is durable and non-obvious. This is why the shim and root INDEX.md carry a "missing knowledge?" instruction: the wiki is a write-back cache that grows from use, not just from chats.

Find a page — kb search

Ranked full-text search over page bodies, for when ls + covers: + descriptive filenames aren't enough (larger wikis, fuzzy recall):

python3 scripts/kb.py search "staleness covers"      # ranked hits + gist + snippet
python3 scripts/kb.py search "rotating tokens" -n 5  # cap results (default 10)
python3 scripts/kb.py search "edge auth" --json      # machine-readable

It uses SQLite FTS5 / BM25 (porter stemmer, title-boosted), modeled on the recall skill. The index is per-wiki — one .ingest/search.db scoped to this repo's pages (gitignored, rebuilt locally by file mtime on every search, never committed) — no embeddings, no models, stdlib sqlite3 only. Unlike recall's machine-wide chat index, results never span repos. Each hit carries the page's Compiled-Truth line as context, so a match comes with the page's gist, not just a snippet. On interpreters whose sqlite3 lacks FTS5 it transparently falls back to ripgrep. This same ranked search backs the web viewer's /api/search.

Local web viewer — kb serve

Browse the wiki in a browser without any external deps:

python3 scripts/kb.py serve               # default port 7654, auto-detects wiki
python3 scripts/kb.py serve --port 8080   # custom port
python3 scripts/kb.py serve --wiki path/to/repo-wiki   # explicit wiki dir

Opens at http://127.0.0.1:<port>/. What you get: a sidebar tree, page render with frontmatter table + Compiled Truth + Timeline, in-page TOC, ranked FTS5 search (see kb search above), staleness pills (fresh / stale / unverified), covers chips, and backlinks.

Design stance: stdlib-only server, vendored offline assets, localhost-only, read-only. Editing pages via the browser is a deferred follow-up (see references/web.md). Full technical details (API routes, security posture, asset provenance): references/web.md.

Comments — human-in-the-loop feedback

The wiki viewer lets users highlight text and post inline comments. These land in <wiki>/.comments/comments.jsonl and are surfaced to agents two ways:

  • Passive hook (wired by kb.py init as a UserPromptSubmit hook): injects open

comments at the top of every agent turn with zero poll overhead.

  • Active watch loop: the agent calls kb.py comments list --json --since <cursor>

on a short interval, acts on new comments, and advances the cursor.

Each comment carries a line anchor (page, line, endline, section, selectedtext) so agents know exactly where in the file the feedback applies.

The agent-edits → viewer-updates loop: when an agent rewrites the .md file in response to a comment, the viewer picks up the change within ~5 seconds via live auto-refresh (per-page /api/changed poll + global /api/revision poll) — no manual reload needed.

Consumption protocol: read the anchor, act (usually edit the .md directly — the comment is the approval), append a Timeline entry, then kb.py comments resolve <id> --note "...".

Full details — hook install snippet, watch-loop pseudocode, act-then-resolve rules, edge cases: references/comments.md.

Staleness & catch-up

python3 scripts/kb.py bootstrap      # read-only signal report for the interactive cold-start
python3 scripts/kb.py status         # full freshness report (live git scan)
python3 scripts/kb.py status --new   # delta: newly stale only, surfaces each page once
python3 scripts/kb.py catchup        # mine chat sessions since the watermark
python3 scripts/kb.py verify <page>  # mark page fresh at HEAD + clear surfaced cursor
python3 scripts/kb.py post-commit    # diff-scoped nudge (runs automatically via git hook)
python3 scripts/kb.py precompact     # print extract-before-compaction directive
python3 scripts/kb.py session-end    # catch-up nudge (runs automatically via SessionEnd)
python3 scripts/kb.py session-start  # heartbeat block (runs automatically via SessionStart)

status is deterministic: it intersects each page's covers globs with what changed in git since its verified_against sha. Stale = a review-queue entry, never a commit gate (hard gates breed --no-verify habits). catchup wraps the vendored recall scripts (multi-agent: Claude / Codex / pi) to enumerate and read sessions.

kb verify <page> is the one-command way to clear a stale/surfaced page: it bumps verified_against to HEAD, appends a Timeline entry, and removes the page's surfaced cursor key. After verify, status --new is silent for that page unless it drifts again.

status --new / delta mode: announces newly-stale pages exactly once per fresh→stale transition. A .ingest/surfaced.json cursor tracks which pages have been surfaced. Re-running status --new in the same session is silent. kb verify clears the cursor entry, allowing the page to surface again if it later drifts.

Details and the watermark model: references/intake.md.

Keep heavy work off the main thread. Long transcripts, large diffs, and multi-session catch-up are slow and token-heavy — dispatch extraction and catchup to subagents or a background job, never inline in the user's session. The SessionStart hook is already non-blocking by design: kb.py session-start does no git scan (it reports a cached drift summary and spawns a detached kb.py reconcile to refresh it). See references/activation.md.

Activation — wired triggers

Maintenance is an install problem, not a willpower problem. kb init or kb plumbing (both plumbing-only, order-independent) installs four committed Claude hooks and one git hook. After that, maintenance is automatic:

Hook Type Fires Effect
SessionStart .claude/settings.json every session inject wiki, announce new-stale delta, surface inherited knowledge-debt, self-heal hooks, spawn reconcile
UserPromptSubmit .claude/settings.json every turn tick the knowledge-debt counter (+ nudge) then inject open wiki comments
PreCompact .claude/settings.json before compaction prints extract-before-compaction directive
SessionEnd .claude/settings.json session ends nudge to run kb catchup
post-commit .git/hooks/post-commit every commit diff-scoped staleness nudge + knowledge-debt tick (exit 0 always)

Add a CI check on PRs as the ungameable backstop. Full details: references/activation.md.

Proactive capture — the knowledge-debt counter

Code drift is caught mechanically (kb status = git diff ∩ covers). Chat-borne knowledge — decisions, gotchas, "why", new subsystems — had no equivalent signal: it relied on the human remembering, or on edge-of-session nudges the agent blows past. A standing "add a page" instruction decays over a long session as context fills.

The knowledge-debt counter is that missing recurring signal. In repo-wiki/.ingest/state.json it tracks {commits, turns, sincesha, sincets}:

  • post-commitcommits += 1; turn-tick (folded into the UserPromptSubmit

hook) → turns += 1.

  • Crossing a threshold (≥ 5 commits or ≥ 15–20 turns since the last wiki write)

prints a visible, escalating, agent-directed line (⚠⚠) telling the agent to proactively offer a one-line capture. post-commit also names committed subsystems with no covering page.

  • Self-resetting: writing any tracked page (*.md, not INDEX.md/.ingest/

.comments) zeroes the counter — a diligent session is never nagged. The reset deliberately ignores .ingest/ so the search.db cache and state.json itself can't trigger a false reset.

Deterministic to fire (no LLM judgment), recurs during the session in front of the agent, and never gates a commit — like kb status, a soft signal. Hard gates breed --no-verify habits; this is capture pressure, not a blocker.

Upgrading an existing installation

No re-init required. The new logic rides existing hook invocations, so it activates the moment a repo's kb.py is updated to this version:

  • post-commit and SessionStart already call kb.py; the new counter logic is

inside cmdpostcommit / cmdsessionstart.

  • The turn tick is folded into the UserPromptSubmit hook's command. Existing installs

pick it up via the SessionStart self-heal, which rewrites a repo-wiki hook whose desired command changed (not just a stale path) — so the next session re-wires the comments hook to also run turn-tick. Zero manual steps.

  • state.json gains a knowledge_debt key, default-initialized on first read (old files

predate it; it's gitignored, so no migration conflict).

The only installs needing a manual kb plumbing are ones predating the UserPromptSubmit comments hook entirely (self-heal repairs existing hooks but won't re-add a hook a user may have intentionally removed).

New-collaborator / fresh clone

What a fresh clone inherits (from .claude/settings.json, committed):

  • SessionStart hook — heartbeat, delta surfacing, knowledge-debt surfacing, self-heal, reconcile spawn
  • UserPromptSubmit hook — knowledge-debt turn-tick + wiki comments injection
  • PreCompact hook — extract-before-compaction directive
  • SessionEnd hook — catch-up nudge

What it does NOT inherit:

  • .git/hooks/post-commit — git never clones local hooks; this is a hard git constraint
  • .ingest/ — local watermark state (gitignored by design; each developer has their own)
  • .comments/ — local comment store (gitignored)

The fix — zero extra steps needed:

The SessionStart hook self-heals the git hook automatically: on the first Claude Code session after a fresh clone, kb session-start detects the missing .git/hooks/post-commit and recreates it. No manual kb init is required.

One trust prompt is unavoidable. Claude Code will ask the user to approve the SessionStart (and other) hooks on the first session. This is a Claude Code security boundary that cannot be bypassed. After approving once, the hooks run automatically in all subsequent sessions.

Summary: "one approval then automatic" is the target. Fully zero-touch is not achievable (git-hook inheritance + trust prompt are hard constraints). If you want the git hook before the first Claude session, run kb plumbing (or init) once after cloning — i.e. python3 <path-to-skill>/scripts/kb.py plumbing (commonly .claude/skills/repo-wiki/scripts/kb.py). It installs plumbing only and is idempotent. The hook paths it writes are derived from the skill's actual install location, so they work regardless of where the skill lives; re-running plumbing also repairs a hook whose path went stale.

CLAUDE.md / AGENTS.md → thin shim

The instruction file mixes directives (do this) and knowledge (this is true). repo-wiki absorbs the knowledge; the file shrinks to a ~12-line shim: a minimal always-on pointer to the wiki plus the few universal/safety directives. Migrating an existing file is the same triage primitive run over a file instead of a chat. See references/claude-md-shim.md and assets/templates/shim.md.

Reference map

File Read it when
references/extraction.md the triage prompt — mining a chat + git diff into proposed pages
references/structure.md filing a page; setting up folders; the resolver + disambiguation
references/pages.md writing a page; frontmatter; the three-way freshness model
references/intake.md git + chat streams, watermarks, catchup, the vendored recall scripts
references/activation.md hooks, the SessionStart heartbeat, CI backstop, install discipline
references/bootstrap.md cold-starting a wiki in an existing repo — the 2-gate interactive flow
references/claude-md-shim.md migrating CLAUDE.md/AGENTS.md; what stays vs what moves
references/web.md kb serve — run instructions, API routes, architecture, security
references/comments.md wiki comments — passive hook, active watch loop, act-then-resolve consumption protocol

Honest limit

This skill guarantees detection, reconciliation, and prompting. It cannot force a human to author good knowledge — that judgment stays human. It surfaces the opportunity at near-zero cost (a git-scoped change applied in place) and makes ignoring it visible every session. Don't promise a fully-autonomous correct KB; the human reviews the committed diff and reverts what's wrong — the report-and-revert loop on significant writes is the check, not a pre-write gate.