# Code exploration for agents

`occ code` opens a freshness-checked, sectioned code graph (no database, no daemon) for JS/TS
and Vue SFCs — script blocks via compiler AST extraction with checker-backed resolution
when available, plus template extraction that turns statically registered component
tags and provable bindings into resolved `uses` edges (feeding callers, impact,
context, PageRank, and facts; unprovable template constructs are refused and
counted under `parserRefusals.vueTemplate`) — plus Python, Go, Rust, Java, C/C++, C#, Kotlin,
Scala, Swift, Ruby, and PHP (tree-sitter). Shared flags on every `code` subcommand
except the NDJSON evidence streams (`blob-structure`, `coordinate-verify`,
`graph-export`, documented in [entity.md](entity.md)): `--path
<repo-root>` (default cwd), `--format json`, global `--pretty`, `-o <file>`,
`--exclude-dir`
(default `node_modules,.git,dist,build,out,target,.next,__pycache__,.venv,vendor,coverage`
— broader than the root scan's), `--ignore-pattern <pattern>` (gitignore-style,
repeatable), `--no-gitignore`, `--content-mode none|excerpt|full`,
`--cache-dir <path>`, `--no-cache`,
`--max-file-size-bytes <n>`, `--max-lines <n>`, `--no-skip-minified`.
Compiler-backed builds also accept `--typescript-checker
preferred|required|disabled` (default `preferred`).

## Orientation — `occ code map` / `occ code pack`

Token-budgeted, PageRank-ranked output. `map` emits top symbol _signatures_ per
file; `pack` emits file _content_ (optionally compressed). This is the primary
"understand this repo cheaply" tool.

```bash
occ code map  --path . --map-tokens 8000 --tokenizer o200k_base -o map.md
occ code pack --path . --map-tokens 8000 --tokenizer o200k_base -o pack.md
```

Shared map/pack flags: `--map-tokens <n>` (default 4096; alias `--token-budget`),
`--tokenizer heuristic|o200k_base|cl100k_base`, `--map-format markdown|xml|json|plain`,
`--mode map|pack`, `--compress` (pack), `--max-symbols <n>`, `--no-bias-exports`,
`--layout ranked|stable`.

`--layout stable` is for embedding the map in a **cached prompt layer**:
path-ordered entries, no rank scores in the rendering, volatile counts in a
constant tail block (truncate markdown at the final `---` for a fully static
prefix). Byte-identical across runs on an unchanged index — including cold vs
warm cache, which ranked JSON is not (`meta.loadSource` flips) — and churn
stays confined to changed files' blocks. Rank still decides admission. Gate on
`health.features?.['code.map.stableLayout.v1'] === true`.

The ceiling measures the complete selected rendering, including headers,
separators, footers, metadata, and the trailing newline. Repo-map JSON is
compact by default; global `--pretty` is also priced exactly. Its
`entries[].tokens` measures each selected JSON entry rather than a markdown
projection.
Code-command JSON payloads (maps, find, analyze, facts, tsquery, pattern,
dirtree, and the rest) expose `meta.loadSource` as `cache` or `build`; maps
price it inside the measured envelope. A full-content cache entry can satisfy
an excerpt map, and every CLI reuse path validates the manifest first. The
same payloads pair the declared per-language `capabilities` block with
per-language `observedCapabilities` minima and degraded-file counts — observed
evidence (regex fallback, `resolver-join-miss` checker joins) can be lower
than declared support, and only the observed block is proof.

When even the empty map envelope exceeds the budget, the command exits nonzero
with the shared narrowing refusal. Each option scopes `--path` to a directory
whose projected spend comes from the held dirtree rollup; the argv is directly
passable as arguments to `occ`. `projectedTokens` is labeled projection and is
not `tokensUsed`.
Fitted truncation is still a successful, exit-zero map.

