Skip to content

Commit 82de402

Browse files
duyetduyetbot
andauthored
feat(kb,okf): add kb init skill and okf graph-viewer renderer (#80)
* feat(kb,okf): add kb init skill and okf graph-viewer renderer kb gains an `init` skill/command that scaffolds a self-contained, OKF v0.1-conformant shared-brain folder (AGENTS.md/DREAM.md/MEMORY.md, memory/, raw/inbox/, and a vendored bin/kb CLI) — idempotent, and never touches anything outside the target folder without explicit confirmation. okf gains render_okf_viewer.py: a generic self-contained HTML graph viewer for any OKF bundle, reading edges from related: frontmatter, [[wikilinks]], and OKF's own [text](path.md) markdown links. kb's scaffold vendors a copy so a generated kb keeps working standalone. Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com> * fix(scripts,kb): resolve ShellCheck failures blocking CI scripts/install-antigravity.sh: replace unquoted command-substitution array assignment (SC2207) with a portable read loop — avoids word splitting/globbing and stays bash 3.2 compatible (macOS default). kb/skills/init/templates/scripts/wire.sh: silence SC2088 with an explicit disable comment — the "~/kb" there is an intentional literal display string, not a path meant to expand. Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com> * fix(kb,okf): address review findings on render_okf_viewer and scripts render_okf_viewer.py (okf canonical + kb vendored copy, kept in sync): - Skip hidden directories (.git, .obsidian, .agent) when walking for concepts and when listing subdirs, so stray .md files and vault config never leak into the bundle or the graph. - Fix a dead-link bug: "Groups" links in a generated index.md could point at a child directory that itself had no concepts and no index.md. Recompute index-worthiness bottom-up so a directory is only linked if it (or a descendant) actually has content. - Warn (not silently corrupt) on duplicate slugs across directories, since build_bundle() uses the bare slug as the Cytoscape node id. - Read notes with utf-8-sig so a UTF-8 BOM doesn't break frontmatter parsing. - Escape text fields (label/type/description/tags/backlinks) before building the viewer's innerHTML, restrict the "source" link to http(s) URLs, and neutralize <, >, & in the embedded JSON bundle so a note's content can't break out of the <script> tag. Documented the remaining trust boundary: a concept's markdown body is still rendered via marked.parse unsanitized, same as opening a vault in Obsidian — this tool assumes the bundle itself is trusted content. kb templates: - sync.sh: don't swallow a failed rebase with `|| true` — a conflict must stop the script before it commits/pushes conflict markers. - bin/kb: quote the cron path (spaces in $KB_DIR), add an xdg-open fallback for `kb viz` on Linux. - wire.sh: `wire off` no longer creates a target file that didn't already exist. - AGENTS.md: fix the frontmatter example to include the `<type>-` prefix, matching the naming rule described just above it. - SKILL.md / README.md: markdownlint fixes (blank lines around a fenced block, language tag on the directory tree fence). Addresses review feedback from CodeRabbit and Gemini Code Assist on PR #80. Skipped: "open files without a context manager" (flagged low-value by the bot itself, not worth the churn on a short-lived CLI); full sanitization of rendered markdown body content (heavy lift, documented as an explicit trust boundary instead — see render_okf_viewer.py's module docstring). Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com> * style(kb,scripts): satisfy repo lint (shfmt, prettier, markdownlint) Reformat every shell script touched in this branch with shfmt (default style, matching the repo's Lint job) and every markdown file with prettier — whitespace/structure only, no behavior change. Also: - bin/kb: quote ${f#"$KB_DIR"/} per shellcheck SC2295. - AGENTS.md: fix the memory-types table's column alignment (MD060). Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com> --------- Co-authored-by: duyetbot <duyetbot@users.noreply.github.com>
1 parent 02773fb commit 82de402

26 files changed

Lines changed: 1727 additions & 70 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@
107107
{
108108
"name": "kb",
109109
"source": "./kb",
110-
"description": "Knowledge base maintenance skills. Consolidate, dedupe, prune, refresh, and forget notes in a markdown KB."
110+
"description": "Knowledge base maintenance skills. Initialize a shared-brain kb, then consolidate, dedupe, prune, refresh, and forget notes in a markdown KB."
111111
},
112112
{
113113
"name": "okf",
114114
"source": "./okf",
115-
"description": "Open Knowledge Format (OKF) tooling. Author, initialize, validate, and refactor knowledge into vendor-neutral OKF v0.1 bundles: markdown files with YAML frontmatter."
115+
"description": "Open Knowledge Format (OKF) tooling. Author, initialize, validate, render, and refactor knowledge into vendor-neutral OKF v0.1 bundles: markdown files with YAML frontmatter."
116116
},
117117
{
118118
"name": "unsloth-training",

kb/.claude-plugin/plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "kb",
3-
"version": "1.0.1",
4-
"description": "Knowledge base maintenance skills. Consolidate, dedupe, prune, refresh, and forget notes in a markdown KB.",
3+
"version": "1.1.0",
4+
"description": "Knowledge base maintenance skills. Initialize a shared-brain kb, then consolidate, dedupe, prune, refresh, and forget notes in a markdown KB.",
55
"author": {
66
"name": "duyet",
77
"url": "https://github.com/duyet"

kb/.codex-plugin/plugin.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "kb",
3-
"version": "1.0.1",
4-
"description": "Knowledge base maintenance skills. Consolidate, dedupe, prune, refresh, and forget notes in a markdown KB.",
3+
"version": "1.1.0",
4+
"description": "Knowledge base maintenance skills. Initialize a shared-brain kb, then consolidate, dedupe, prune, refresh, and forget notes in a markdown KB.",
55
"author": {
66
"name": "duyet"
77
},
88
"skills": "./skills/",
99
"commands": "./commands/",
1010
"interface": {
1111
"displayName": "Knowledge Base",
12-
"shortDescription": "Maintain a markdown knowledge base: consolidate, dedupe, prune, and forget notes.",
12+
"shortDescription": "Initialize and maintain a markdown knowledge base: consolidate, dedupe, prune, and forget notes.",
1313
"developerName": "duyet",
1414
"category": "productivity",
1515
"capabilities": ["Skill", "Command"],

kb/README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ markdown knowledge base via a path argument or the `$KB_DIR` environment variabl
55

66
## Skills
77

8+
- **init** — scaffold a brand-new shared-brain kb folder (default `~/kb`): the
9+
memory protocol (`AGENTS.md`/`CLAUDE.md`/`DREAM.md`/`MEMORY.md`), an OKF v0.1
10+
`memory/` bundle, a capture inbox, and a self-contained CLI (`bin/kb`,
11+
`scripts/render_okf_viewer.py` for the graph viewer, `lint.sh`, `sync.sh`,
12+
`wire.sh`). Idempotent; never overwrites existing files; never edits anything
13+
outside the target folder without asking first.
814
- **dream** — the consolidation pass. Merges near-duplicate notes, flags contradictions,
915
prunes stale/low-value notes, ingests inbox captures, refreshes notes from their
1016
source URLs, splits multi-fact notes, relinks/retags, and rebuilds the index. Shows a
@@ -20,11 +26,17 @@ markdown knowledge base via a path argument or the `$KB_DIR` environment variabl
2026
## Usage
2127

2228
```bash
23-
dream ./docs/kb # consolidate a KB (interactive, diff-for-approval)
24-
dream $KB_DIR --auto # non-interactive; merges/prunes, skips contradictions
25-
dream forget "old server" # propose deleting notes matching a query
29+
init # scaffold a new shared-brain kb at ~/kb (or $KB_DIR)
30+
init ~/kb # scaffold at an explicit path
31+
32+
dream ./docs/kb # consolidate a KB (interactive, diff-for-approval)
33+
dream $KB_DIR --auto # non-interactive; merges/prunes, skips contradictions
34+
dream forget "old server" # propose deleting notes matching a query
2635
```
2736

2837
The KB is any directory of `*.md` notes with YAML frontmatter (`name`, `type`, `tags`,
2938
`created`, `updated`, optional `pinned`/`confidence`/`sources`), optionally with a
30-
`MEMORY.md` index, a `raw/inbox/` of captures, and `raw/` source docs.
39+
`MEMORY.md` index, a `raw/inbox/` of captures, and `raw/` source docs — exactly what
40+
`init` scaffolds. It is also a conformant [OKF v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
41+
bundle; see the companion **okf** plugin for deeper bundle authoring, validation, and
42+
graph-viewer rendering.

kb/commands/init.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
description: Scaffold a new shared-brain knowledge base folder (default ~/kb) — OKF v0.1-conformant, with a graph viewer and its own CLI, vendored and self-contained.
3+
---
4+
5+
# /init
6+
7+
Scaffold a new shared-brain kb folder: memory protocol (`AGENTS.md`/`CLAUDE.md`/
8+
`DREAM.md`/`MEMORY.md`), an OKF v0.1 `memory/` bundle, a capture inbox
9+
(`raw/inbox/`), and a self-contained CLI (`bin/kb`, `scripts/`). Delegate to the
10+
`init` skill for the full scaffold. Idempotent — never overwrites existing files.
11+
12+
## Arguments
13+
14+
- `path`: target directory (optional; defaults to `$KB_DIR` or `~/kb`)
15+
16+
Pass the rest of the line as `$ARGUMENTS`. Examples: `/init`, `/init ~/kb`,
17+
`/init ./team-kb`.
18+
19+
## Workflow
20+
21+
1. Resolve the target path from `$ARGUMENTS`, `$KB_DIR`, or the default `~/kb`;
22+
confirm with the user if ambiguous.
23+
2. Invoke the `init` skill and follow its steps exactly.
24+
3. Report files created vs. skipped (pre-existing).
25+
4. Offer PATH export, `git init`, and `scripts/wire.sh on` as separate,
26+
confirm-first follow-ups — never run them without asking, since wiring
27+
edits global agent config outside the scaffolded folder.
28+
29+
## Guardrails
30+
31+
- Never overwrite a file that already exists in the target.
32+
- Never touch anything outside the target folder without explicit confirmation.
33+
- Never invent personal facts to seed `memory/` with — leave it for the user.
34+
- Keep this command thin — all scaffolding logic lives in the `init` skill.

kb/skills/init/SKILL.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
name: init
3+
description: Scaffold a new shared-brain knowledge base folder (default ~/kb) — a plain-markdown, OKF v0.1-conformant memory store that any coding agent can read/write across sessions. Use when the user asks to set up, init, or bootstrap a kb / shared brain / persistent agent memory folder, or wants an OKF bundle with a graph viewer ready out of the box.
4+
---
5+
6+
# init — scaffold a shared-brain kb folder
7+
8+
## What this creates
9+
10+
A self-contained directory — plain markdown, no database, no server — that is:
11+
12+
- **A memory protocol.** `AGENTS.md` (the full read/write/dream rules), `CLAUDE.md`
13+
(thin pointer for Claude Code), `DREAM.md` (the consolidation pass), `MEMORY.md`
14+
(the index every agent reads first).
15+
- **An OKF v0.1 bundle.** `memory/` is the bundle root; every note is one `.md`
16+
file with a `type` in frontmatter. Conforms to
17+
[OKF v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
18+
— see the companion **okf** skill/plugin for deeper bundle authoring and
19+
validation.
20+
- **A capture inbox.** `raw/inbox/` for low-ceremony daily notes; `raw/` for
21+
immutable source docs.
22+
- **Its own CLI and tooling**, vendored into `scripts/`/`bin/` so the folder
23+
keeps working even if this Claude plugin is later removed: `bin/kb`
24+
(capture/lint/sync/gen/viz/wire), `scripts/render_okf_viewer.py` (regenerates
25+
`memory/**/index.md` + a self-contained `viz.html` graph viewer), `scripts/
26+
lint.sh`, `scripts/sync.sh`, `scripts/wire.sh`.
27+
28+
This is the generic, brand-neutral form of a personal "shared brain" pattern —
29+
it ships with no memory content, no assumed git remote, and no personal
30+
branding. Everything it writes is a template for the user to fill in.
31+
32+
## When to use
33+
34+
- "set up a kb / shared brain / persistent memory folder for me"
35+
- "init ~/kb" or "bootstrap my knowledge base"
36+
- The user wants cross-session, cross-agent memory but has none yet.
37+
38+
If a kb already exists at the target (has `AGENTS.md` or `memory/`), this skill
39+
is still safe to run — see Idempotency below — but check first whether the user
40+
actually wants `dream` (consolidate existing notes) instead of `init`.
41+
42+
## Steps
43+
44+
1. **Resolve the target path.** Default `$HOME/kb`. Use `$KB_DIR` if set, or a
45+
path the user gave explicitly. Confirm the path with the user if ambiguous.
46+
2. **Scaffold.** Run the bundled script with an absolute path (it does not
47+
expand `~`):
48+
49+
```bash
50+
bash "${CLAUDE_PLUGIN_ROOT}/skills/init/scripts/scaffold.sh" "$HOME/kb"
51+
```
52+
53+
It is idempotent — creates missing files, chmods scripts executable, seeds
54+
starter `memory/{user,feedback,reference,projects,topics}/` groups, and
55+
**never overwrites a file that already exists** in the target. It ends by
56+
running `render_okf_viewer.py` once so `memory/index.md` and `viz.html`
57+
exist immediately.
58+
59+
3. **Report what happened**: how many files were created vs. skipped
60+
(pre-existing), and the target path.
61+
4. **Offer, but do not run automatically, three follow-ups** — each changes
62+
something outside the new folder or is otherwise consequential, so ask
63+
first:
64+
- **PATH.** Suggest adding `export PATH="<target>/bin:$PATH"` to the user's
65+
shell rc. Don't edit their `.zshrc`/`.bashrc` yourself unless they ask.
66+
- **Version control.** Offer `git init` (and `git remote add origin <url>`
67+
if they have one). Skip silently if they don't want git.
68+
- **Wiring.** `<target>/scripts/wire.sh on` adds a small marked block to
69+
`~/.claude/CLAUDE.md` (and `~/.codex/AGENTS.md` / `~/.config/opencode/
70+
AGENTS.md` if those tools are present) so every future session
71+
auto-reads the kb. This edits files **outside** the scaffolded folder and
72+
affects every future session — explain what it does and get explicit
73+
confirmation before running it. `wire.sh off` cleanly reverses it.
74+
5. **If the user wants example notes**, don't invent personal facts — either
75+
leave `memory/` empty for them to fill in via `kb capture`, or ask what to
76+
record.
77+
78+
## After scaffolding
79+
80+
- Point to `memory/_TEMPLATE.md` for the note format and `AGENTS.md` for the
81+
full protocol — both are self-documenting inside the new folder.
82+
- For ongoing maintenance (merge duplicates, prune stale notes, rebuild the
83+
index), use this plugin's **dream** skill against the new kb.
84+
- For richer OKF authoring/validation beyond what `bin/kb gen` covers (custom
85+
concept types, `validate_okf.py` conformance checks), use the **okf** plugin.
86+
- `kb viz` (or `bin/kb viz` before `PATH` is set) opens the graph viewer any
87+
time after notes are added.
88+
89+
## Idempotency & safety
90+
91+
- `scaffold.sh` only ever creates files that don't already exist — re-running
92+
it against a partially-set-up or already-populated kb is safe and adds
93+
nothing to files it finds present.
94+
- It never touches anything outside `<target>` — no global config, no shell
95+
rc, no git remote. Those are the explicit, confirm-first follow-ups above.
96+
- It writes no personal data — the scaffolded files are generic templates.
97+
98+
## Checklist
99+
100+
- [ ] Resolved target path (arg, `$KB_DIR`, or confirmed default `~/kb`).
101+
- [ ] Ran `scaffold.sh` with an absolute path; reported created vs. skipped files.
102+
- [ ] `memory/index.md` and `viz.html` exist (scaffold.sh generates them).
103+
- [ ] Offered PATH / git init / wire as separate, confirm-first steps — did not
104+
edit anything outside the target folder without asking.
105+
- [ ] Did not invent personal facts to seed `memory/` with.

kb/skills/init/scripts/scaffold.sh

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env bash
2+
# Scaffold a new shared-brain kb folder at <target> (default: ~/kb).
3+
# Idempotent: never overwrites a file that already exists in <target>, so it's
4+
# safe to re-run against a kb that's already partially set up. Does NOT run
5+
# git init, does NOT touch any file outside <target> (wiring is a separate,
6+
# explicit step — see scripts/wire.sh in the scaffolded folder).
7+
set -euo pipefail
8+
9+
TEMPLATES="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/../templates" && pwd)"
10+
TARGET="${1:-$HOME/kb}" # pass an absolute path; this script does not expand ~
11+
12+
created=() skipped=()
13+
14+
put() { # put <src-relative-to-templates> <dest-relative-to-target>
15+
local src="$TEMPLATES/$1" dest="$TARGET/$2"
16+
mkdir -p "$(dirname "$dest")"
17+
if [[ -e "$dest" ]]; then
18+
skipped+=("$2")
19+
return
20+
fi
21+
cp "$src" "$dest"
22+
created+=("$2")
23+
}
24+
25+
mkdir -p "$TARGET"
26+
27+
put "AGENTS.md" "AGENTS.md"
28+
put "CLAUDE.md" "CLAUDE.md"
29+
put "DREAM.md" "DREAM.md"
30+
put "README.md" "README.md"
31+
put "gitignore" ".gitignore"
32+
put "memory/_TEMPLATE.md" "memory/_TEMPLATE.md"
33+
put "raw/README.md" "raw/README.md"
34+
put "scripts/lint.sh" "scripts/lint.sh"
35+
put "scripts/sync.sh" "scripts/sync.sh"
36+
put "scripts/wire.sh" "scripts/wire.sh"
37+
put "scripts/render_okf_viewer.py" "scripts/render_okf_viewer.py"
38+
put "bin/kb" "bin/kb"
39+
chmod +x "$TARGET"/scripts/*.sh "$TARGET/bin/kb" 2>/dev/null || true
40+
41+
# Starter memory groups + inbox — empty dirs need a placeholder to survive git.
42+
for d in memory/user memory/feedback memory/reference memory/projects memory/topics raw/inbox; do
43+
mkdir -p "$TARGET/$d"
44+
[[ -e "$TARGET/$d/.gitkeep" ]] || {
45+
: >"$TARGET/$d/.gitkeep"
46+
created+=("$d/.gitkeep")
47+
}
48+
done
49+
50+
if [[ ! -e "$TARGET/.agent/state.json" ]]; then
51+
mkdir -p "$TARGET/.agent"
52+
printf '{}\n' >"$TARGET/.agent/state.json"
53+
created+=(".agent/state.json")
54+
fi
55+
56+
if [[ ! -e "$TARGET/MEMORY.md" ]]; then
57+
cat >"$TARGET/MEMORY.md" <<'EOF'
58+
# Memory Index
59+
60+
Master table of contents. One line per note — read this first, then open only
61+
the notes relevant to your task. See `AGENTS.md` for the protocol.
62+
63+
(No notes yet — this index is rebuilt by hand or by a `DREAM.md` pass as notes
64+
are added under `memory/`.)
65+
EOF
66+
created+=("MEMORY.md")
67+
fi
68+
69+
# Initial OKF index.md + viz.html so the bundle is immediately browsable.
70+
python3 "$TARGET/scripts/render_okf_viewer.py" "$TARGET/memory" \
71+
--title "$(basename "$TARGET")" --out "$TARGET/viz.html" >/dev/null
72+
73+
echo "kb scaffolded at $TARGET"
74+
echo " created: ${#created[@]} file(s)"
75+
[[ ${#skipped[@]} -gt 0 ]] && echo " skipped (already existed): ${skipped[*]}"
76+
echo
77+
echo "next steps:"
78+
echo " export PATH=\"$TARGET/bin:\$PATH\" # add to your shell rc"
79+
echo " cd $TARGET && git init # optional: version control"
80+
echo " $TARGET/scripts/wire.sh on # optional: wire the reflex into agents' global config (ask the user first — it edits files outside this folder)"

0 commit comments

Comments
 (0)