okf 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.okf/capabilities/agent-skill.md +112 -0
- data/.okf/capabilities/bundles-manager.md +144 -0
- data/.okf/capabilities/graph-server.md +678 -0
- data/.okf/capabilities/index.md +26 -0
- data/.okf/capabilities/library-api.md +82 -0
- data/.okf/capabilities/linter.md +83 -0
- data/.okf/capabilities/read-views.md +228 -0
- data/.okf/capabilities/render.md +66 -0
- data/.okf/capabilities/search.md +297 -0
- data/.okf/capabilities/validator.md +60 -0
- data/.okf/cli.md +214 -0
- data/.okf/design/browser-tests.md +211 -0
- data/.okf/design/core-shell-split.md +73 -0
- data/.okf/design/index.md +17 -0
- data/.okf/design/integration-first.md +140 -0
- data/.okf/design/packaging.md +65 -0
- data/.okf/design/ruby-floor.md +53 -0
- data/.okf/design/runtime-dependencies.md +82 -0
- data/.okf/design/search-engines.md +154 -0
- data/.okf/design/server-trust-boundary.md +139 -0
- data/.okf/index.md +40 -0
- data/.okf/log.md +724 -0
- data/.okf/model/bundle.md +47 -0
- data/.okf/model/concept.md +75 -0
- data/.okf/model/graph.md +59 -0
- data/.okf/model/index.md +9 -0
- data/.okf/model/skeleton.md +76 -0
- data/.okf/overview.md +87 -0
- data/.okf/registry.md +432 -0
- data/.okf/structure/format-layer.md +59 -0
- data/.okf/structure/index.md +22 -0
- data/.okf/structure/search.md +53 -0
- data/.okf/structure/the-analysers.md +60 -0
- data/.okf/structure/the-cli.md +99 -0
- data/.okf/structure/the-disk-shell.md +76 -0
- data/.okf/structure/the-model.md +81 -0
- data/.okf/structure/the-server.md +74 -0
- data/.okf/structure/the-skill.md +52 -0
- data/.okf/testing/adding-a-verb.md +76 -0
- data/.okf/testing/index.md +12 -0
- data/.okf/testing/the-harness.md +45 -0
- data/CHANGELOG.md +161 -16
- data/README.md +226 -17
- data/lib/okf/cli/command.rb +8 -3
- data/lib/okf/cli/registry.rb +306 -47
- data/lib/okf/cli.rb +1 -1
- data/lib/okf/registry.rb +448 -22
- data/lib/okf/render/graph/template.html.erb +6 -2
- data/lib/okf/server/hub.rb +6 -2
- data/lib/okf/skill/reference/cli/registry.md +49 -6
- data/lib/okf/skill/reference/cli.md +1 -1
- data/lib/okf/version.rb +1 -1
- metadata +46 -5
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,149 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.2.0] - 2026-08-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`okf registry import <@slug…> [--from FILE]` — copy chosen bundles out of
|
|
13
|
+
another registry file into the one in force, where they become yours.** It is
|
|
14
|
+
the opposite trade from `link` and the pair is the point: a link holds a live
|
|
15
|
+
pointer to a whole file and the other side keeps owning what it lends, while an
|
|
16
|
+
import copies chosen references and hands over ownership, so what lands renames,
|
|
17
|
+
defaults and groups like anything you registered by hand. The case it exists for
|
|
18
|
+
is standing in a repo, running `okf registry list -g`, and wanting one of the
|
|
19
|
+
bundles it shows — before this the only way to move it was to read the path off
|
|
20
|
+
the screen and retype it into `registry set`.
|
|
21
|
+
|
|
22
|
+
The source is `--from`, defaulting to the global registry, because `-g` goes on
|
|
23
|
+
meaning the registry acted *on*, as it does on every sibling subcommand. A group
|
|
24
|
+
ask brings its members and any group nested inside it, recreated under the same
|
|
25
|
+
names. Slugs are preserved, so a collision **refuses** (`--as` renames a single
|
|
26
|
+
ask) rather than being minted around the way a linked name is — a linked name was
|
|
27
|
+
never chosen here, an imported one was typed. A bundle already registered here
|
|
28
|
+
under another name refuses first, naming that name. Every ask is validated before
|
|
29
|
+
anything is written, so an import lands whole or leaves the file byte-for-byte
|
|
30
|
+
alone.
|
|
31
|
+
|
|
32
|
+
- **`.okf.json` is the project-local registry's filename.** `okf registry init`
|
|
33
|
+
writes it, and it is what the docs now name. The older `.okf-registry.json` is
|
|
34
|
+
**still discovered**, so no committed registry breaks: both names are checked in
|
|
35
|
+
each directory on the way up — per directory, not one name swept to the root and
|
|
36
|
+
then the other, or a legacy file at a repo's root would beat a `.okf.json` two
|
|
37
|
+
levels down and "the nearest one wins" would mean something else. Within one
|
|
38
|
+
directory the short name wins, and a legacy file left beside it is named on
|
|
39
|
+
stderr rather than silently ignored.
|
|
40
|
+
|
|
41
|
+
The deprecation note is the `registry` umbrella's alone, and it is one stderr
|
|
42
|
+
line: that verb's subject *is* a registry file, and it is not the one people run
|
|
43
|
+
in loops or pipe into something else, which is exactly what `lint` and `search`
|
|
44
|
+
are. Renaming is `git mv .okf-registry.json .okf.json`, and the note says so. One
|
|
45
|
+
transitional cost worth naming: a checkout renamed to `.okf.json` is invisible to
|
|
46
|
+
an installed okf older than 2.2.0, which will fall back to the global registry
|
|
47
|
+
until that install is upgraded.
|
|
48
|
+
|
|
49
|
+
- **`okf registry link <name> <file>` — the global registry points at another
|
|
50
|
+
registry file, and that file's bundles resolve here.** Nothing is copied: the
|
|
51
|
+
target keeps owning its rows, so an edit there shows on the next read. The case
|
|
52
|
+
it exists for is a repository that already curates its own bundles in a
|
|
53
|
+
committed `.okf-registry.json` — a link composes that curation instead of
|
|
54
|
+
duplicating it, and the target resolves its own relative paths exactly as it
|
|
55
|
+
would from inside that checkout. A linked bundle answers to its own slug, or to
|
|
56
|
+
`<name>-<slug>` when the name is already taken here; `@<name>` resolves as a
|
|
57
|
+
group over the set; `okf registry unlink <name>` drops it.
|
|
58
|
+
|
|
59
|
+
Links are the **global** registry's alone. A project-local one parses them and
|
|
60
|
+
never resolves them, which is what makes depth one structural — a linked file's
|
|
61
|
+
own links are never followed, so no chain forms and there is no cycle to guard.
|
|
62
|
+
A link is read-only: `rename`, `del`, `default`, `set --as` and `group` refuse a
|
|
63
|
+
slug it owns, naming the file that does, from the browser's ⚙ Bundles panel as
|
|
64
|
+
from the terminal. A target that has gone or cannot be parsed is listed
|
|
65
|
+
`(missing)`/`(unreadable)` and resolves to nothing, rather than taking down the
|
|
66
|
+
registry holding it.
|
|
67
|
+
|
|
68
|
+
- `registry group` and `registry ungroup` refuse a group a link brought in —
|
|
69
|
+
the link's own set, or one the linked file curates. Naming one took the
|
|
70
|
+
update path, reported `grouped …`, and discarded the change on the next read,
|
|
71
|
+
because only the groups this registry owns are written. A write that reports
|
|
72
|
+
success and does not happen is worse than one that raises.
|
|
73
|
+
|
|
74
|
+
- **`-g`/`--global` on every `registry` subcommand but `init`.** It forces the
|
|
75
|
+
`$OKF_HOME` registry for one command, so `okf registry list -g` reads the global
|
|
76
|
+
one from inside a repo carrying its own, and `okf registry set <dir> -g`
|
|
77
|
+
registers there without leaving. `OKF_NO_DISCOVERY=1` already did this for a
|
|
78
|
+
whole session and still does; the flag exists because a lever reachable only
|
|
79
|
+
through an env var is one most people never find. It stays on the `registry`
|
|
80
|
+
umbrella — the one verb whose subject *is* a registry file — and nowhere else.
|
|
81
|
+
|
|
82
|
+
- The graph page's ⚙ Bundles panel marks a linked row `via @onm` and **offers no
|
|
83
|
+
actions menu** on it. Rename, Remove and Default are all refused for a linked
|
|
84
|
+
bundle, so the menu could only have produced three errors. The request is
|
|
85
|
+
refused whether or not the button exists — the guard is in `Registry`, not in
|
|
86
|
+
the page — which is the same split the read-only server already keeps: hiding
|
|
87
|
+
a control is a UI, refusing the request is the boundary.
|
|
88
|
+
|
|
89
|
+
- **`okf help` shows one `registry` row instead of ten, and `okf registry --help`
|
|
90
|
+
prints the subcommands.** Ten rows for one verb made a third of the map about
|
|
91
|
+
registry management, and the map is there to name the verbs rather than to be
|
|
92
|
+
every verb's manual. The row names the help that replaces it, since nothing
|
|
93
|
+
else tells a reader an umbrella has subcommands. A bare `okf registry` still
|
|
94
|
+
lists the registry, and `okf registry <command> --help` still answers for that
|
|
95
|
+
command.
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- `okf registry list --json` groups now carry a `link` key — `null` for a group
|
|
100
|
+
this registry owns, the link's name for one that arrived through a link.
|
|
101
|
+
`Registry#groups_listing` returns both kinds in one list, own groups first,
|
|
102
|
+
because `#group?` resolves a linked group and a listing that named only the
|
|
103
|
+
local half would answer about a smaller set than the same object can resolve —
|
|
104
|
+
the drift every library consumer would inherit silently. A caller that wants
|
|
105
|
+
only the editable groups filters on `link`.
|
|
106
|
+
|
|
107
|
+
- `okf registry list --json` gains a `links` array, and each bundle row gains
|
|
108
|
+
`link` (the link it arrived through, `null` when the registry owns it) and
|
|
109
|
+
`origin` (its slug in that file, differing only where a collision moved the
|
|
110
|
+
name). The on-disk registry gains a `"links"` key, written empty when there are
|
|
111
|
+
none; an older file with no such key reads unchanged.
|
|
112
|
+
|
|
113
|
+
## [2.1.1] - 2026-08-20
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
|
|
117
|
+
- **The package metadata follows the `gems/` move and the repository rename.**
|
|
118
|
+
Two URLs on the package page were about to be wrong at once. `changelog_uri`
|
|
119
|
+
named `blob/main/okf/CHANGELOG.md`, a path that stopped existing when the
|
|
120
|
+
four gems moved under `gems/`; `homepage` named `serradura/okf-gem`, and the
|
|
121
|
+
repository is now **`serradura/okf`** — the name the command has had all
|
|
122
|
+
along. rubygems.org serves whatever the last release published, so neither
|
|
123
|
+
corrects itself: only a release republishes metadata, and this is that
|
|
124
|
+
release. Both land in one round rather than two, which is the whole reason
|
|
125
|
+
the rename waited for the paths to stop moving.
|
|
126
|
+
|
|
127
|
+
`homepage_uri`, `source_code_uri` and `changelog_uri` are all derived from
|
|
128
|
+
`homepage`, so one line moves four pieces of this gem's metadata. GitHub
|
|
129
|
+
redirects the old URLs permanently, so anything already published keeps
|
|
130
|
+
resolving.
|
|
131
|
+
|
|
132
|
+
### Added
|
|
133
|
+
|
|
134
|
+
- **The gem ships a file-level map of itself, at `.okf/`.** `structure/` names
|
|
135
|
+
every one of the fifty files under `lib/`, grouped by the layer that owns it,
|
|
136
|
+
and `testing/adding-a-verb.md` is the ordered walk a new command owes. It is
|
|
137
|
+
the gem's own documentation rather than a sample, so an installed okf now
|
|
138
|
+
carries a real bundle for a reader to open with the tool they just installed:
|
|
139
|
+
`okf server "$(gem contents okf --show-install-dir)/.okf"`.
|
|
140
|
+
|
|
141
|
+
It deliberately copies nothing from the repository's own bundle, which still
|
|
142
|
+
holds okf's format, model, capabilities and design constraints — a second copy
|
|
143
|
+
of a catalogue is worse than none.
|
|
144
|
+
|
|
145
|
+
`test/unit/bundle_catalog_test.rb` pins both halves: a file under `lib/` named
|
|
146
|
+
by no concept, a concept naming a file that is gone, or the repository
|
|
147
|
+
bundle's `cli.md` group table disagreeing with `OKF::CLI.builtins` all fail
|
|
148
|
+
the suite. That group table was code-derived and unchecked until now.
|
|
149
|
+
`test/unit/packaging_test.rb` pins that the bundle actually ships.
|
|
150
|
+
|
|
8
151
|
## [2.1.0] - 2026-08-17
|
|
9
152
|
|
|
10
153
|
### Changed
|
|
@@ -1437,7 +1580,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1437
1580
|
### Added
|
|
1438
1581
|
|
|
1439
1582
|
- Claude Code plugin. The repository now doubles as a plugin marketplace:
|
|
1440
|
-
`/plugin marketplace add serradura/okf
|
|
1583
|
+
`/plugin marketplace add serradura/okf`, then `/plugin install okf@okfgem`.
|
|
1441
1584
|
The plugin carries the canonical skill (a generated copy; `rake plugin:sync`
|
|
1442
1585
|
keeps it in lockstep with `lib/okf/skill`, and a test fails on drift), one
|
|
1443
1586
|
front-door command (`/okf:gem`: no arguments orients on the CLI, the bundle,
|
|
@@ -1543,18 +1686,20 @@ Initial release.
|
|
|
1543
1686
|
|
|
1544
1687
|
- Runs on Ruby >= 2.4 with two runtime dependencies: rack and webrick.
|
|
1545
1688
|
|
|
1546
|
-
[2.
|
|
1547
|
-
[1.
|
|
1548
|
-
[
|
|
1549
|
-
[1.
|
|
1550
|
-
[1.
|
|
1551
|
-
[1.
|
|
1552
|
-
[1.
|
|
1553
|
-
[1.
|
|
1554
|
-
[1.
|
|
1555
|
-
[1.
|
|
1556
|
-
[1.
|
|
1557
|
-
[1.
|
|
1558
|
-
[1.
|
|
1559
|
-
[1.
|
|
1560
|
-
[1.
|
|
1689
|
+
[2.1.1]: https://github.com/serradura/okf/compare/v2.1.0...v2.1.1
|
|
1690
|
+
[2.1.0]: https://github.com/serradura/okf/compare/v2.0.0...v2.1.0
|
|
1691
|
+
[2.0.0]: https://github.com/serradura/okf/compare/v1.13.0...v2.0.0
|
|
1692
|
+
[1.13.0]: https://github.com/serradura/okf/compare/v1.12.0...v1.13.0
|
|
1693
|
+
[1.12.0]: https://github.com/serradura/okf/compare/v1.11.0...v1.12.0
|
|
1694
|
+
[1.11.0]: https://github.com/serradura/okf/compare/v1.10.0...v1.11.0
|
|
1695
|
+
[1.10.0]: https://github.com/serradura/okf/compare/v1.9.0...v1.10.0
|
|
1696
|
+
[1.9.0]: https://github.com/serradura/okf/compare/v1.8.0...v1.9.0
|
|
1697
|
+
[1.8.0]: https://github.com/serradura/okf/compare/v1.7.0...v1.8.0
|
|
1698
|
+
[1.7.0]: https://github.com/serradura/okf/compare/v1.6.0...v1.7.0
|
|
1699
|
+
[1.6.0]: https://github.com/serradura/okf/compare/v1.5.0...v1.6.0
|
|
1700
|
+
[1.5.0]: https://github.com/serradura/okf/compare/v1.4.0...v1.5.0
|
|
1701
|
+
[1.4.0]: https://github.com/serradura/okf/compare/v1.3.0...v1.4.0
|
|
1702
|
+
[1.3.0]: https://github.com/serradura/okf/compare/v1.2.0...v1.3.0
|
|
1703
|
+
[1.2.0]: https://github.com/serradura/okf/compare/v1.1.0...v1.2.0
|
|
1704
|
+
[1.1.0]: https://github.com/serradura/okf/compare/v1.0.0...v1.1.0
|
|
1705
|
+
[1.0.0]: https://github.com/serradura/okf/releases/tag/v1.0.0
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@ ranked search, and a live knowledge graph. 100% local.**
|
|
|
5
5
|
|
|
6
6
|
[Site](https://okfgem.com) · [Docs](https://okfgem.com/docs/) ·
|
|
7
7
|
[Live demo](https://demo.okfgem.com) ·
|
|
8
|
-
[Project README](https://github.com/serradura/okf
|
|
8
|
+
[Project README](https://github.com/serradura/okf#readme)
|
|
9
9
|
|
|
10
10
|
OKF (Open Knowledge Format) is portable project knowledge: Markdown files with
|
|
11
11
|
YAML frontmatter that both humans and agents read from one source. This gem is
|
|
@@ -22,20 +22,41 @@ on every Ruby since **2.4** — the one your OS already ships.
|
|
|
22
22
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
25
|
+
> **In Claude Code**, the plugin is the fastest path: two commands install the whole
|
|
26
|
+
> toolchain (skill, `/okf:gem`, and the curation hook). See the
|
|
27
|
+
> [project README](https://github.com/serradura/okf#claude-code-plugin).
|
|
28
|
+
> Everywhere else, install the gem:
|
|
29
|
+
|
|
25
30
|
```bash
|
|
26
31
|
gem install okf
|
|
27
32
|
# or, in a project
|
|
28
33
|
bundle add okf
|
|
29
34
|
```
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
Tested and supported on every Ruby from **2.4 through 4.0**. From a checkout,
|
|
37
|
+
`bundle exec rake install` builds and installs it locally.
|
|
38
|
+
|
|
39
|
+
## No Ruby? Use Docker
|
|
40
|
+
|
|
41
|
+
The official image bundles the CLI, so every `okf` command runs against a bundle
|
|
42
|
+
you mount at `/data`:
|
|
32
43
|
|
|
33
44
|
```bash
|
|
34
45
|
docker run --rm -v "$PWD:/data" ghcr.io/serradura/okf validate .
|
|
46
|
+
docker run --rm -v "$PWD:/data" -p 8808:8808 ghcr.io/serradura/okf server . --bind 0.0.0.0
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Tired of the long line? The Docker-backed [`okf` command](https://docker.okfgem.com)
|
|
50
|
+
drops the prefix so every verb reads exactly like the native CLI:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
curl -fsSL https://docker.okfgem.com/install.sh | sh # PowerShell: irm https://docker.okfgem.com/install.ps1 | iex
|
|
54
|
+
okf validate .
|
|
55
|
+
okf server .
|
|
35
56
|
```
|
|
36
57
|
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
Images are published for `linux/amd64` and `linux/arm64` on
|
|
59
|
+
[ghcr.io](https://github.com/serradura/okf/pkgs/container/okf).
|
|
39
60
|
|
|
40
61
|
## Four steps to your first bundle
|
|
41
62
|
|
|
@@ -55,6 +76,41 @@ okf server <folder> # 4. explore what you got, as a live graph
|
|
|
55
76
|
|
|
56
77
|
Then `/okf maintain` keeps it in sync as the code changes.
|
|
57
78
|
|
|
79
|
+
What the gem does, and which verb does it. This table is the map; **[the
|
|
80
|
+
docs](https://okfgem.com/docs/)** are the manual.
|
|
81
|
+
|
|
82
|
+
| Capability | What it answers | Verb |
|
|
83
|
+
| ------------------------------------------------------------- | --------------------------------- | -------------------------- |
|
|
84
|
+
| [Companion agent skill](https://okfgem.com/docs/skill/) | Can an agent author it? | `skill` |
|
|
85
|
+
| [Conformance validator](https://okfgem.com/docs/cli/validate/) | Is this a legal OKF bundle? | `validate` |
|
|
86
|
+
| [Curation linter](https://okfgem.com/docs/cli/lint/) | Is it navigable, complete, fresh? | `lint` / `loose` |
|
|
87
|
+
| [Ranked text search](https://okfgem.com/docs/cli/search/) | Which concept covers X? | `search` |
|
|
88
|
+
| [Read views](https://okfgem.com/docs/cli/) | What is in here, and where? | `index` / `dirs` / `catalog` |
|
|
89
|
+
| [Interactive graph server](https://okfgem.com/docs/cli/server/) | Can I explore it visually? | `server` |
|
|
90
|
+
| [Static render](https://okfgem.com/docs/cli/render/) | Can I ship a serverless snapshot? | `render` |
|
|
91
|
+
| [Library API](https://okfgem.com/docs/library/) | Can my Ruby program use it? | in-process |
|
|
92
|
+
|
|
93
|
+
And because knowledge rarely lives in one bundle, a registry gives each one a
|
|
94
|
+
name — see [one registry, many bundles](#one-registry-many-bundles) below.
|
|
95
|
+
|
|
96
|
+
## The graph
|
|
97
|
+
|
|
98
|
+
One page, from a phone to a desktop: the navigation rail becomes a drawer, the
|
|
99
|
+
toolbar folds into a `⚙` sheet, and a tap opens a preview card at the bottom edge
|
|
100
|
+
rather than a panel over the whole viewport, so the graph stays live while you
|
|
101
|
+
read. Drag the card up for the neighbourhood, tap a link and it walks there in
|
|
102
|
+
place.
|
|
103
|
+
|
|
104
|
+
It is keyboard-first: **`⌘/Ctrl-K`** opens a command palette that searches
|
|
105
|
+
concepts, jumps to a view, and — behind a [hub](#one-registry-many-bundles) —
|
|
106
|
+
switches bundles. **`/`** jumps to the current view's search, **`?`** answers with
|
|
107
|
+
every shortcut. Cluster mode boxes the graph by directory and nests as deep as
|
|
108
|
+
your tree does.
|
|
109
|
+
|
|
110
|
+
To skip the server entirely, **`okf render <dir>`** writes that same page as one
|
|
111
|
+
self-contained HTML file, the whole bundle baked in, so you can publish the graph
|
|
112
|
+
on GitHub Pages or any static host.
|
|
113
|
+
|
|
58
114
|
## The command line
|
|
59
115
|
|
|
60
116
|
Written to be read by an **agent first and a person second** — that is what the
|
|
@@ -75,6 +131,8 @@ okf graph <dir|@slug> [--hubs] [--traffic] # the raw graph; --hubs ranks c
|
|
|
75
131
|
okf server [DIR|@slug…] [-p PORT] [--bind ADDR] # the live graph: one bundle, or all of them
|
|
76
132
|
okf render <dir|@slug> [-o FILE] # the same page as one static, self-contained file
|
|
77
133
|
okf registry init | list | set | del | default | rename | group | ungroup # name & group your bundles
|
|
134
|
+
okf registry link | unlink <name> <file> # fold another registry file's bundles in
|
|
135
|
+
okf registry import <@slug…> [--from FILE] # copy bundles out of another registry into this one
|
|
78
136
|
okf skill <dest> # install the companion agent skill
|
|
79
137
|
okf --version
|
|
80
138
|
```
|
|
@@ -83,16 +141,157 @@ Exit codes: `0` success, `1` non-conformant bundle (or a `lint --fail-on`
|
|
|
83
141
|
threshold crossed), `2` usage error. Every flag is in `okf <verb> --help` and in
|
|
84
142
|
[the docs](https://okfgem.com/docs/).
|
|
85
143
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
144
|
+
```bash
|
|
145
|
+
$ okf validate docs
|
|
146
|
+
OKF v0.2 conformance — docs
|
|
147
|
+
concepts: 37 index.md: 10 log.md: 1
|
|
148
|
+
! warn features/link-suggestions.md: cross-link target not found: `/graph-view.md` (tolerated under §6.1)
|
|
149
|
+
…
|
|
150
|
+
✓ conformant (33 warning(s))
|
|
151
|
+
|
|
152
|
+
$ okf server docs
|
|
153
|
+
serving 37 concepts at http://127.0.0.1:8808 (Ctrl-C to stop)
|
|
154
|
+
|
|
155
|
+
$ okf render docs > public/index.html # the same page, static — host it anywhere
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## One registry, many bundles
|
|
159
|
+
|
|
160
|
+
The registry is a per-user, ordered list of bundles in one plain JSON file (`$OKF_HOME/registry.json`, default `~/.okf`) — hand-editable,
|
|
161
|
+
greppable, no database. It stores references, never content: the bundles stay in
|
|
162
|
+
the repos that own them.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
okf registry set ./docs --as handbook # give the bundle a name
|
|
166
|
+
okf lint @handbook # @slug works wherever a <dir> does, from anywhere
|
|
167
|
+
okf search @all rate limit # ranked retrieval across every registered bundle
|
|
168
|
+
okf server # no args: the whole registry behind one hub
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Related bundles can share a name: `okf registry group backend @handbook @runbooks`
|
|
172
|
+
makes `@backend` stand for the set (members can be groups too, so they nest), and
|
|
173
|
+
`okf search @backend rate limit` or `okf server @backend` then targets all of them
|
|
174
|
+
at once — a durable subset for the two verbs that take several bundles.
|
|
175
|
+
|
|
176
|
+
The registry lives under `$OKF_HOME` (default `~/.okf`) — one per user. For one
|
|
177
|
+
scoped to a single project instead, `okf registry init` drops a
|
|
178
|
+
`.okf.json` in the current directory (the older `.okf-registry.json` is still
|
|
179
|
+
discovered, and `okf registry` says so once so you can `git mv` it); okf then
|
|
180
|
+
discovers it by walking up from wherever you run, and every registry op — and every `@slug` — resolves through
|
|
181
|
+
it in place of the global one. So a bare `okf server` inside that repo serves *its*
|
|
182
|
+
bundles with no `$OKF_HOME` setup. The nearest registry wins; `-g` on any
|
|
183
|
+
`registry` subcommand reaches the global one for a single command (`okf registry
|
|
184
|
+
list -g`, `okf registry set ./docs -g`), and `OKF_NO_DISCOVERY=1` does it for a
|
|
185
|
+
whole shell.
|
|
186
|
+
|
|
187
|
+
Commit that file and it travels with the repo: a bundle under the project root is
|
|
188
|
+
stored relative to the registry, so a checkout on another machine — or a container
|
|
189
|
+
that mounts the repo — resolves the same bundles unchanged. (Bundles outside the
|
|
190
|
+
tree keep absolute paths, which do not travel.)
|
|
191
|
+
|
|
192
|
+
A repository that already curates its own bundles can lend that list rather than
|
|
193
|
+
have it copied. `okf registry link onm ~/ONM/.okf.json` points the global
|
|
194
|
+
registry at another registry file: its bundles resolve under their own slugs,
|
|
195
|
+
`@onm` names the set, and nothing is duplicated — edit the other file and the
|
|
196
|
+
change shows on the next read. They are read-only from here, since the file that
|
|
197
|
+
owns them is elsewhere.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
okf registry link okf ~/code/okf/.okf.json # that repo's own curation, composed
|
|
201
|
+
okf search @all rate limit # now spans both files
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
When you want one bundle rather than a whole file, `import` is the opposite
|
|
205
|
+
trade — it copies the reference, and what lands is yours to rename, default and
|
|
206
|
+
group. The source is `--from`, defaulting to the global registry, which inside a
|
|
207
|
+
repo is the only other one you have. A group ask brings its members with it,
|
|
208
|
+
slugs are preserved (a collision refuses rather than being renamed behind your
|
|
209
|
+
back), and nothing is written unless every ask checks out.
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
okf registry list -g # what does the global registry hold?
|
|
213
|
+
okf registry import handbook specs # take those two, here, as mine
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Behind the hub each bundle mounts at `/b/<slug>/`, `/b/` lists them all, and the
|
|
217
|
+
`⌘/Ctrl-K` palette both switches bundles and **searches every one at once** — type
|
|
218
|
+
a few words and the matching concepts appear with their bundle and a snippet, from
|
|
219
|
+
wherever you are.
|
|
220
|
+
|
|
221
|
+
The ⚙ rail opens **Bundles**, the registry on the graph page itself: make
|
|
222
|
+
default, rename, remove, where you are already reading. Those controls are the one
|
|
223
|
+
thing that does not follow you onto a network — bind anywhere but loopback and
|
|
224
|
+
they are refused outright, since `--bind 0.0.0.0` is how a personal tool becomes a
|
|
225
|
+
public one.
|
|
226
|
+
|
|
227
|
+
## Reading a big bundle a level at a time
|
|
228
|
+
|
|
229
|
+
A few hundred concepts is a map nobody reads whole, so `index` and `dirs` descend
|
|
230
|
+
instead of dumping. `--dir` takes a directory **and everything under it**,
|
|
231
|
+
`--depth N` bounds how far below that it goes, and the two compose the way you
|
|
232
|
+
actually walk a tree:
|
|
91
233
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
234
|
+
```bash
|
|
235
|
+
okf dirs @handbook # the shape: every dir, what it holds directly and below
|
|
236
|
+
okf index @handbook --depth 1 --no-body # the top of the map, no prose
|
|
237
|
+
okf index @handbook --dir platform/api # now open one branch — with the chain that places it
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Naming a `--dir` brings its ancestors along, marked `↑`, so a branch is never
|
|
241
|
+
shown adrift of the context that says what it is — the root `index.md`'s prose
|
|
242
|
+
first among it.
|
|
243
|
+
|
|
244
|
+
For an agent the saving is the whole point. On a 400-concept bundle the full
|
|
245
|
+
`okf index --json` is 313 KB; the skeleton it orients on is 2.8 KB:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
okf index @handbook --json --depth 1 --except body,listing
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## The agent skill
|
|
252
|
+
|
|
253
|
+
The gem carries the [companion OKF agent skill](https://okfgem.com/docs/skill/):
|
|
254
|
+
a `SKILL.md` plus reference and template files that teach a coding agent to
|
|
255
|
+
author, maintain, and consume OKF bundles and to drive
|
|
256
|
+
[the command line](#the-command-line).
|
|
257
|
+
Because the skill ships inside the gem, installing the gem already puts the skill
|
|
258
|
+
on your machine, and the skill's CLI reference can never drift from the
|
|
259
|
+
executable it was released with.
|
|
260
|
+
|
|
261
|
+
The skill routes a small set of verbs. In Claude Code they run as `/okf:gem
|
|
262
|
+
<verb>`; used standalone, the skill infers the verb from your request.
|
|
263
|
+
|
|
264
|
+
| Verb | What it does |
|
|
265
|
+
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
266
|
+
| _(none)_ | Orient on the bundle and recommend the highest-value next move |
|
|
267
|
+
| `search` | Answer a question from the bundle, token-lean: the map, the finder, only the winning bodies |
|
|
268
|
+
| `produce` | Create or extend a bundle from code, docs, or knowledge in people's heads |
|
|
269
|
+
| `migrate` | Adopt existing Markdown docs in place: frontmatter and reserved files added, bodies kept verbatim |
|
|
270
|
+
| `maintain` | Sync the bundle's content with reality after the code or docs change |
|
|
271
|
+
| `refine` | Restructure it for retrieval: evidence-first, cohesion over balance — proposes, never applies |
|
|
272
|
+
| `consume` | Use the bundle as context for a task, writing back what you learn |
|
|
273
|
+
| `curate` | Structural upkeep as it stands: `validate` + `lint` + `loose` |
|
|
274
|
+
| `doctor` | Install and verify the CLI, then doctor the bundle |
|
|
275
|
+
| `<okf-cli-verb>` | Run any CLI verb (`validate`, `lint`, `search`, `index`, `server`, the read views) and interpret its output |
|
|
276
|
+
|
|
277
|
+
Three of those look alike and are not, which is the distinction worth learning
|
|
278
|
+
first: **`curate`** keeps the bundle *sound* (the structure as it stands),
|
|
279
|
+
**`maintain`** keeps it *true* (the code changed, so the content must catch up),
|
|
280
|
+
and **`refine`** changes *where knowledge lives* — the folder a concept sits in,
|
|
281
|
+
a fact re-explained in three overviews. Reach for `refine` when nothing is wrong
|
|
282
|
+
and everything is hard to find. It reads the evidence, then hands you a proposal
|
|
283
|
+
— it never rearranges your bundle on its own.
|
|
284
|
+
|
|
285
|
+
Point it at your agent's config directory and the tree settles in its own
|
|
286
|
+
`skills/okf/` folder, so a shared skills directory never gets the files loose:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
okf skill .claude # Claude Code -> .claude/skills/okf
|
|
290
|
+
okf skill .agents # agent-agnostic -> .agents/skills/okf
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The resolved directory must be empty unless you pass `--force`, so a customized
|
|
294
|
+
skill is never clobbered.
|
|
96
295
|
|
|
97
296
|
## The library
|
|
98
297
|
|
|
@@ -173,12 +372,22 @@ do not know.
|
|
|
173
372
|
|
|
174
373
|
## More
|
|
175
374
|
|
|
176
|
-
The [project README](https://github.com/serradura/okf
|
|
375
|
+
The [project README](https://github.com/serradura/okf#readme) carries the
|
|
177
376
|
diagrams, the comparison with `CLAUDE.md`, agent auto-memory and wikis, the
|
|
178
377
|
Claude Code plugin, and the way to install the skill into any agent without this
|
|
179
|
-
gem (`npx skills add serradura/okf
|
|
180
|
-
|
|
181
|
-
gem
|
|
378
|
+
gem (`npx skills add serradura/okf`). The [docs](https://okfgem.com/docs/) are the manual.
|
|
379
|
+
|
|
380
|
+
And the gem documents *itself* in OKF. `.okf/` ships inside it — a map of what
|
|
381
|
+
every file under `lib/` does, and the walk a new verb owes — so from an
|
|
382
|
+
installed copy:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
okf server "$(gem contents okf --show-install-dir)/.okf"
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
reads this gem's own knowledge as a graph, in this gem. That is the shortest
|
|
389
|
+
honest demonstration there is: the format is good enough that the tool's
|
|
390
|
+
maintainers use it on the tool.
|
|
182
391
|
|
|
183
392
|
## License
|
|
184
393
|
|
data/lib/okf/cli/command.rb
CHANGED
|
@@ -577,12 +577,17 @@ module OKF
|
|
|
577
577
|
|
|
578
578
|
# The registry a verb resolves against — the single seam that opts the CLI
|
|
579
579
|
# into discovery. `cwd: Dir.pwd` is what makes OKF::Registry.load walk up for
|
|
580
|
-
# a project-local .okf
|
|
580
|
+
# a project-local .okf.json; a library caller passing no cwd stays
|
|
581
581
|
# global-only. The registry subcommands and `server` open through here too,
|
|
582
582
|
# so a bare `okf server` inside a repo serves that repo's bundles.
|
|
583
|
-
|
|
583
|
+
# +global+ forces the $OKF_HOME registry by withholding the cwd discovery
|
|
584
|
+
# needs — the per-command form of OKF_NO_DISCOVERY, and the only thing
|
|
585
|
+
# `okf registry -g` does. It is an argument to the `registry` verb rather
|
|
586
|
+
# than a flag on all fourteen, because that verb's *subject* is a registry
|
|
587
|
+
# file; every other verb keeps inheriting the env var's one signal.
|
|
588
|
+
def open_registry(global: false)
|
|
584
589
|
require "okf/registry"
|
|
585
|
-
OKF::Registry.load(cwd: Dir.pwd)
|
|
590
|
+
OKF::Registry.load(cwd: global ? nil : Dir.pwd)
|
|
586
591
|
end
|
|
587
592
|
|
|
588
593
|
# Resolve one @ref through the active registry — a discovered project-local
|