Focus the map toward a task (boost relevant files/symbols):
`--query "<text>"`, `--focus-path <path>` (repeatable), `--focus-depth <n>`
(default 1), `--changed-from <ref>`, `--changed-to <ref>`, `--staged`.

```bash
occ code map --path . --query "auth token refresh" --focus-path src/auth --map-tokens 4096
occ code map --path . --changed-from main --map-tokens 4096   # diff-focused map
```

## Directory tree — `occ code dirtree`

Bounded, ignore-aware tree derived from the built code index, not from a raw
filesystem walk. Use this when you need package/folder shape plus truncation
breadcrumbs for drill-in.

```bash
occ code dirtree --path . --format json
occ code dirtree --path . --mode map --map-tokens 4096 --tokenizer o200k_base
occ code dirtree --path . --focus-path src/code --depth 4 --max-entries 25
occ code dirtree --path . --tokens --top 10 --min-tokens 500 --map-tokens 8000 --format json
```

Modes: `compact` (default, collapses single-child directory chains), `verbose`,
and `map` (compact plus top symbol signatures from the highest-ranked file per
directory). JSON output includes `truncatedPaths`; call again with
`--focus-path <path>` and higher caps to drill into an elided subtree.

Add `--tokens` for a source-spend map. Every emitted file or directory then
carries `{tokens, pct, files}`; directory counts are post-order rollups.
`--min-tokens <n>` prunes smaller children and `--top <k>` retains the largest
K children at each directory (both apply only with `--tokens`). `wouldFitBudget` compares the focused subtree's
whole-file token count with `--map-tokens`. The default count is heuristic;
choose `--tokenizer o200k_base` or `cl100k_base` for exact BPE counts. JSON also
states index freshness, output truncation, and how many files had full content
available for counting.

## Architecture — `occ code clusters` / `occ code flows`

Use `clusters` for deterministic current-checkout module communities over the
resolved local-import graph. A cluster has a stable `cluster1:` id, member
paths, size, cohesion (unique internal edges / all unique incident edges),
path-derived keywords/label, externally reached exported entry points, and
cross-cluster dependency counts. Only multi-file clusters are
published. Bounds (`--limit`, `--max-members`, `--max-entry-points`,
`--max-dependencies`) never change ids and every omission plus parser/import
coverage gap is counted.

Use `flows` for deterministic bounded BFS traces over resolved call edges from
ranked exported function/class entry points. Ranking applies 2× for no local
importers, 1.5× for framework paths/basenames, and 1.2× for the required export
kind. Each stable `flow1:` trace carries
node ids, conservative spans, depth, linked cluster ids, proved back-edge
`cycleEdges` split from shared-callee `revisitedEdges`, and frontier
omissions. Tune `--limit`, `--max-candidates`, `--max-depth`,
`--max-branching`, and `--max-steps`; read parser/resolver coverage before
treating absence as proof.

```bash
occ code clusters --path . --format json
occ code flows --path . --max-depth 8 --max-branching 4 --format json
```

Feature-detect with `code.moduleClusters.v1` and `code.flowTraces.v1`.

## Search — `occ code find <mode>`

- `occ code find fused "<query>"` — combines name + pattern + content search with
  rank fusion (`--weights name:3,pattern:2,content:1`). Best when unsure.
  Add `symbols:2` to the weights for the camelCase-aware fuzzy arm (`fmtNm` →
  `formatName`, with `symbolMatch` highlight positions), and `--page-rank` to
  blend graph importance as a bounded ×2 multiplier (results report the applied
  `pageRank`). Both opt-in; unknown weights keys are rejected. Gate on
  `health.features?.['code.find.fused.symbols.v1']` / `['code.find.fused.pageRank.v1']`.
- `occ code find name <name>` — exact symbol name. `--file <path>` to disambiguate, `--type <node-type>`.
- `occ code find pattern <substr>` — substring match on names.
- `occ code find type <nodeType>` — list all nodes of a type (`file|module|function|class|interface|type-alias|enum|variable`).
- `occ code find content <text>` — full-text search (auto-upgrades to `--content-mode full`).

