okf-gem · docs
CLI · read

okf index

Orient before you read: the bundle's map.

When to use it

  • First, when picking up an existing bundle. It is the cheapest high-signal orientation: the map, the rollups, and the listings in one pass.
  • To catch enumeration drift. An index.md that stopped listing a concept is invisible to grep (you cannot grep for an entry that is missing); the map makes the gap visible.
  • Before an agent reads anything else. okf index <dir> --except body,listing is the lean skeleton of the whole bundle in a few hundred bytes.

How it works

index implements the spec's section 6 index files as a view. It prints one entry per directory that holds concepts or carries an index.md, root first: the authored index body (frontmatter stripped), a type and tag rollup over the concepts that live directly there, its child directories, and the concept listing.

It is also the one read verb that sees the reserved layer: index.md files are structural, so okf catalog, okf files, and the other concept views never show them. For a directory that has concepts but no index.md, the listing is synthesized from the concepts' descriptions and tagged (no index.md); section 6 explicitly permits synthesizing a map on the fly.

--dir PATH narrows the map to one directory and everything below it, and is repeatable (--dir model --dir format shows both): a concept matches when its directory is the path or sits below it, root (or .) names the bundle root (a real root/ directory, where one exists, owns the name instead since 1.13.0), and matching folds case. --depth N keeps only that many directory levels below the starting point, which is the --dir when one is given and the bundle root otherwise. It is relative, not absolute, so --dir a/b --depth 1 reads "a/b and one level under it"; --depth 0 is the starting point alone, and anything but a whole number is a usage error (exit 2). With --dir, the chain of ancestors up to the root is shown by default so the branch is placed in the context that names it, the root index.md's prose first among them; those rows carry a leading and ancestor: true, stay out of total, and --no-ancestors drops them. Ascent and descent are separate axes, so --depth never bounds the chain. --no-body drops the prose to a skeleton of headers, rollups, and child pointers. It is a read view: advisory, always exit 0.

The --area flag is deprecated. It still works, but it warns, it maps to --dir, and it saw only the first path segment where --dir speaks the whole path. It cannot combine with --depth or --dir, and that pairing is refused (exit 2). For the shape read these two flags share, one row per directory rather than a full map, see okf dirs.

Try it

okf index docs/ --dir features
Index map - docs (1 directory)

  features/  ·  12 concepts · Feature 12
    → bundles/  chat/
    One concept per shipped capability. Start with the chat pipeline,
    then follow each feature's links into the models it reads.

To walk a large tree a level at a time, pair --dir with --depth:

okf index docs/ --dir cli --depth 1 --except body,listing

For a machine, okf index docs/ --json emits { bundle, count, directories: [{ dir, index_path, present, synthesized, count, types, tags, subdirs, body, listing: [{ id, title, description, type, tags }] }] } as compact single-line JSON. --fields / --except project that shape down (--no-body is shorthand for dropping just body), and on a large bundle dropping body and listing is the difference between a few hundred bytes and hundreds of KB: on one 414-concept bundle, index --json went from 313 KB to 2.8 KB at --depth 1 --except body,listing, which is what makes index usable at scale.

Pitfalls

  • --dir is repeatable, not comma-separated. Pass the flag once per directory: --dir model --dir format. Matching folds case and reaches every directory below the one you name, and root names the bundle root so you never shell-quote (root); a bundle with a real root/ directory keeps it addressable, since the real directory wins over the alias. The deprecated --area saw only the first segment, so prefer --dir.
  • A synthesized directory is a signal, never a defect. (no index.md) means a map worth writing, but index emits no lint findings and never fails a bundle; the curation question belongs to okf lint.
  • A --dir that matches nothing is an empty map, not an error. The exit code stays 0; check the count before assuming the directory exists. The ancestor chain is not printed for a --dir that matched nothing, so a lone root row never reads as a partial answer to a query that in fact matched nothing.
  • Do not look for index.md in the other views. Reserved files appear only here; the bundle anatomy page explains what makes them reserved.
esc
navigate open