decision-wiki
v0.1.1
Published
Decision ledger + per-module decision wiki + first-touch context injection for Claude Code projects. Self-contained; copy this directory into any repo.
Maintainers
Readme
decision-wiki
A decisions ledger, a per-module decision wiki generated from it, and two Claude Code hooks that push a module's decision context into the agent's context the first time a session edits that module. Plus a CI check that refuses changes to gated modules that record no reason.
Self-contained: this directory has its own package.json, lockfile, and prebuilt dist/. Copy
it anywhere. It imports nothing from a parent repository.
Built on Effect v4 (4.0.0-rc.112, pinned exactly). See SPEC.md for what must be true and
schema/ for the machine-readable contract.
Drop into a project
Published on npm as decision-wiki. From an empty project:
npx decision-wiki init --ci # writes config, hooks, wiki schema page, CLAUDE.md line, CI workflow
npx decision-wiki decide -s "…" -r "…" -m core
npx decision-wiki wiki generateWhen run from the npx cache the two hook bundles are copied into .claude/decision-wiki/ (so
hook paths survive cache pruning and clones) and the CI workflow invokes npx --yes
decision-wiki@<version> check. Commit .claude/decision-wiki/ with the rest.
Or copy the directory in and run the bundle directly:
# 1. copy this directory into the project (any location; kits/decision-wiki is conventional)
# 2. materialize the system
node kits/decision-wiki/dist/decision-wiki.mjs init --ci
# 3. edit .claude/decision-wiki.json: real module globs, gate the load-bearing ones
# 4. record the first decision and render
node kits/decision-wiki/dist/decision-wiki.mjs decide -s "…" -r "…" -m <module>
node kits/decision-wiki/dist/decision-wiki.mjs wiki generateinit writes .claude/decision-wiki.json, merges two hook entries into
.claude/settings.json (PostToolUse on Edit|Write|NotebookEdit, SessionStart), writes
docs/wiki/SCHEMA.md, creates the ledger directory, appends one line to CLAUDE.md, and with
--ci writes .github/workflows/decision-check.yml. Running it again changes nothing.
The prebuilt hooks need only Node 22+. No install is required to use the kit; npm ci is
needed only to change it.
Adopting an existing setup: init --from-surfaces <surfaces.json> --decisions-dir <dir>
--legacy-jsonl <file> seeds gated modules from a decision-surfaces map and reads an existing
one-file-per-row ledger plus its frozen JSONL as-is.
Commands
decision-wiki decide -s <statement> -r <rationale> [-e <evidence>]... [--reversal <c>]... [--supersedes <id>]... [-m <module|*>]...
decision-wiki list [--all] [--json]
decision-wiki wiki generate
decision-wiki wiki lint [--strict]
decision-wiki check [base] [head] # CI gate; exit 1 when a gated module changed with no appended row
decision-wiki init [--from-surfaces f] [--decisions-dir d] [--legacy-jsonl f] [--wiki-dir d] [--ci]
decision-wiki schema [out-dir] # render the contract to JSON SchemaEvery command accepts --root <dir> (default: CLAUDE_PROJECT_DIR, else the nearest
.claude/decision-wiki.json upward from cwd). Built-in --help, --version, --wizard
(interactive argument construction), --completions bash|zsh|fish, --log-level.
How the injection reads
First Edit/Write in a module this session:
--- docs/wiki/<module>.md (injected wholesale) ---
…the whole page, when it is at or under budgets.pageWholesaleBytes (4 KB) and fits the total (8 KB)…or, for a page over budget, the generated decisions block plus "Read docs/wiki/.md before proceeding". With no wiki generated yet, a list derived straight from the ledger. Never twice for the same (session, module). Never on Bash. Never blocking.
Layout
src/schema.ts the contract (Effect Schema); everything else derives from it
src/emit-schema.ts renders schema/*.json (tests fail on drift)
src/ledger.ts read-union + exclusive-create append; slug; supersession
src/config.ts .claude/decision-wiki.json loader; project-root resolution
src/glob.ts ** / * / ? matcher; path tokens in prose
src/associate.ts decision -> module (explicit, side-car, derived, global)
src/wiki.ts page + index rendering, hashes, lint
src/hooks.ts surface (first touch) + banner (session start)
src/hook-*.ts thin entrypoints (core-only imports, fail-safe)
src/check.ts git-range CI check
src/init.ts idempotent scaffolder
src/cli.ts the command tree (effect/unstable/cli)
scripts/build.mjs esbuild -> dist/ (CLI 1.0 MB, each hook 290 KB, minified)
test/ vitest 4 suite
schema/ generated JSON Schema documentsDevelop
npm ci
npm run typecheck && npm test && npm run build # or: npm run verify
npm run schema # re-render schema/ after changing src/schema.tsCommit dist/ after npm run build; drop-in users run the bundle, not the source. If a host
repository ignores dist/ globally, add !<kit>/dist/ and !<kit>/dist/*.mjs negations (this
repository does, in its root .gitignore).
Version notes
effect/unstable/cliis exempt from semver even after 4.0 stable. The exact pin and the committed bundle isolate users from that; bumping is a kit-maintainer task.- Known upcoming change in the next RC (on
mainas of 2026-09-05, unreleased):Configconstructors become PascalCase. The kit does not useConfigyet. @effect/vitest4.x requires vitest 4.x (not 5).