All accept `--limit <n>` (default 50) and `--format json`.

`find name` and `find fused` also accept `--inline-context <n>` (default 0)
and score-free `--citations` / `--format citations`. `--citations` cannot be
combined with `--format json` — the command errors; use `--format citations`
for machine-readable citation rows. Citation rows are
`path:start-end kind name (mechanical note)` plus a coverage footer; zero hits
state absence, and identifier-only results disclose that grep would suffice.
Inline source comes from held index content or from working-tree bytes whose
size and SHA-256 match the parsed manifest. A mismatch returns
`inline-context-stale` and no source block.

## Structural facts — `occ code facts`

List the fixed predicate roster before choosing one:

```bash
occ code facts --list
occ code facts exported-unreferenced --path . --format json
occ code facts untested-entrypoints --path . --limit 20 --format json
occ code facts cycle-members --path . --format json
occ code facts orphan-modules --path . --format json
```

`untested-entrypoints` uses entity-impact test reachability when its cache is
available. If that path cannot be constructed, it falls back to reverse local
import reachability and sets `bestEffort: true`; read `honesty` and
`diagnostics` before treating an absence as complete.

All absence-based relationship facts are capability-gated. Import-dependent
predicates exclude languages without static local-import resolution and name
each refusal in both `diagnostics` and typed `capabilityGaps`; a supported
language with zero resolved local imports stays answerable at best effort.
`exported-unreferenced` excludes languages that produced calls but resolved
none, while retained rows report `unresolvedCallEdgesNamingSymbol`. Always
read `honesty.unresolvedCallEdges` and `honesty.coverage`; gate this contract on
`health.features?.['code.facts.capabilityGate'] === true`. Unresolved call
edges include deliberately withheld dynamic dispatch
(`parserRefusals.dynamicDispatch`, diagnostic `dynamic-dispatch-refused`) — a
refusal to guess a callee, not a missing relationship.

`layer-violations` is never inferred. Pass an explicit JSON manifest:

```json
{
  "layers": [
    { "name": "foundation", "paths": ["src/foundation/**"], "allow": [] },
    { "name": "services", "paths": ["src/services/**"], "allow": ["foundation"] }
  ]
}
```

```bash
occ code facts layer-violations --layers layers.json --format json
```

Same-layer imports are allowed. `allow` lists cross-layer targets; `["*"]`
allows every declared layer. Overlapping path assignments and unknown allowed
layer names are rejected instead of guessed. Programmatic forms:
`queryCodeFacts(index, predicate, options)`,
`createOcc().code.facts(index, predicate, options)`, and
`session.facts(predicate, options)`.

## Structural queries — `occ code ast` / `occ code tsquery`

Reach for a structural query when the question is about a code _shape_ rather
than a name: "every `await` inside a `catch`", "switch statements without a
`default`", "calls whose third argument is a literal". For a known symbol name
prefer `find name` / `doc` / `source`; for plain text prefer `rg`. Structural
queries are the rung between those two — they match the parse tree, so
formatting and identifier choice do not matter.

Use `ast` to discover the grammar's node names, then pass a tree-sitter
S-expression to `tsquery`:

```bash
occ code ast --lang typescript --snippet 'function run() {}'
occ code ast src/component.tsx --path . --map-tokens 2000
occ code tsquery --lang typescript --query '(function_declaration) @function' --path . --limit 20 --map-tokens 4096 --format json
occ code tsquery --lang typescript --query-file query.scm --file src/code --lines 100:400 --format json
```

Quoting-heavy queries read better from a file: `--query-file <path>` (or `-`
for stdin) replaces the inline `--query` string. `--file <path>` scopes the
query to one file or directory subtree, and `--lines <start:end>` keeps only
matches fully inside a 1-based line range — both are enforced by the query
cursor rather than post-filtered, and both are echoed back under `scope` in
JSON output. The built-in predicates `#eq?`, `#match?`, and `#any-of?` work
inside queries.

