{
"name": "ct-okf",
"description": "Author, query, and index Open Knowledge Format (OKF v0.1) bundles — directory trees of Markdown concepts whose leading YAML frontmatter carries a required `type` plus optional title/description/resource/tags/timestamp, alongside reserved index.md / log.md files and Markdown cross-links. ct-okf is SUBCOMMAND-shaped (`ct okf <verb>`); the `commands` array lists every verb and its arguments. It works over the project's configured OKF content roots and keeps a lazily-maintained full-text index, so `search` is always current. Roots are discovered three ways (any suffices, all converge on the .ct/okf.jsonc config): a `.okf` marker file, a bundle-root index.md declaring okf_version, or a config entry managed by `roots`/`init`. The index lives under .ct/okf/ as immutable fst segments (new content layers a segment; `index condense` merges and drops tombstones). Query verbs: `search QUERY...` (full-text across roots, auto-updates the index first; supports term, term* prefix, term~/term~N fuzzy, /regex/; filter --type/--tag, cap --limit) and `find` (list concepts by --type/--tag in the --base bundle). Configure: `roots list|add|rm|scan`, `index status|update|condense|rebuild`, `init` (discover roots, record them, build the index). Check (framed verdict): `validate` (conformance; --strict also fails on broken links) and `links` (broken bundle cross-links) — both take --question, --expect (any|none|N|=N|+N|-N, default none), --emit/--emit-stderr ({RESULT} {QUESTION} {COUNT} {TOTAL} {BASE} {MATCHES}). Author (these write): `show PATH`, `add PATH --type ...` (alias new), `mv SRC DST` (alias rename; fixes bundle cross-links), `set FIELD=VALUE --file`, `log MESSAGE --kind`, `gen-index` ((re)generate index.md, --scaffold for an okf_version stub), `script PATH` (atomic .ctb batch). Global flags (`base`/`name`/`hidden`/`follow`/`no-ignore`/`json`/`json-pretty`/`quiet`/`timeout`/heartbeat) apply across verbs. Exit 0 SUCCESS, 1 ERROR, 2 usage/runtime error. Because the authoring verbs write, ct-okf is not on the read-only allowlist (read-only OKF composition is provided by the OKF-aware ct-search/ct-tree/ct-view/ct-outline and the `okf` built-in check). Invoke as `ct okf <verb> ...` or `ct-okf <verb> ...`.",
"commands": [
{ "name": "search", "summary": "Full-text search across content roots (auto-updates the index first).", "args": "QUERY... [--limit N=20] [--type TYPE] [--tag T,...]" },
{ "name": "find", "summary": "List concepts by metadata in the --base bundle.", "args": "[--type TYPE] [--tag T,...]" },
{ "name": "roots", "summary": "Manage content roots.", "args": "list | add DIR [--marker] | rm DIR | scan [--write]" },
{ "name": "index", "summary": "Maintain the search index.", "args": "status | update | condense | rebuild" },
{ "name": "init", "summary": "Discover content roots, record them, and build the index.", "args": "[--marker]" },
{ "name": "validate", "summary": "Judge the --base bundle's OKF conformance (framed verdict).", "args": "[--strict] [--question Q] [--expect SPEC] [--emit T] [--emit-stderr T]" },
{ "name": "links", "summary": "Report broken bundle cross-links (framed verdict).", "args": "[--strict] [--question Q] [--expect SPEC] [--emit T] [--emit-stderr T]" },
{ "name": "show", "summary": "Print one concept's frontmatter.", "args": "PATH" },
{ "name": "add", "summary": "Scaffold a new concept (alias: new).", "args": "PATH --type TYPE [--title T] [--description D] [--tag T,...]" },
{ "name": "mv", "summary": "Move/rename a concept, fixing bundle cross-links (alias: rename).", "args": "SRC DST" },
{ "name": "set", "summary": "Set or update a scalar frontmatter field.", "args": "FIELD=VALUE --file PATH" },
{ "name": "log", "summary": "Prepend a dated entry to a bundle's log.md.", "args": "MESSAGE [--kind LABEL]" },
{ "name": "gen-index", "summary": "(Re)generate a bundle's index.md from its concepts.", "args": "[--scaffold]" },
{ "name": "script", "summary": "Run a .ctb batch of OKF mutations atomically.", "args": "PATH [--dry-run] [--fence STR]" }
],
"input_schema": {
"type": "object",
"properties": {
"base": {
"type": "string",
"description": "Search root for bundle-scoped verbs (validate/links/find/show); the directory project discovery starts from for search/index/roots/init. Default '.'.",
"default": "."
},
"name": {
"type": "string",
"description": "Limit to files whose name matches; '|'-separated alternatives, each substring->glob->regex promoted and anchored."
},
"hidden": {
"type": "boolean",
"description": "Include dot-entries (names starting with '.')."
},
"follow": {
"type": "boolean",
"description": "Follow symlinks while traversing."
},
"no-ignore": {
"type": "boolean",
"description": "Walk gitignored / .ignore files too (the .git directory is always skipped)."
},
"json": {
"type": "boolean",
"description": "Emit a structured JSON result instead of text."
},
"json-pretty": {
"type": "boolean",
"description": "Like --json, but pretty-printed (indented)."
},
"quiet": {
"type": "boolean",
"description": "Suppress informational output (exit status and --emit still report)."
},
"timeout": {
"type": "number",
"description": "Abort with exit 2 if the run exceeds SECS seconds (fractional allowed)."
},
"heartbeat": {
"type": "number",
"description": "Print a liveness pulse every SECS seconds (fractional allowed) while the run is in progress."
},
"heartbeat-emit": {
"type": "string",
"description": "Heartbeat line template. Tokens: {ELAPSED} (whole seconds so far) {TOOL}. Default: \"[{ELAPSED}s]\"."
},
"heartbeat-to": {
"type": "string",
"enum": ["stderr", "stdout"],
"description": "Stream heartbeat pulses are written to. Default: stderr."
}
},
"required": []
},
"examples": [
{"cmd": "ct okf validate --base docs/concepts", "why": "Judge a bundle's OKF conformance with a framed pass/fail verdict."},
{"cmd": "ct okf links --base docs/concepts", "why": "Report broken cross-links within an OKF bundle."}
]
}