okf-wiki: scaffold an Open Knowledge Format knowledge base
OKF (Open Knowledge Format) stores knowledge as small markdown files: one concept per
file, each carrying its own provenance in YAML frontmatter, with directory index.md
files for navigation and a validator that enforces the contract. It is built for
knowledge bases that both people and agents read and edit, newsroom institutional
memory, a research atlas, a team's decision log, an infrastructure map.
This skill scaffolds a conforming OKF project and validates it. The format contract is
in spec/SPEC.md (in this skill's directory), read it before changing structure.
When to use
- The user wants to start an OKF knowledge base, atlas, or wiki.
- They want docs structured as one-concept-per-file with provenance, not prose pages.
- They want to "initialize OKF" in a repo, optionally publishing into its GitHub wiki.
Start here: scope the wiki with the user
Before you scaffold anything, settle four things with the user. They shape what gets created and
how it is published, and they are awkward to retrofit once concepts exist. Ask with AskUserQuestion
rather than in prose, in two steps: the first three questions in one call, then the publish question
as a follow-up call only if the audience came back public or both (it does not apply to an
internal-only wiki, and its relevant options depend on that answer, so it cannot share the first
batch). Infer the title from the repo or project and confirm it. Skip any question the user already
answered in their request, do not re-ask what they have told you.
- Audience, who reads this wiki? This answer sets the others:
- Internal (agents and teammates): the orientation hooks earn their keep, so keep them on.
The bundle may hold infrastructure detail, so it usually lives in a private repo. The in-repo
bundle/ is the source of truth.
- Public (people browsing): readability and secret-scrubbing come first; the hooks matter
less, since people read it and agents do not. Plan a published view (see Publish below).
- Both: the in-repo
bundle/ is the source of truth with hooks on for agents, plus a
published view for people. Default here when the user is unsure.
- Title and sections, the knowledge-base title (infer it, then confirm) and the starting
sections. Offer sections as a use-case preset, not a blank prompt:
- Newsroom institutional memory:
people, orgs, sources, decisions, beats
- Research atlas:
concepts, sources, methods, findings
- Infrastructure or fleet map:
machines, services, networks, credentials, processes
- Decision log:
decisions, context, events
The chosen title and list feed --title and --sections below; the user can edit the list.
- Populate now or later, author concepts now from existing material (a repo, docs, notes, or a
URL: gather it and enter the authoring loop after scaffolding), or scaffold an empty tree the user
fills in later.
- Publish target, a follow-up
AskUserQuestion call, made only after the audience comes back
public or both (skip it entirely for an internal-only wiki):
- In-repo bundle only (default): the validator and relative links work directly, with no
extra surface to maintain. Right for most wikis.
- GitHub wiki: an optional reading surface. Advanced and manual, see "Optional: publish into
a GitHub wiki" below, bootstrapped with
scripts/gh-wiki-bootstrap.py.
- GitHub Pages: a browsable site rendered from the bundle. Not built yet, treat it as a
goal and keep the in-repo bundle as the source of truth.
Carry the answers into the scaffold command (the title and sections, plus --no-hooks if the user
opts out of the hooks for a public-only wiki) and into the populate step. The audience answer is
also the visibility decision the "Before finishing" section asks you to make deliberately, you are
making it here, up front, where it can steer the rest of the setup.
What gets created
scripts/scaffold.py writes a project that passes its own validator by construction:
<target>/
SPEC.md the OKF format contract
README.md how to use and validate the bundle
scripts/validate.py the validator
.claude/ Claude Code adapter: session-orientation hooks
settings.json registers the hooks (Claude Code approves them once)
hooks/okf-anchor.py SessionStart: load the index into context
hooks/okf-orient.py PreToolUse: gate the first action on orientation
bundle/ the OKF bundle (the validated tree)
index.md carries okf_version: "0.3" by default; "0.4" with --trust-signals
<section>/
index.md
example-concept.md a starter concept with full frontmatter
Docs and tooling sit at the project root; only bundle/ is validated. Keep them
separate, the validator treats every non-reserved .md inside the bundle as a
concept that needs frontmatter, so a stray SPEC.md inside bundle/ would fail.
The .claude/ hooks sit outside bundle/, so they never trip the concept checks.
How to run it
${CLAUDE_SKILL_DIR} below is this skill's own directory (the folder holding this
SKILL.md). Claude Code substitutes it with the real absolute path before you run the
command, so it works regardless of the current directory. On Windows, use python instead
of python3 (stock Windows has no python3). The --title and --sections come from the
onboarding answers above, and --no-hooks only if the user opted out. Scaffold into a new
directory; it validates automatically at the end:
python3 "${CLAUDE_SKILL_DIR}/scripts/scaffold.py" ./my-knowledge-base \
--title "Team knowledge base" \
--sections concepts,services,decisions
Default section is concepts. Use --force to write into a non-empty directory,
--no-validate to skip the validation run, and --date YYYY-MM-DD to set the sample
frontmatter date. The session hooks are written by default; --no-hooks skips them and
--hooks-os posix|windows overrides the auto-detected launch command (see below).
Validate any time, from the scaffolded project root (use python on Windows):
python3 scripts/validate.py --bundle bundle # must exit 0
Populate the bundle: author concepts from existing material
Scaffolding leaves an empty tree with one placeholder concept. The usual next request,
"here are my docs / plans / notes / repo, build the wiki", has no importer script, and
can't have one: deciding what counts as a single concept, writing its one-line description,
choosing its type, and pointing source at real provenance is judgment work, not a
mechanical transform. So you (Claude) author the concepts directly, in this loop:
- Gather the source. Read what the user pointed you at, a file, a folder, a repo, or a
URL (fetch a URL first). Skim the whole thing before writing anything, so you can see the
natural concept boundaries.
- Decide concept boundaries. One file is one concept: one thing a reader would look up on
its own (a service, a decision, a path, a person, an event). Split a doc that covers five
things into five concepts; merge fragments that only mean something together into one. A
heading is a hint, not a rule, do not blindly map one
## to one file.
- Draft each concept at
bundle/<section>/<slug>.md with the full frontmatter. Read the
bundle-root index.md before writing so the verification key matches its declared format:
use verified for okf_version 0.1 through 0.3; use verified_on for okf_version 0.4.
Emit that exact key with type, title, description, source, timestamp, tags:
type from the vocab. Infrastructure: Machine, Network, Service, Session, Project,
Repo, Credential, Path, Process. Domain-neutral: Concept, Decision, Event, Person,
Org, Source. Plus Reference (the catch-all). The set is closed; an unlisted type fails.
description is one line. source, quote every element, points at where the fact
actually came from (the origin file path, URL, command, or event), not at this skill.
- Set
timestamp to today. verified/verified_on is the date the fact was last confirmed
true, set it by how you came to know it, not reflexively to today:
- You re-checked it against reality now, or the user is the authority for it (a decision,
preference, or intent they state in this session): today.
- The user is recalling external or system state (a spec, a path, a config): their memory is a
source claim, not a re-check, so date it to when that state was last checked or to the
recollection's own date, not today just because it came up now.
- It was copied from a dated source without re-checking: the date it was last known true (the
source's own date), not today.
- It came from an undated record you cannot re-confirm (a memory file, an old conversation):
the oldest date you can evidence, file timestamp, introducing commit, or the date it was
said, never today. If you cannot evidence any date at all, it is not yet a verifiable fact;
find a datable source or leave the concept out.
When the date is uncertain, round it down: an older
verified correctly reads as "may be
stale, re-check," while today reads as "just confirmed." The frontmatter date is the contract;
a caveat in the body does not undo an overstated value, because the validator and tools read
only the date.
- Strip secret values as you go: a credential concept names the key and its retrieval path,
never the value. The validator fails the build on a leaked secret.
- Place and link. Put each concept in the right section (create sections as needed), add a
bullet for it to that section's
index.md, and cross-link related concepts with relative
[text](path.md) links, not [[slug]] wikilinks. [[slug]] is the auto-memory idiom; the
OKF validator rejects it and never resolves it, so a typo'd or deleted reference passes silently.
When you create a new section, also link it from the bundle-root index.md, that root is the
navigation map the session anchor loads, so a section missing from it is invisible to orientation
even though validation still passes.
- Clear the placeholder. If you scaffolded fresh, delete the starter
example-concept.md (and
its bullet in the section index.md) once real concepts exist, otherwise the sample ships in
the finished wiki and still passes validation.
- Validate in a loop. Run
python3 scripts/validate.py --bundle bundle, fix what it
reports, repeat until it exits 0. Unquoted source elements and missing frontmatter keys are
the common failures. Author in batches and validate between them rather than writing fifty
files and debugging the lot.
When the source is already OKF
If the user points you at an existing OKF bundle (e.g. an upstream example: an index.md
carrying okf_version plus concept files with frontmatter), you are adopting it, not importing
it. Copy or clone the tree in, point the validator at the new root, and fix any links that broke
in the move. To keep it as its own area beside other content, give it a uniquely named top
directory, then create one combined-root index.md that carries okf_version and strip the
frontmatter from each adopted bundle's own root index.md, turning it into a normal section index
(the validator allows okf_version on the one combined root only; a nested index.md that still
carries it fails validation). Write cross-links as relative paths and validate the combined root.
Re-authoring an already-conforming bundle into your own concepts is wasted work; only reshape it if
that is the actual goal.
The format, briefly
Full contract in spec/SPEC.md. This spec is a strict fork of Google's upstream OKF: it
requires all seven frontmatter keys, uses a source list in place of upstream's resource
and # Citations, adds a verification-date key, closes the type vocab, and enforces link
resolution. spec/SPEC.md ("Relationship to upstream OKF") lists every difference. The
load-bearing rules:
- Required frontmatter on every concept:
type, title, description, source, the
version-specific verification key described above, timestamp, tags. type is one of:
Machine, Network, Service, Session, Project, Repo, Credential, Path, Process
(infrastructure); Concept, Decision, Event, Person, Org, Source (domain-neutral); or
Reference (catch-all).
- Quote every
source element, source pointers carry # and : which break YAML
if unquoted. source: ["README.md", "issue #445"].
verified/verified_on is the date the fact was last confirmed true, a re-check
against reality, or the user stating a fact they are the authority for (a decision, a
preference); a fact they merely recall about external state is a source claim, not a
re-check. timestamp is when the concept was authored/updated. The verification date is
ISO YYYY-MM-DD; timestamp may also be a full ISO 8601 datetime in 0.3 and 0.4. See
the authoring loop above for the full date rules.
- No secret values, ever. A credential concept documents the key name and retrieval
path, never the value. The validator fails the build on a leaked secret.
index.md and log.md are reserved, no frontmatter (except the bundle-root
index.md, which carries okf_version only).
Optional: upstream v0.2 trust/provenance signals
Upstream Google OKF v0.2 (July 2026) added an optional vocabulary for a consumer to judge a
concept before reading it: generated (who/what produced it), verified (a list of
independent confirmations, not this fork's own single-date field), sources (structured,
per-pointer credibility signals), status (draft/stable/deprecated), stale_after (an
absolute expiry date), and an Attested Computation type for a sanctioned, checkable
computation. None of it is required, and a bundle that adopts none of it is unaffected.
Scaffold a project with these enabled, scaffold.py <target> --trust-signals, and the
bundle declares okf_version: "0.4", with verified renamed to verified_on in the
required set (freeing verified for the new shape; see spec/SPEC.md's "Trust and
provenance" section for the full field contract and the reasoning behind the rename).
Attested Computation is likewise a 0.4-only type. Without the flag, scaffolding is
unchanged from before this vocabulary existed.
Session hooks
A scaffolded project ships a .claude/ with two hooks so any Claude session opened in it
starts from the bundle, not from memory:
okf-anchor.py (SessionStart) prints the bundle's root index into the session context.
okf-orient.py (PreToolUse, no matcher) blocks the first action of the session once,
until Claude confirms it read the index, then unblocks for the rest of the session. It is
inert outside an OKF bundle and fails open on any error, so it never wedges a session.
Both are one cross-platform python3 script. The scripts are identical on every OS; only the
interpreter in .claude/settings.json changes: python3 on macOS/Linux, python on
Windows. scaffold.py auto-detects the OS; --hooks-os posix|windows forces it.
Claude Code treats a checked-in .claude/settings.json as untrusted, so the first time the
project is opened it asks the user to approve the hooks; they run automatically after that.
To turn them off, scaffold with --no-hooks, or delete .claude/ (or set disableAllHooks)
in an existing project.
Client boundary
The portable OKF surface is SPEC.md, requirements.txt, scripts/validate.py, and the
bundle/ tree. The generated README.md documents both that shared surface and any enabled
client adapter. The three generated .claude/ files are a Claude Code adapter, not part of
the OKF format and not shared Codex behavior. Codex does not read them as project configuration,
and this skill must not claim that their SessionStart or PreToolUse lifecycle runs there.
The general onboarding route above still names Claude Code's AskUserQuestion and
${CLAUDE_SKILL_DIR} surfaces. The recorded Codex pilot pre-set every onboarding choice and
used an explicit project-relative installed path; it does not establish that the unadapted
general route is portable.
For a mixed Claude Code and Codex project, keep .claude/ so Claude Code can request trust
and use the hooks; Codex leaves it inert. For a Codex-only project, pass --no-hooks while
scaffolding or delete .claude/ afterward. Either choice leaves the portable bundle and
validator unchanged.
Optional: publish into a GitHub wiki
OKF lives best as in-repo files (the validator and relative links work directly). A repo's
GitHub wiki is an optional reading surface, and wiring it up is an advanced, manual step,
most users should skip it and keep the bundle in-repo.
A wiki with zero pages has no git repo to push to and no API, so the very first page must be
created through the web UI. scripts/gh-wiki-bootstrap.py automates that one step, but it
drives a real logged-in browser, so it needs two things you provide yourself (a GitHub PAT
does not work, wiki pages are a web-UI-only surface):
- Playwright with Chromium installed:
pip install playwright && playwright install chromium.
- A saved GitHub web session: a Playwright
storageState JSON, captured from a browser
where you have already logged into GitHub. The script reuses that session; it does not log
in for you. Pass its path with --state (default: ~/.cache/gh_state.json).
python3 "${CLAUDE_SKILL_DIR}/scripts/gh-wiki-bootstrap.py" owner/repo --state path/to/gh_state.json
# then: git clone https://github.com/owner/repo.wiki.git and push your pages
Note the impedance: GitHub wikis are flatter than an OKF tree and use [[WikiLinks]], so
OKF's nested directories and relative links need adapting for the wiki surface. Treat the
wiki as a published view, not the source of truth. (v0.1 ships the bootstrap step; an
automatic bundle-to-wiki sync is not built yet.)
Before finishing
- Run the validator and confirm it exits 0.
- Confirm the visibility you set during onboarding still fits what got authored: a bundle that
ended up documenting real infrastructure is usually internal. OKF takes no position; you must.
1---2name: okf-wiki3description: Builds an Open Knowledge Format (OKF) knowledge base from existing docs, notes, or a repo. Use to scaffold an OKF wiki.4license: MIT5---6
7# okf-wiki: scaffold an Open Knowledge Format knowledge base
8
9OKF (Open Knowledge Format) stores knowledge as small markdown files: one concept per
10file, each carrying its own provenance in YAML frontmatter, with directory `index.md`
11files for navigation and a validator that enforces the contract. It is built for
12knowledge bases that both people and agents read and edit, newsroom institutional
13memory, a research atlas, a team's decision log, an infrastructure map.
14
15This skill scaffolds a conforming OKF project and validates it. The format contract is
16in `spec/SPEC.md` (in this skill's directory), read it before changing structure.
17
18## When to use
19
20- The user wants to start an OKF knowledge base, atlas, or wiki.
21- They want docs structured as one-concept-per-file with provenance, not prose pages.
22- They want to "initialize OKF" in a repo, optionally publishing into its GitHub wiki.
23
24## Start here: scope the wiki with the user
25
26Before you scaffold anything, settle four things with the user. They shape what gets created and
27how it is published, and they are awkward to retrofit once concepts exist. Ask with `AskUserQuestion`
28rather than in prose, in two steps: the first three questions in one call, then the publish question
29as a follow-up call only if the audience came back public or both (it does not apply to an
30internal-only wiki, and its relevant options depend on that answer, so it cannot share the first
31batch). Infer the title from the repo or project and confirm it. Skip any question the user already
32answered in their request, do not re-ask what they have told you.
33
341. **Audience**, who reads this wiki? This answer sets the others:
35 - **Internal (agents and teammates):** the orientation hooks earn their keep, so keep them on.
36 The bundle may hold infrastructure detail, so it usually lives in a private repo. The in-repo
37 `bundle/` is the source of truth.
38 - **Public (people browsing):** readability and secret-scrubbing come first; the hooks matter
39 less, since people read it and agents do not. Plan a published view (see Publish below).
40 - **Both:** the in-repo `bundle/` is the source of truth with hooks on for agents, plus a
41 published view for people. Default here when the user is unsure.
422. **Title and sections**, the knowledge-base title (infer it, then confirm) and the starting
43 sections. Offer sections as a use-case preset, not a blank prompt:
44 - Newsroom institutional memory: `people, orgs, sources, decisions, beats`
45 - Research atlas: `concepts, sources, methods, findings`
46 - Infrastructure or fleet map: `machines, services, networks, credentials, processes`
47 - Decision log: `decisions, context, events`
48 The chosen title and list feed `--title` and `--sections` below; the user can edit the list.
493. **Populate now or later**, author concepts now from existing material (a repo, docs, notes, or a
50 URL: gather it and enter the authoring loop after scaffolding), or scaffold an empty tree the user
51 fills in later.
524. **Publish target**, a follow-up `AskUserQuestion` call, made only after the audience comes back
53 public or both (skip it entirely for an internal-only wiki):
54 - **In-repo bundle only (default):** the validator and relative links work directly, with no
55 extra surface to maintain. Right for most wikis.
56 - **GitHub wiki:** an optional reading surface. Advanced and manual, see "Optional: publish into
57 a GitHub wiki" below, bootstrapped with `scripts/gh-wiki-bootstrap.py`.
58 - **GitHub Pages:** a browsable site rendered from the bundle. Not built yet, treat it as a
59 goal and keep the in-repo bundle as the source of truth.
60
61Carry the answers into the scaffold command (the title and sections, plus `--no-hooks` if the user
62opts out of the hooks for a public-only wiki) and into the populate step. The audience answer is
63also the visibility decision the "Before finishing" section asks you to make deliberately, you are
64making it here, up front, where it can steer the rest of the setup.
65
66## What gets created
67
68`scripts/scaffold.py` writes a project that passes its own validator by construction:
69
70```
71<target>/
72 SPEC.md the OKF format contract
73 README.md how to use and validate the bundle
74 scripts/validate.py the validator
75 .claude/ Claude Code adapter: session-orientation hooks
76 settings.json registers the hooks (Claude Code approves them once)
77 hooks/okf-anchor.py SessionStart: load the index into context
78 hooks/okf-orient.py PreToolUse: gate the first action on orientation
79 bundle/ the OKF bundle (the validated tree)
80 index.md carries okf_version: "0.3" by default; "0.4" with --trust-signals
81 <section>/
82 index.md
83 example-concept.md a starter concept with full frontmatter
84```
85
86Docs and tooling sit at the project root; only `bundle/` is validated. Keep them
87separate, the validator treats every non-reserved `.md` inside the bundle as a
88concept that needs frontmatter, so a stray `SPEC.md` inside `bundle/` would fail.
89The `.claude/` hooks sit outside `bundle/`, so they never trip the concept checks.
90
91## How to run it
92
93`${CLAUDE_SKILL_DIR}` below is this skill's own directory (the folder holding this
94`SKILL.md`). Claude Code substitutes it with the real absolute path before you run the
95command, so it works regardless of the current directory. On Windows, use `python` instead
96of `python3` (stock Windows has no `python3`). The `--title` and `--sections` come from the
97onboarding answers above, and `--no-hooks` only if the user opted out. Scaffold into a new
98directory; it validates automatically at the end:
99
100```bash
101python3 "${CLAUDE_SKILL_DIR}/scripts/scaffold.py" ./my-knowledge-base \
102 --title "Team knowledge base" \
103 --sections concepts,services,decisions
104```
105
106Default section is `concepts`. Use `--force` to write into a non-empty directory,
107`--no-validate` to skip the validation run, and `--date YYYY-MM-DD` to set the sample
108frontmatter date. The session hooks are written by default; `--no-hooks` skips them and
109`--hooks-os posix|windows` overrides the auto-detected launch command (see below).
110
111Validate any time, from the scaffolded project root (use `python` on Windows):
112
113```bash
114python3 scripts/validate.py --bundle bundle # must exit 0
115```
116
117## Populate the bundle: author concepts from existing material
118
119Scaffolding leaves an empty tree with one placeholder concept. The usual next request,
120"here are my docs / plans / notes / repo, build the wiki", has no importer script, and
121can't have one: deciding what counts as a single concept, writing its one-line description,
122choosing its `type`, and pointing `source` at real provenance is judgment work, not a
123mechanical transform. So you (Claude) author the concepts directly, in this loop:
124
1251. **Gather the source.** Read what the user pointed you at, a file, a folder, a repo, or a
126 URL (fetch a URL first). Skim the whole thing before writing anything, so you can see the
127 natural concept boundaries.
1282. **Decide concept boundaries.** One file is one concept: one thing a reader would look up on
129 its own (a service, a decision, a path, a person, an event). Split a doc that covers five
130 things into five concepts; merge fragments that only mean something together into one. A
131 heading is a hint, not a rule, do not blindly map one `##` to one file.
1323. **Draft each concept** at `bundle/<section>/<slug>.md` with the full frontmatter. Read the
133 bundle-root `index.md` before writing so the verification key matches its declared format:
134 use `verified` for `okf_version` `0.1` through `0.3`; use `verified_on` for `okf_version` `0.4`.
135 Emit that exact key with `type, title, description, source, timestamp, tags`:
136 - `type` from the vocab. Infrastructure: Machine, Network, Service, Session, Project,
137 Repo, Credential, Path, Process. Domain-neutral: Concept, Decision, Event, Person,
138 Org, Source. Plus Reference (the catch-all). The set is closed; an unlisted type fails.
139 - `description` is one line. `source`, quote every element, points at where the fact
140 actually came from (the origin file path, URL, command, or event), not at this skill.
141 - Set `timestamp` to today. `verified`/`verified_on` is the date the fact was last confirmed
142 true, set it by how you came to know it, not reflexively to today:
143 - You re-checked it against reality now, or the user is the authority for it (a decision,
144 preference, or intent they state in this session): today.
145 - The user is recalling external or system state (a spec, a path, a config): their memory is a
146 source claim, not a re-check, so date it to when that state was last checked or to the
147 recollection's own date, not today just because it came up now.
148 - It was copied from a dated source without re-checking: the date it was last known true (the
149 source's own date), not today.
150 - It came from an undated record you cannot re-confirm (a memory file, an old conversation):
151 the oldest date you can evidence, file timestamp, introducing commit, or the date it was
152 said, never today. If you cannot evidence any date at all, it is not yet a verifiable fact;
153 find a datable source or leave the concept out.
154 When the date is uncertain, round it down: an older `verified` correctly reads as "may be
155 stale, re-check," while today reads as "just confirmed." The frontmatter date is the contract;
156 a caveat in the body does not undo an overstated value, because the validator and tools read
157 only the date.
158 - Strip secret values as you go: a credential concept names the key and its retrieval path,
159 never the value. The validator fails the build on a leaked secret.
1604. **Place and link.** Put each concept in the right section (create sections as needed), add a
161 bullet for it to that section's `index.md`, and cross-link related concepts with relative
162 `[text](path.md)` links, not `[[slug]]` wikilinks. `[[slug]]` is the auto-memory idiom; the
163 OKF validator rejects it and never resolves it, so a typo'd or deleted reference passes silently.
164 When you create a new section, also link it from the bundle-root `index.md`, that root is the
165 navigation map the session anchor loads, so a section missing from it is invisible to orientation
166 even though validation still passes.
1675. **Clear the placeholder.** If you scaffolded fresh, delete the starter `example-concept.md` (and
168 its bullet in the section `index.md`) once real concepts exist, otherwise the sample ships in
169 the finished wiki and still passes validation.
1706. **Validate in a loop.** Run `python3 scripts/validate.py --bundle bundle`, fix what it
171 reports, repeat until it exits 0. Unquoted `source` elements and missing frontmatter keys are
172 the common failures. Author in batches and validate between them rather than writing fifty
173 files and debugging the lot.
174
175### When the source is already OKF
176
177If the user points you at an existing OKF bundle (e.g. an upstream example: an `index.md`
178carrying `okf_version` plus concept files with frontmatter), you are adopting it, not importing
179it. Copy or clone the tree in, point the validator at the new root, and fix any links that broke
180in the move. To keep it as its own area beside other content, give it a uniquely named top
181directory, then create one combined-root `index.md` that carries `okf_version` and strip the
182frontmatter from each adopted bundle's own root `index.md`, turning it into a normal section index
183(the validator allows `okf_version` on the one combined root only; a nested `index.md` that still
184carries it fails validation). Write cross-links as relative paths and validate the combined root.
185Re-authoring an already-conforming bundle into your own concepts is wasted work; only reshape it if
186that is the actual goal.
187
188## The format, briefly
189
190Full contract in `spec/SPEC.md`. This spec is a strict fork of Google's upstream OKF: it
191requires all seven frontmatter keys, uses a `source` list in place of upstream's `resource`
192and `# Citations`, adds a verification-date key, closes the type vocab, and enforces link
193resolution. `spec/SPEC.md` ("Relationship to upstream OKF") lists every difference. The
194load-bearing rules:
195
196- **Required frontmatter** on every concept: `type, title, description, source`, the
197 version-specific verification key described above, `timestamp, tags`. `type` is one of:
198 Machine, Network, Service, Session, Project, Repo, Credential, Path, Process
199 (infrastructure); Concept, Decision, Event, Person, Org, Source (domain-neutral); or
200 Reference (catch-all).
201- **Quote every `source` element**, source pointers carry `#` and `: ` which break YAML
202 if unquoted. `source: ["README.md", "issue #445"]`.
203- **`verified`/`verified_on`** is the date the fact was last confirmed true, a re-check
204 against reality, or the user stating a fact they are the authority for (a decision, a
205 preference); a fact they merely recall about external state is a source claim, not a
206 re-check. **`timestamp`** is when the concept was authored/updated. The verification date is
207 ISO `YYYY-MM-DD`; `timestamp` may also be a full ISO 8601 datetime in `0.3` and `0.4`. See
208 the authoring loop above for the full date rules.
209- **No secret values, ever.** A credential concept documents the key name and retrieval
210 path, never the value. The validator fails the build on a leaked secret.
211- **`index.md` and `log.md` are reserved**, no frontmatter (except the bundle-root
212 `index.md`, which carries `okf_version` only).
213
214### Optional: upstream v0.2 trust/provenance signals
215
216Upstream Google OKF v0.2 (July 2026) added an optional vocabulary for a consumer to judge a
217concept before reading it: `generated` (who/what produced it), `verified` (a list of
218independent confirmations, not this fork's own single-date field), `sources` (structured,
219per-pointer credibility signals), `status` (draft/stable/deprecated), `stale_after` (an
220absolute expiry date), and an `Attested Computation` type for a sanctioned, checkable
221computation. None of it is required, and a bundle that adopts none of it is unaffected.
222
223Scaffold a project with these enabled, `scaffold.py <target> --trust-signals`, and the
224bundle declares `okf_version: "0.4"`, with `verified` renamed to `verified_on` in the
225required set (freeing `verified` for the new shape; see `spec/SPEC.md`'s "Trust and
226provenance" section for the full field contract and the reasoning behind the rename).
227`Attested Computation` is likewise a `0.4`-only type. Without the flag, scaffolding is
228unchanged from before this vocabulary existed.
229
230## Session hooks
231
232A scaffolded project ships a `.claude/` with two hooks so any Claude session opened in it
233starts from the bundle, not from memory:
234
235- **`okf-anchor.py`** (SessionStart) prints the bundle's root index into the session context.
236- **`okf-orient.py`** (PreToolUse, no matcher) blocks the first action of the session once,
237 until Claude confirms it read the index, then unblocks for the rest of the session. It is
238 inert outside an OKF bundle and fails open on any error, so it never wedges a session.
239
240Both are one cross-platform python3 script. The scripts are identical on every OS; only the
241interpreter in `.claude/settings.json` changes: `python3` on macOS/Linux, `python` on
242Windows. `scaffold.py` auto-detects the OS; `--hooks-os posix|windows` forces it.
243
244Claude Code treats a checked-in `.claude/settings.json` as untrusted, so the first time the
245project is opened it asks the user to approve the hooks; they run automatically after that.
246To turn them off, scaffold with `--no-hooks`, or delete `.claude/` (or set `disableAllHooks`)
247in an existing project.
248
249### Client boundary
250
251The portable OKF surface is `SPEC.md`, `requirements.txt`, `scripts/validate.py`, and the
252`bundle/` tree. The generated `README.md` documents both that shared surface and any enabled
253client adapter. The three generated `.claude/` files are a Claude Code adapter, not part of
254the OKF format and not shared Codex behavior. Codex does not read them as project configuration,
255and this skill must not claim that their `SessionStart` or `PreToolUse` lifecycle runs there.
256
257The general onboarding route above still names Claude Code's `AskUserQuestion` and
258`${CLAUDE_SKILL_DIR}` surfaces. The recorded Codex pilot pre-set every onboarding choice and
259used an explicit project-relative installed path; it does not establish that the unadapted
260general route is portable.
261
262For a mixed Claude Code and Codex project, keep `.claude/` so Claude Code can request trust
263and use the hooks; Codex leaves it inert. For a Codex-only project, pass `--no-hooks` while
264scaffolding or delete `.claude/` afterward. Either choice leaves the portable bundle and
265validator unchanged.
266
267## Optional: publish into a GitHub wiki
268
269OKF lives best as in-repo files (the validator and relative links work directly). A repo's
270GitHub wiki is an optional reading surface, and wiring it up is an advanced, manual step,
271most users should skip it and keep the bundle in-repo.
272
273A wiki with zero pages has no git repo to push to and no API, so the very first page must be
274created through the web UI. `scripts/gh-wiki-bootstrap.py` automates that one step, but it
275drives a real logged-in browser, so it needs two things you provide yourself (a GitHub PAT
276does not work, wiki pages are a web-UI-only surface):
277
278- **Playwright with Chromium installed:** `pip install playwright && playwright install chromium`.
279- **A saved GitHub web session:** a Playwright `storageState` JSON, captured from a browser
280 where you have already logged into GitHub. The script reuses that session; it does not log
281 in for you. Pass its path with `--state` (default: `~/.cache/gh_state.json`).
282
283```bash
284python3 "${CLAUDE_SKILL_DIR}/scripts/gh-wiki-bootstrap.py" owner/repo --state path/to/gh_state.json
285# then: git clone https://github.com/owner/repo.wiki.git and push your pages
286```
287
288Note the impedance: GitHub wikis are flatter than an OKF tree and use `[[WikiLinks]]`, so
289OKF's nested directories and relative links need adapting for the wiki surface. Treat the
290wiki as a published view, not the source of truth. (v0.1 ships the bootstrap step; an
291automatic bundle-to-wiki sync is not built yet.)
292
293## Before finishing
294
295- Run the validator and confirm it exits 0.
296- Confirm the visibility you set during onboarding still fits what got authored: a bundle that
297 ended up documenting real infrastructure is usually internal. OKF takes no position; you must.