Text output always ends with `N capture(s) in M/K file(s); coverage=<verdict>`,
including zero-hit queries. A truncated source index also emits a note before
that footer, so silence is never presented as verified absence.

For recovered syntax, treat `honesty.syntaxErrorFiles` as the complete
file-level signal. Detailed syntax diagnostics are deliberately bounded to the
recovery subtrees and are a sample, not an exact count of every CST error node.

JavaScript, TypeScript, and TSX use their vendored grammars only on this
explicit surface; ordinary symbol extraction remains on the TypeScript
compiler API. Each capture includes its source span and, where containment is
unique, the smallest containing indexed `nodeId` for follow-up source, caller,
impact, or context queries. `--limit` bounds returned captures and
`--map-tokens` bounds their serialized payload; opt-in `--budget-early-exit`
stops post-match work once the budget is exhausted, at the cost of possibly
skipping a smaller later capture. JSON `honesty` reports partial
grammar scans, omitted captures, unjoined captures, and ambiguous span joins.

Programmatic forms: `queryTreeSitter(index, options)`,
`createOcc().code.tsquery(index, options)`, `session.tsquery(options)`, and
`parseTreeSitterAst(options)` / `createOcc().code.ast(options)`.

## Pattern matching — `occ code pattern` / `occ code facts --rules`

Prefer `pattern` over `tsquery` when the question can be written as example
code: patterns use `$META` (one node) and `$$$MULTI` (zero or more nodes)
metavariables instead of grammar node names, so no `ast` discovery step is
needed. A `--rule-file` unlocks the full ast-grep rule object — relational
(`inside`, `has` with `stopBy`), composite (`all`, `any`, `not`), `kind`,
`regex`, and per-metavariable `constraints` — which express negation and
cross-node logic that raw S-expressions cannot.

```bash
occ code pattern --lang typescript --pattern 'JSON.parse($A)' --path . --file src --format json
occ code pattern --lang typescript --rule-file rule.json --path . --format json
occ code facts --rules rules.json --path . --format json
```

Matches carry captured metavariables, join to indexed `nodeId`s exactly like
`tsquery` captures, and report the same `honesty` block plus an `engine`
stamp. `--rules` on `facts` evaluates a JSON manifest of named rules
(`{rules: [{id, language, rule, message?, constraints?, utils?, files?}]}`)
as user-defined fact predicates — OCC never infers the rules. Metavariable
names are `[A-Z_][A-Z0-9_]*`; the `regex` clause is Rust regex syntax (no
lookbehind/backreferences); patterns must parse as one complete node. For
`--lang php`, string patterns are refused (the php grammar parses bare text
as inline HTML) — use an object pattern
`{"context": "<?php ...", "selector": "<node-kind>"}` in a rule file, or
`kind`/`regex`/relational clauses. The engine is read-only: nothing is ever
rewritten.

Pattern text output has the matching footer form,
`N match(es) in M/K file(s); coverage=<verdict>`, after all diagnostics.
Pattern and custom-rule scans share `tsquery`'s opt-in `--budget-early-exit`
work bound.

`--rules`, `--rule-file`, and `--query-file` resolve relative paths from the
invoking working directory, independently of `--path`. Pass `-` for bounded
stdin input (64 KiB maximum).

Programmatic forms: `queryCodePattern(index, options)`,
`createOcc().code.pattern(index, options)`, `session.pattern(options)`, and
`queryCustomCodeFacts(index, manifest, options)` /
`createOcc().code.rulesFacts`. Gate on
`health.features?.['code.pattern'] === true`. Over MCP, the same surface is
the read-only `occ_pattern` tool.

## Contract reads — `occ code doc`

Use `doc` before `source` when a signature, leading comment, parameter order,
or body price is enough. It returns `signature`, `docComment`, `params`, and
`bodyTokens`, but never the body.

```bash
occ code doc buildRepoMap --path . --format json
occ code doc buildRepoMap --path . --file src/code/map.ts --tokenizer o200k_base --format json
occ code doc --path . --batch < queries.json
occ code doc --path . --queries-json queries.json --format json
occ code doc --path . --queries-json queries.json --format json --compact-honesty
```

Single queries disambiguate with `--node-id`, `--file`, `--kind`, and
`--container`. Batch queries are `{nodeId}` or
`{name, relativePath?, kind?, containerName?}`; results remain positionally
aligned and preserve `not_found`/`ambiguous` entries. TypeScript, JavaScript, and Vue use the compiler path; vendored
tree-sitter languages collect contiguous leading comments. A missing grammar
that forces regex fallback reports `unsupported`. JSON includes an honesty
block covering freshness, truncation, source coverage, and ambiguity.
Full per-result honesty remains the default. For large JSON batches,
`--compact-honesty` emits one measured envelope baseline and an `honestyDelta`
on every result whose effective values differ; merge the delta into the
baseline before judging that result.

Programmatic forms: `readCodeDocs(index, queries)`,
`createOcc().code.doc(index, queries)`, and `session.readDocs(queries)`. Gate on
`health.features?.['code.doc'] === true`.

## Source reads — `occ code source`

Use `source` when you already know the symbol and need its exact body without
reading the whole file. Prefer this for named symbols; use `rg`/shell reads for
text, config, and quick facts.

```bash
occ code map --path . --map-format json --map-tokens 4096 -o map.json
occ code source --path . --node-id "<nodeId>" --format json
occ code source bootstrap --path . --file src/main.ts --type function --format json
```

JSON repo-map symbols include `nodeId`, `endLine`, and `containerName`.
Exact-span parsers emit `node2:<type>:<absolute-path>:<startByte>:<endByte>`;
legacy line-derived ids remain accepted as lookup aliases when unambiguous.
Byte positions are part of the address, so ids can change after edits; re-run
`code map` or `code find name` after moving a symbol.

## Symbol drift — `occ code symbol-hash`

Hash symbol bodies by a stable, line-independent key
(`{relativePath, name, kind?, containerName?}`). Node ids embed the line, so
they churn on any edit above the symbol; symbol keys do not. Persist the
returned top-level `bodyHash`; it remains the frozen full 64-hex sha256 of the
legacy full-line slice. Compiler and Tree-sitter symbols also return
`exactSpanHash`, a sha256 of the parser-proved UTF-8 byte span. The versioned
`hashes` tuple carries both identities plus normalized and structural tiers.

```bash
occ code symbol-hash --path . --file src/main.ts --name bootstrap --format json
occ code symbol-hash --path . --queries-json queries.json --format json   # batch; - reads stdin
```

Pass the legacy three-hash tuple back as `expected`; include `exactSpanHash`
(or `--expected-exact-span-hash`) when available so same-line neighbours cannot
cause false drift. The resulting `verdict` is `fresh`, default
`normalized-equal`, `semantic-drift`, `gone`, or `unknown-tier`;
`--no-normalized-equal-verdict` requests the permanently decodable legacy
`cosmetic-drift` label. `normalized-equal` means only that body bytes
changed while the frozen normalizing lexer emitted the same tokens—not a
semantic no-op. `semantic-drift` means those normalized tokens differ—not that
runtime behavior differs. Escape spellings such as `"\n"` and `"n"` can
collide under this frozen hash version, so never gate semantics on normalized
equality. Declaration-only parsers have `algo: "none"` and never guess a
verdict. `--resolve-gone` is opt-in and consults entity lineage for a
rename/move successor; the ordinary path never builds an entity session.

Per-query statuses: `resolved` / `not_found` / `ambiguous` (with candidates —
add `--kind` or `--container` to disambiguate) / `error`. Batch entries are
independent; results align positionally with the queries. Any non-resolved
result exits nonzero. `spanExact: false` means the parser only gave a
declaration line (regex-fallback languages) — fall back to file-level hashing.

## Syntax checks — `occ code check`

Use `check` as a lightweight post-edit parse gate before wider tests. It supports
TS/JS (`.ts`, `.tsx`, `.mts`, `.cts`, `.js`, `.jsx`, `.mjs`, `.cjs`, `.es6`),
Vue SFCs, Python, and the vendored tree-sitter languages (Go, Rust, Java,
C/C++, C#, Kotlin, Scala, Swift, Ruby, PHP); unsupported files exit 0 with
`status: "unsupported"` so they do not fail CI accidentally. Vue SFC analysis
also extracts statically bound component tags and interpolation / `v-on` /
`v-bind` identifiers as resolved usage edges with original-SFC spans. Dynamic,
global, ambiguous, shadowed, or otherwise unprovable targets never become
guessed edges; their typed `parserRefusals.vueTemplate` buckets keep
`templateUses` partial. A script-less SFC still reports `vue-script-absent`.

```bash
occ code check src/main.ts --format json
occ code check src/App.vue --format json
```

`occ code check` exits nonzero only when `valid` is `false`.

## Relationships — `occ code analyze <kind>`

- `occ code analyze calls <fn>` — what a function calls (outgoing).
- `occ code analyze callers <fn>` — what calls a function (incoming, impact analysis).
- `occ code analyze chain <fromFn> <toFn>` — call paths between two functions (`--depth <n>`, default 5).
- `occ code analyze deps <target>` — module/file import relationships (local/external/unresolved).
- `occ code analyze coupling <target>` — module-level coupling metrics.
- `occ code analyze tree <className>` — class/interface inheritance.

`calls`/`callers`/`tree` accept `--file <path>` to disambiguate. Relationships
report `resolved` / `ambiguous` / `unresolved` status explicitly.
`callers` and `deps` accept `--inline-context <n>` around each call/import
reference.

## Seams — `occ code seams`

Enumerate cross-module seams: import/call edges between directory-modules,
optionally weighted by git co-change. Use it to find the strongest ungoverned
relationships in a repo and to durably reference one.

```bash
occ code seams --path . --since "90 days ago" --limit 20 --format json
occ code seams --path . --resolve "seam:src::src/code" --inline-context 1 --format json
```

Each seam carries `seamKey` (`seam:` + both modules sorted, `::`-joined),
`importEdgeCount`, `callEdgeCount`, optional `cochange {count, lift,
lastCochangedAt}`, and `rank`. `--since` aggregates co-change over full HEAD
history bounded by the window and works with `--path` below the git toplevel.
`--min-lift <n>` filters by lift (needs `--since`); `--resolve` accepts one or
more seam keys, answers `resolved`/`missing` per key, and exits nonzero when
anything is missing. A
directory rename changes the key by design — treat `missing` as drift, never
as clean.
Use `--inline-context <n>` to attach verified source around one representative
cross-module edge for each returned seam.

## Change-aware — `occ code diff` / `occ code history`

```bash
occ code diff --base main --map-tokens 4096 --format json   # which symbols changed
occ code history buildRepoMap --format json                 # git line history for a symbol
```

`code diff` flags: `--base <ref>`, `--head <ref>`, `--staged`, `--range-mode
merge-base|exact` (default `merge-base`; `exact` compares the endpoint trees
directly), `--map-tokens <n>` (default 4096), `--tokenizer`. See also
[git.md](git.md) for raw patches.

The changed-symbol budget includes the range header, summary, truncation line,
per-file headings, and JSON envelope/escaping when JSON is selected.

## Full index — `occ code index`

Build/dump the full codebase index (files, symbols, edges, capabilities). Heavy;
prefer `map`/`find`/`analyze` for targeted questions. Each `files[].symbols[]`
entry carries a `nodeId`, so a consumer can jump from a file symbol straight to
its graph node (and to `occ code source --node-id <id>`) without scanning
`nodes`.

## Immutable blob structure — `occ code blob-structure`

Use this when the input is an exact Git object rather than the current checkout. Send `{requestId, oid, relativePath}` NDJSON on stdin; OCC emits body-free declarations and syntactic facts plus parser provenance and explicit gaps.

```bash
oid=$(git rev-parse HEAD:src/index.ts)
printf '{"requestId":"index","oid":"%s","relativePath":"src/index.ts"}\n' "$oid" |
  occ code blob-structure --path .
```

The same OID is read once but remains a separate result for every input occurrence. Parsing is keyed by both OID and path because an extension controls the language. Treat `partial` and `unavailable` as evidence gaps, not as an empty source file. Resource bounds are settable per run: `--max-requests`, `--max-blob-bytes`, `--max-blob-lines`, `--max-total-blob-bytes`, `--max-batch-bytes`, and `--max-spans`; `--no-formats` and `--no-skip-minified` mirror the indexer's filters. Add `--require-complete` when either a partial or unavailable result must fail the process.

Blob V2 intentionally contains no lineage or resolved graph. It adds canonical
half-open UTF-8 byte spans and per-result parser capability evidence. When a consumer
also has an entity session, pass the complete event stream through
`collectGitBlobStructureBatch(events)` and then call
`session.resolveBlobLineage({ ref, ...batch })`. The collector consumes through
EOF and rejects missing/duplicate receipts, gapped ordering, corrupt counts, or
events after the footer. Lineage pins one commit, verifies the complete receipt,
each path/OID, and each declaration's available identity-bearing facts before
attaching only historical ids OCC already proved. Persisted V1 receipts remain
readable, but the V2 lineage adapter treats their parser@1, line-only evidence
as incomplete and never attaches a V2 identity. Unframed result-only input is
also never complete. Receipt integrity assumes a trusted local process;
it is not cryptographic authentication of a hostile payload.

## Programmatic surface — for long-running hosts

Editor/agent integrations that embed `occ` — holding an index or a
`CodeQuerySession` across turns instead of shelling out per call — have
in-process equivalents for the verbs above, plus a few probes with no CLI:

- **`searchSymbols(index, query, { limit, kinds, pathFilter })`** /
  `session.searchSymbols(...)` — fuzzy symbol search across name,
  container-qualified name, and file path. Each result carries a `score`, the
  matched `positions`/`span` (for highlighting), and a `nodeId` for a follow-up
  source read. The corpus is memoized per index, so repeated queries in a
  long-lived host pay the build once. Facade: `createOcc().code.searchSymbols`.
  From the shell, reach for `occ code find` instead.
- **`buildCodeContext(index)`** / `session.projectContext()` — project a full or
  slim index down to per-file exported symbols, a deduplicated local import
  graph, and external dependency roots. Pure and synchronous; the shape hosts
  hand to a model or a graph view. Facade: `createOcc().code.context`.
- **Typed graph signatures** — compiler-backed function and method
  `CodeNode.signature` values include parameter types and explicit return
  types. Map, find, current-entity, and context consumers benefit without a
  separate query. Gate on
  `health.features?.['code.index.richSignatures'] === true`.
- **`buildChangedRepoMap(index, { changed: { base, head } | { staged: true }, ...mapOptions })`**
  — the `--changed-from` map on the API: changed files join the focus set and
  admitted entries carry `changed`/`churn`. `toRepoMapChangeContext` /
  `stampRepoMapChanges` are exported for callers that already hold a diff
  summary. Facade: `createOcc().code.mapChanged`.
- **`buildDirectoryTree(index, options)`** / `session.getDirectoryTree(options)`
  / `createOcc().code.directoryTree(index, options)` — bounded directory tree
  over indexed files, with `compact`/`verbose`/`map` modes and
  `truncatedPaths` drill-in hints.
- **`clusterCodeModules(index, options)`** / `session.clusters(options)` /
  `createOcc().code.clusters(index, options)` — deterministic resolved-import
  communities with stable cluster ids and measured coverage/omissions.
- **`traceCodeFlows(index, options)`** / `session.flows(options)` /
  `createOcc().code.flows(index, options)` — bounded resolved-call traces with
  stable flow ids, spans, depth, cluster linkage, and frontier honesty.
- **`hashCodeSymbols(index, queries, options?)`** / `session.hashSymbols(...)`
  — the batch three-tier verification primitive behind `occ code symbol-hash`.
  The frozen `bodyHash` feature key remains valid; gate exact-span baselines on
  `health.features?.['code.symbol.exactSpanHash.v1'] === true`. Facade:
  `createOcc().code.symbolHash`. Gate the `normalized-equal` behavior on
  `health.features?.['code.symbol.verification.v2'] === true`.
- **`readCodeDocs(index, queries, options?)`** / `session.readDocs(...)` —
  contract-only symbol reads with a body token price and no body. Facade:
  `createOcc().code.doc`. Gate on `health.features?.['code.doc'] === true`.
- **`listCodeSeams(index, { cochange?, minLift?, limit? })`** /
  `resolveCodeSeams(index, seamKeys, options?)` / `session.seams(...)` /
  `session.resolveSeams(...)` — seam enumeration and freshness checks. Pure:
  pass a `GitCochangeSummary` from `getGitCochange` to attach co-change (use
  `scope: 'history'` with `since` for a windowed history join, and
  `rebaseCochangeToIndexRoot(summary, prefix)` when the index root sits below
  the git toplevel — git paths are toplevel-relative). Facade:
  `createOcc().code.seams` / `.resolveSeams`; `seamKeyFor(moduleA, moduleB)` is
  exported for key construction. Gate on `health.features?.['code.seams']`.
- **`store.peekMetadata()` / `store.isFresh()`** — probe a persisted
  `CodeIndexStore` without deserializing or parsing. `peekMetadata()` returns the
  on-disk metadata (available before the first `getSession()` of a process);
  `isFresh()` stat-diffs the working tree against the persisted manifest
  (`added`/`modified`/`deleted` counts). Both validate the cache entry belongs to
  this repo, options, and occ version — use them to decide whether to rebuild
  before serving a session.
- **`occ code status`** — read entity-cache head, indexed head, counts,
  truncation, build time, directory, freshness, aggregate cache bytes/entries,
  and superseded roots through the metadata-only store path. It never builds an index. Add `--full` only when complete parser,
  worktree, and truncation status is worth opening or building the entity
  session.
- **`occ cache prune [--max-age <days>] [--max-bytes <n>]`** — the only
  automatic-cache deletion surface. It removes superseded schemas explicitly,
  applies optional last-open/size bounds, and protects an entry held by a live
  store in the same process.
- **`probe(options)`** / `createOcc().probe(options)` — runtime readiness
  without building an index: git availability, repository-scoped entity-cache
  presence, tree-sitter grammar coverage, and per-format document parser
  readiness. Where `health()` reports what the build ships, `probe()` reports
  what will actually work here, right now — use it to explain an empty result
  or precheck a host integration. CLI: `occ probe [directory]`; its heavyweight
  grammar and document-parser checks default off and require `--grammars` /
  `--document-parsers`, while the library defaults remain on.
- **`health().features`** — a map of stable feature identifiers (e.g.
  `code.searchSymbols`, `code.directoryTree`, `store.isFresh`, `code.map.changed`). Feature-detect
  against it (`health.features?.['store.isFresh'] === true`) instead of
  `typeof`-probing when a host must support multiple occ versions.
  CLI: `occ health --format json`.

`createCodeQuerySession(options, onProgress?, signal?)` and
`session.refresh(onProgress?, signal?)` accept an `AbortSignal` for cancellation.
