<h1 align="center">OCC</h1>

<p align="center">
  <a href="https://www.npmjs.com/package/@cesarandreslopez/occ"><img src="https://img.shields.io/npm/v/@cesarandreslopez/occ?label=npm" alt="npm"></a>
  <a href="https://www.npmjs.com/package/@cesarandreslopez/occ"><img src="https://img.shields.io/npm/dt/@cesarandreslopez/occ?label=npm%20Downloads" alt="npm Downloads"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
  <a href="https://github.com/cesarandreslopez/occ/actions/workflows/ci.yml"><img src="https://github.com/cesarandreslopez/occ/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://deepwiki.com/cesarandreslopez/occ"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
</p>

<p align="center">
  <strong>Office Cloc and Count</strong> — document metrics, structure extraction, content inspection, and code exploration for real repositories.
</p>

> **Experimental:** All features in OCC are currently experimental. This project cannot be considered stable software yet. APIs, output formats, and command interfaces may change between minor versions.

## What is this?

OCC started as a way to make office documents visible in the same workflows that already work well for code metrics tools like `scc` and `cloc`. It has since grown into a multi-purpose CLI that can:

- scan office documents for word/page/sheet/slide metrics
- extract document heading structure for navigation and RAG-style use cases
- inspect documents (`occ doc inspect`), spreadsheets (`occ sheet inspect`), and presentations (`occ slide inspect`) for metadata, risk flags, and content previews
- extract structured table content from documents (`occ table inspect`)
- analyze workspaces for combined code, document, and structure metrics (`occ workspace analyze`) and cross-document references (`occ workspace documents`)
- quickly describe whether a directory is a code, office, documentation, data, or mixed project (`occ describe`, `occ workspace describe`)
- summarize code metrics and file-level complexity through `scc`
- explore JavaScript, TypeScript, Vue Single-File Components, Python, Go, Rust, Java, C/C++, Kotlin, and other tree-sitter-backed repositories with symbol search, exact `nodeId` source reads, syntax checks, structural facts and queries, call analysis, dependency inspection, and inheritance queries (`occ code`)
- track git changes, diffs, commit history, churn, and file-level co-change — and map a diff to the code symbols it touches (`occ git`, `occ code diff`, `occ code history`)
- capture immutable repository evidence, emit resumable work episodes, parse exact Git blobs, verify stored coordinates, and export the pinned entity graph without a checkout (`occ git capture`, `occ atoms`, `occ code blob-structure`, `occ code coordinate-verify`, `occ code graph-export`)

## Agent Skills

OCC ships an **Agent Skill** so AI coding agents can automatically learn how to use the CLI. It uses the open `SKILL.md` format read by **Claude Code**, **OpenAI Codex**, and other agents — a single umbrella `occ` skill with a decision/router table covering workspace reconnaissance, office-document and table triage, and code exploration, plus on-demand reference files for deeper detail. Humans can read the same files as concise CLI recipes.

The skill ships inside the package (`node_modules/@cesarandreslopez/occ/skills/`). Install it explicitly into your agent(s):

```bash
# Install for all supported agents into your user skills dir
occ skills install            # ~/.claude/skills/occ and ~/.codex/skills/occ

# Project-local install (per-repo, checked in if you like)
occ skills install --project  # ./.claude/skills/occ

# Pick one agent, force overwrite, or symlink for live updates
occ skills install --agent claude --force
occ skills install --link

# Inspect what's bundled
occ skills list
occ skills path
```

Claude Code users can also install it as a plugin straight from git:

```text
/plugin marketplace add cesarandreslopez/occ
/plugin install occ@occ
```

After install the skill lands at `<skills-dir>/occ/SKILL.md` and your agent surfaces it automatically when a task involves exploring a repository or office documents.

## Features

- **Office document metrics** — words, pages, paragraphs, slides, sheets, rows, cells
- **Seven formats supported** — DOCX, XLSX, PPTX, PDF, ODT, ODS, ODP
- **Document structure extraction** — `--structure` parses heading hierarchy into a navigable tree with dotted section codes (1, 1.1, 1.2, ...)
- **Document inspection via `occ doc inspect`** — metadata, risk flags, content stats, heading structure, and content preview for DOCX and ODT
- **Spreadsheet inspection via `occ sheet inspect`** — workbook properties, hidden sheets, names, formulas, links, comments, schema preview, and token estimates for XLSX and ODS
- **Presentation inspection via `occ slide inspect`** — metadata, risk flags, per-slide inventory, and content preview for PPTX and ODP
- **Table extraction via `occ table inspect`** — structured table content from DOCX, XLSX, PPTX, ODT, and ODP with auto-detected headers, sample row limits, and merged cell support
- **Code metrics via scc** — auto-detects code files and integrates scc output, including file-level `Complexity` where scc provides it
- **Code exploration via `occ code`** — JS/TS, Vue SFC, Python, Go, Rust, Java, C/C++, Kotlin, and other tree-sitter-backed symbol lookup, exact `nodeId` source reads with `occ code source`, syntax checks with `occ code check`, content search, callers/callees, dependency categories, inheritance, module coupling, and ambiguity-aware chains
- **Verified inline references and citations** — `--inline-context N` attaches bounded source around find, caller, dependency, seam, impact, and context references; reduced indexes read disk only after size+SHA-256 verification. `find name` and `find fused` also support score-free `--citations` / `--format citations` with mechanical graph notes and explicit zero-hit coverage.
- **Repository map / pack via `occ code map` / `occ code pack`** — token-budgeted, PageRank-ranked repo map (top symbol signatures per file) or content pack, with a pluggable heuristic or BPE (`o200k_base` / `cl100k_base`) tokenizer for exact complete-rendering budgets across markdown, plain text, XML, and compact JSON, opt-in query/path focus (`--query`, `--focus-path`, `--focus-depth`) to bias the map toward a specific task, and structured per-directory narrowing projections when even the empty envelope cannot fit
- **Persistent CLI code indexes** — code exploration commands validate a stat manifest and reuse the sectioned index outside the repository; tokenizer/content-digest rows also preserve exact `dirtree --tokens` counts across processes. JSON maps and query envelopes report `meta.loadSource` as `cache` or `build`, `--no-cache` opts out, and `occ cache prune` explicitly bounds age or disk use without deleting an entry held by a live store
- **Workspace analysis via `occ workspace`** — fast directory description plus combined code, document, and structure analysis with versioned JSON contracts, per-document summaries, and cross-reference detection
- **Directory tree via `occ code dirtree`** — bounded, ignore-aware trees from the built code index with focus drill-in, map-mode symbol annotations, and optional per-path source-token rollups for budget preflight
- **Contract reads via `occ code doc`** — signature, leading documentation, parameter list, and body token price for one or many symbols without returning their bodies
- **Symbol verification via `occ code symbol-hash`** — preserves the frozen full-line sha256, adds a byte-exact span hash where the parser can prove one, and emits versioned normalized and structural tiers; replay an expected tuple for a mechanical verdict. Normalized-token equality reports `normalized-equal` by default (`--no-normalized-equal-verdict` restores the permanently decodable `cosmetic-drift` label), and `--resolve-gone` can consult lineage
- **Module clusters and code flows via `occ code clusters` / `occ code flows`** — deterministic, bounded current-checkout architecture receipts over resolved imports and calls, with stable ids, cluster cohesion/entry points/dependencies, multi-step flow spans/depth/cluster linkage, and explicit parser, resolver, budget, and output omissions
- **Seam enumeration via `occ code seams`** — cross-module import/call relationships with durable order-independent `seamKey`s, optional git co-change weighting (`--since`), lift/importance ranking, and `--resolve` freshness checks where a missing key is surfaced as drift
- **Git context via `occ git`** — changed files, diff summaries and token-bounded patches, commit/file history, churn hotspots, and file-level co-change over a typed, shell-injection-safe git client; plus git-aware code (`occ code diff`, `occ code history`, `occ code map --changed-from`) that maps a diff to the code symbols it touches
- **Immutable Git evidence** — `occ git capture` streams every reachable commit, parent delta, and pinned-tree entry with explicit coverage; `occ code blob-structure` projects exact Git blobs into body-free declarations and syntactic facts without consulting the working tree
- **Deterministic work episodes via `occ atoms`** — streams one source-body-free record per parent-child edge with Git coordinates, branch-aware run lineage, exact patch-payload measures, exact revert edges, changed module pairs, pinned `ent1:*` head mappings, resumable cursors, and a verified coverage receipt
- **Pinned entity graph export** — `occ code graph-export` emits observed lineage nodes, explicit import/call module seams, and entity-pair edges with parent-edge co-change count/lift, directed call/inheritance incidence, and unavailable historical structure
- **Committed blob lineage composition** — `collectGitBlobStructureBatch` preserves the complete header/results/footer receipt, then entity-session `resolveBlobLineage` pins one commit, verifies the receipt and declarations against its physical tree and historical state, and attaches only lineage ids OCC already proved; legacy result-only input stays accepted but can never claim complete coverage
- **Entity intelligence via `occ code entities` / `impact` / `blame` / `log` / `context`** — tracks functions, methods, classes, and data-format keys across renames, moves between files, and container changes, giving each a durable lineage id. Entity-search JSON uses the detailed measured envelope by default (`--no-envelope` restores the legacy bare array); `search()` and `searchDetailed()` keep their explicit library contracts. Entity-record diff proves logic drift only from compatible manifest-pinned CST evidence whose physical grammar bytes were re-verified in the current process; otherwise it reports changed bodies as unknown. It scopes with `--file` and pairs with the whole-diff proof for an opt-in `--exit-code` on proved structural drift; impact finds affected tests by reverse call traversal rather than filename similarity and returns each with a runnable selector; blame attributes each entity conservatively; context returns a token-budgeted bundle of an entity plus what it calls and what calls it, with role-derived narrowing commands when its fixed envelope cannot fit. History is cached incrementally outside the repository
- **Entity hotspots via `occ code hotspots`** — rank current code entities by proved logic-changing lineage events multiplied by token count or line span, preserve unknown events, retain the historical cosmetic count only as a numeric JSON compatibility field, and optionally blend normalized PageRank without hiding bounded-window births, result-limit omissions, ambiguity, or wide evidence gaps
- **Entity temporal coupling via `occ code cochange [entity]`** — find functions whose proved logic changes land in the same commits even when they share a file or no import edge, using rename-surviving lineage ids and explicit count/window denominators plus measured omissions, ambiguity, and wide evidence gaps
- **Documentation/entity drift via `occ code drift` / `drift-documents`** — join unfenced Markdown identifiers to unique exported declarations (or explicit `path#symbol` targets), using either repository section history or caller-supplied `{content, baseCommit}` documents, and surface every refusal instead of treating unresolved prose as verified freshness
- **Memory anchors via `occ code anchor` / `occ code verify-anchors`** — capture one entity as a verifiable anchor (durable lineage id, symbol key, and a hash tuple, with `baseCommit` stamped only when capture proves the committed pairing against a reconciled working tree) and later grade stored anchors with one proved verdict each — `fresh`, `normalized-equal`, `semantic-drift`, `moved`, `renamed`, `deleted`, or fail-closed `unknown` — so an external memory system can invalidate stale claims without OCC ever storing them
- **Prefix-stable repo maps via `occ code map --layout stable`** — path-ordered, score-free rendering with volatile counts in a constant tail block, byte-identical across runs (cold or warm cache) on an unchanged index and churn-localized when code changes, for embedding a repo slice in a cached prompt layer; stable JSON is a relocatable documented projection (`RepoMapStableDocumentSchema`)
- **Fused retrieval upgrades** — `occ code find fused` optionally adds the camelCase-aware fuzzy scorer as a fourth rank-fusion arm (`--weights …,symbols:N`) and blends graph PageRank as a bounded, derivable multiplier (`--page-rank`); `occ code entities --fuzzy` brings the same subsequence matching to durable entities with exact-name precedence preserved
- **Whole-diff verification via `occ code diff --entities --exit-code`** — every entity diff reports the legacy entity-record summary and an authoritative `whole-file-cst-v4` proof over every raw changed-file record; V4 binds checked-in grammar-WASM and trivia-policy digests and proves ordinary comments plus whitespace in safe grammars as `cosmetic-change`, while trivia-only changes beside directives, BOM/encoding changes, unsafe grammars, and missing evidence remain `unknown`. The opt-in exit code still fails only for proved non-trivia structural drift; `--fail-on-unknown` additionally fails on unknown whole-diff evidence or partial obligation coverage
- **Verification obligations via `occ code diff --obligations`** — compose semantic changes with reverse test reachability and current module seams, returning untested logic gaps, touched `seamKey`s, and a numeric JSON compatibility split whose unprovable cosmetic arm is omitted from text; with `--exit-code`, only a proved untested logic gap fails
- **Structural facts via `occ code facts`** — list and evaluate bounded index predicates for unreferenced exports, untested entry points, import cycles, orphan modules, and explicit layer-manifest violations; relationship-dependent absence claims exclude unsupported languages through typed capability gaps, count unresolved calls, and downgrade incomplete evidence instead of fabricating a full result
- **Tree-sitter queries via `occ code tsquery` / `occ code ast`** — run bounded S-expression queries over vendored grammars, including TS/TSX/JS, from an inline string, a `--query-file`, or stdin; scope with `--file` and `--lines`; print parse trees to discover node names, and join captures to indexed `nodeId`s by source-span containment. The opt-in `--budget-early-exit` bounds post-match work at the cost of possibly skipping a smaller later capture
- **Pattern matching via `occ code pattern` / `occ code facts --rules`** — match code-shaped ast-grep patterns (`console.log($$$ARGS)`) and full rule objects (relational `inside`/`has`, composite `all`/`any`/`not`, per-metavariable `constraints`) over the same vendored grammars, join matches to indexed `nodeId`s, and evaluate user-defined JSON rule manifests as custom fact predicates. The vendored WASM engine is read-only and digest-pinned; it never rewrites anything. Pattern and custom-rule scans share the explicit `--budget-early-exit` work bound
- **Cheap runtime diagnostics via `occ health`, `occ probe`, and `occ code status`** — inspect the static feature manifest, opt into heavyweight grammar/document-parser readiness checks, or read entity-cache freshness and bounds without triggering an index build; `occ code status --full` explicitly pays for complete session status
- **Honest root-scan JSON and zero-hit text** — root JSON always distinguishes `code: null` from an empty scc result and carries `skippedFiles` plus diagnostics; structural-query and pattern text always ends with file coverage, even when there are no matches
- **MCP server via `occ mcp`** — the same capabilities over a non-resident stdio Model Context Protocol server, as thirteen `occ_*` tools: no daemon, no network, no telemetry, exits when the client disconnects, and refuses paths outside the repository it was started against. It re-checks freshness before each call so a long-lived server does not go stale, reports count-based cold-build progress to clients that request it, and offers an ambiguity-safe targeted source read
- **Multiple output modes** — grouped by type, per-file breakdown, or JSON
- **CI-friendly** — ASCII-only, no-color mode for pipelines
- **Flexible filtering** — include/exclude extensions, exclude directories, .gitignore-aware
- **Progress bar** — with ETA for large scans
- **Agent Skills** — ships a universal `SKILL.md` skill (Claude Code + OpenAI Codex) installable via `occ skills install`
- **Zero config** — auto-downloads scc binary on install, works out of the box

## Quick Start

**Requires Node.js 22.3 or later.** Node 24 is supported and tested. OCC's PDF
support loads `pdfjs` through `process.getBuiltinModule`, which arrived in 22.3;
on anything older the PDF parser fails to load. Node 18 and 20 are not supported
as of 0.15.0 — both are past end-of-life.

**Global install:**

```bash
npm i -g @cesarandreslopez/occ
occ
```

**No-install usage:**

```bash
npx @cesarandreslopez/occ docs/ reports/
```

**From source:**

```bash
git clone https://github.com/cesarandreslopez/occ.git && cd occ
npm install
npm run build
npm test
npm start
```

## Usage

```bash
# Scan current directory
occ

# Scan specific directories
occ docs/ reports/

# Per-file breakdown
occ --by-file docs/

# JSON output
occ --format json docs/

# Indented JSON for a human reader (machine JSON is compact by default)
occ --format json --pretty docs/

# Static features, cheap runtime readiness, and metadata-only cache freshness
occ health --format json
occ probe . --format json
occ code status --path . --format json
occ cache prune --max-age 30

# Explicitly load heavyweight probes or build full entity status when needed
occ probe . --grammars --document-parsers --format json
occ code status --path . --full --format json

# Extract document structure (heading hierarchy)
occ --structure docs/

# Structure as JSON
occ --structure --format json docs/

# Inspect a document for metadata, risk flags, and content preview
occ doc inspect report.docx
occ doc inspect report.docx --format json

# Inspect an XLSX or ODS workbook before reading its contents deeply
occ sheet inspect finance.xlsx
occ sheet inspect finance.xlsx --format json --sample-rows 3 --max-columns 12

# Inspect a presentation for slide inventory and content preview
occ slide inspect deck.pptx
occ slide inspect deck.pptx --format json --slide 3

# Extract structured table data from documents
occ table inspect report.docx --format json
occ table inspect finance.xlsx --table 1 --sample-rows 10

# Explore JS/TS and Python code
occ code find name UserService --path .
occ code analyze callers createUser --path .
occ code analyze deps src/deps --path .
occ code analyze chain ambiguousCaller duplicate --path .

# Read one symbol body by nodeId, then check changed-file syntax
occ code map --path . --map-format json --map-tokens 4096
occ code source --path . --node-id "function:/abs/repo/src/main.ts:bootstrap:3" --format json
occ code check src/main.ts --path . --format json

# Module coupling metrics
occ code analyze coupling src/code --path .

# Dump full codebase index as JSON
occ code index --path . --format json

# Token-budgeted, PageRank-ranked repo map (signatures) and pack (content)
occ code map --path . --map-tokens 4096
occ code pack --path . --map-tokens 8192 --tokenizer o200k_base
occ code dirtree --path . --mode map --map-tokens 4096

# Git-aware code: which symbols a diff touched, and a diff-focused repo map
occ code diff --base main --map-tokens 4096
occ code history UserService --limit 10
occ code map --path . --changed-from main --map-tokens 4096

# Inspect git changes, history, and churn
occ git changed --base main
occ git diff --base main --patch --map-tokens 2048
occ git history src/cli.ts --limit 10
occ git churn --sort churn --limit 20
occ git cochange --target src/cli.ts --limit 20

# Workspace-level analysis (code + documents + structures)
occ workspace analyze --format json

# Quick directory classification
occ describe .
occ workspace describe --format json

# Document summaries with cross-references
occ workspace documents --format json

# Only specific formats
occ --include-ext pdf,docx docs/

# Skip code analysis
occ --no-code docs/

# CI-friendly (ASCII, no color)
occ --ci docs/
```

## Example Output

```
-- Documents ---------------------------------------------------------------
  Format    Files    Words    Pages                  Details      Size
----------------------------------------------------------------------------
  Word         12   34,210      137              1,203 paras    1.2 MB
  PDF           8   22,540       64                             4.5 MB
  Excel         3                                12 sheets      890 KB
----------------------------------------------------------------------------
  Total        23   56,750      201              1,203 paras    6.5 MB

-- Code (via scc) ----------------------------------------------------------
  Language    Files    Lines   Blanks  Comments     Code
----------------------------------------------------------------------------
  JavaScript     15     2340      180       320     1840
  Python          8     1200       90       150      960
----------------------------------------------------------------------------
  Total          23     3540      270       470     2800

Scanned 23 documents (56,750 words, 201 pages) in 120ms
```

### Structure Output (`--structure`)

```
-- Structure: report.docx --------------------------------------------------
1   Executive Summary
  1.1   Background ......................................... p.1
  1.2   Key Findings ....................................... p.1-2
2   Methodology
  2.1   Data Collection .................................... p.3
  2.2   Analysis Framework ................................. p.4
    2.2.1   Quantitative Methods ........................... p.4
    2.2.2   Qualitative Methods ............................ p.5
3   Results ................................................ p.6-8
4   Conclusions ............................................ p.9

4 sections, 10 nodes, max depth 3
```

## Supported Formats

| Format     | Extension | Metrics                    | Structure               |
| ---------- | --------- | -------------------------- | ----------------------- |
| Word       | `.docx`   | words, pages\*, paragraphs | Yes                     |
| PDF        | `.pdf`    | words, pages               | Yes (with page mapping) |
| Excel      | `.xlsx`   | sheets, rows, cells        | —                       |
| PowerPoint | `.pptx`   | words, slides              | Yes (slide headers)     |
| ODT        | `.odt`    | words, pages\*, paragraphs | Yes (best-effort)       |
| ODS        | `.ods`    | sheets, rows, cells        | —                       |
| ODP        | `.odp`    | words, slides              | Yes (slide headers)     |

\* Pages for Word/ODT are estimated at 250 words/page.

## CLI Flags

| Flag                         | Description                                    | Default             |
| ---------------------------- | ---------------------------------------------- | ------------------- |
| `--by-file` / `-f`           | Row per file                                   | grouped by type     |
| `--format <type>`            | `tabular` or `json`                            | `tabular`           |
| `--pretty`                   | Indent machine JSON for human reading          | off                 |
| `--structure`                | Extract and display document heading hierarchy | off                 |
| `--include-ext <exts>`       | Comma-separated extensions                     | all supported       |
| `--exclude-ext <exts>`       | Comma-separated to skip                        | none                |
| `--exclude-dir <dirs>`       | Directories to skip                            | `node_modules,.git` |
| `--ignore-pattern <pattern>` | Gitignore-style pattern to ignore (repeatable) | none                |
| `--no-gitignore`             | Disable .gitignore respect                     | enabled             |
| `--sort <col>`               | Sort by: files, name, words, size              | `files`             |
| `--output <file>` / `-o`     | Write to file                                  | stdout              |
| `--ci`                       | ASCII-only, no color                           | off                 |
| `--large-file-limit <mb>`    | Skip files over this size                      | `50`                |
| `--no-code`                  | Skip scc code analysis                         | off                 |
| `--show-confidence`          | Show confidence levels for each metric         | off                 |
| `--quick`                    | Count files and bytes without parsing          | off                 |
| `--token-budget <n>`         | Hard ceiling for the complete emitted output   | unbounded           |
| `--tokenizer <name>`         | Counter for `--token-budget`                   | `heuristic`         |

## Code Exploration

`occ code` adds on-demand code exploration without changing the existing document-scan workflow. It keeps no daemon or background indexer: each command validates a persisted, sectioned graph against the working-tree manifest, then loads it or incrementally rebuilds it. Pass `--no-cache` for a direct in-memory build.

**JavaScript, TypeScript, and Vue Single-File Components** use the TypeScript compiler AST for extraction and, by default, the TypeScript checker for trusted call, inheritance, import, and export resolution. If checker construction fails, the default `preferred` mode reports partial evidence and leaves guesses unresolved; use `--typescript-checker required` to fail the build or `disabled` for syntax-only resolution. Vue keeps original SFC coordinates while extracting `<script>` / `<script setup>` plus statically bound component tags and identifiers in interpolations and `v-on` / `v-bind`. Template bindings become resolved `uses` edges; dynamic/global/ambiguous targets and unprovable scopes are counted refusals, and a script-less SFC still reports `vue-script-absent`. **Python, Go, Rust, Java, C/C++, C#, Kotlin, Scala, Swift, Ruby, and PHP** use vendored tree-sitter grammars for symbols, calls, and inheritance. JavaScript, TypeScript, and TSX also ship query-only tree-sitter grammars. Any extension without a vendored grammar still parses name-only without failing.

```bash
# Exact symbol lookup
occ code find name Greeter --path test/fixtures/code-explore
occ code find name Greeter --path test/fixtures/code-explore --inline-context 2 --format json

# Score-free path/span references for an agent prompt
occ code find fused "cache invalidation" --path . --format citations

# Substring search
occ code find pattern service --path .

# Full-text content search
occ code find content normalize_name --path .

# Price and read a symbol contract without receiving its body
occ code doc bootstrap --path . --file src/main.ts --format json
occ code doc --path . --queries-json queries.json --format json
occ code doc --path . --queries-json queries.json --format json --compact-honesty

# Read exactly one symbol body by nodeId (from code map/find/index JSON) or by name
occ code map --path . --map-format json --map-tokens 4096
occ code source --path . --node-id "function:/abs/repo/src/main.ts:bootstrap:3" --format json
occ code source bootstrap --path . --file src/main.ts --type function

# Check syntax without a language server (exits nonzero only when invalid)
occ code check src/main.ts --path .

# Hash a symbol by stable line-independent key; persist the nested hash tuple
occ code symbol-hash --path . --file src/main.ts --name bootstrap --format json
occ code symbol-hash --path . --queries-json queries.json --format json

# Enumerate cross-module seams, weight by co-change, and re-check a persisted key
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

# Enumerate structural predicates, then evaluate one with bounded JSON output
occ code facts --list
occ code facts untested-entrypoints --path . --limit 20 --format json

# Discover tree-sitter node names, then query TS and join captures to nodeIds
occ code ast --lang typescript --snippet 'function run() {}'
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

# Match code-shaped ast-grep patterns and user-defined rule manifests
occ code pattern --lang typescript --pattern 'JSON.parse($A)' --path . --file src --format json
occ code facts --rules rules.json --path . --format json

# Outgoing and incoming call analysis
occ code analyze calls bootstrap --path test/fixtures/code-explore
occ code analyze callers createUser --path test/fixtures/code-explore --inline-context 2

# Dependency and inheritance inspection
occ code analyze deps src/service --path test/fixtures/code-explore --inline-context 1
occ code analyze tree UserService --path test/fixtures/code-explore

# Module coupling analysis
occ code analyze coupling src/code --path test/fixtures/code-explore

# Ambiguity-aware chain analysis
occ code analyze chain ambiguousCaller duplicate --path test/fixtures/code-explore

# Token-budgeted, importance-ranked repo map and pack
occ code map --path . --map-tokens 4096
occ code pack --path . --map-tokens 8192 --tokenizer o200k_base

# Bounded directory tree from the built, ignore-aware code index
occ code dirtree --path . --mode map --map-tokens 4096

# Deterministic architecture clusters and bounded multi-step call flows
occ code clusters --path . --format json
occ code flows --path . --max-depth 10 --max-branching 5 --format json

# Map where the context budget actually goes, with a fit preflight
occ code dirtree --path . --tokens --top 10 --min-tokens 500 --format json

# Focus the map on a task — by query and/or path (with graph neighbors)
occ code map --path . --query "workspace context injection" --focus-path src/services/memory --map-tokens 4096

# Change-aware: which symbols a git diff touched, the git history for a symbol,
# and a repo map focused on the files changed since a base ref
occ code diff --base main --map-tokens 4096
occ code history UserService --limit 10
occ code map --path . --changed-from main --map-tokens 4096
```

Highlights of the current code exploration behavior:

- **Full index export** via `occ code index` — dump the complete graph (files, symbols, edges, language capabilities) as JSON or a summary line
- **Repository map and pack** via `occ code map` / `occ code pack` — PageRank-ranked, token-budgeted output (symbol signatures or file content) that charges the complete selected rendering, greedily admits the highest-ranked files within the budget, and shrinks content or sheds low-rank symbols rather than dropping a file that nearly fits, with a pluggable heuristic or BPE tokenizer (`--tokenizer o200k_base|cl100k_base`). JSON maps are compact, and `entries[].tokens` measures the compact JSON entry rather than a markdown projection.
- **Directory tree** via `occ code dirtree` / `buildDirectoryTree` / `session.getDirectoryTree` — bounded, ignore-aware tree output derived from `CodebaseIndex.files` with `truncatedPaths` for drill-in, map mode for top symbol signatures per subtree, and opt-in per-path source-token rollups with a `wouldFitBudget` preflight; store-backed token counts persist by tokenizer and content digest
- **Module clustering** via `occ code clusters` / `clusterCodeModules` / `session.clusters` — ten deterministic label-propagation passes over resolved local imports, returning stable `cluster1:` ids, members, cohesion, keywords, externally reached exports, cross-cluster dependencies, and complete omission/coverage accounting
- **Flow tracing** via `occ code flows` / `traceCodeFlows` / `session.flows` — ranked exported function/class entry points followed through resolved calls only, returning stable `flow1:` chains with node ids, spans, depth, cluster linkage, proved back-edge cycle counts split from revisited shared callees, and explicit candidate/result/frontier limits
- **Focused maps** via `--query`, `--focus-path` (repeatable), and `--focus-depth` — opt-in, additive relevance scoring (query + path + graph neighbors) blended with the global rank so task-relevant files surface within the budget; omitting the flags keeps the global PageRank overview unchanged
- **Change-aware exploration** via `occ code diff` (symbols touched by a git diff range, with removed-symbol recovery), `occ code history <symbol>` (git line history for a symbol), and `occ code map --changed-from <ref>` (diff-focused repo maps)
- **Exact, pattern, type, and content search** over the repository graph
- **Fuzzy symbol search** via `searchSymbols` / `session.searchSymbols` (`createOcc().code.searchSymbols`) — rank symbols across name, container-qualified name, and file path with match positions/spans for highlighting; the corpus is memoized per index so repeated queries in long-running hosts pay the build once
- **Code-context projection** via `buildCodeContext` / `session.projectContext` (`createOcc().code.context`) — project a full or slim index down to per-file exported symbols, a deduplicated local import graph, and external dependency roots
- **Symbol→node linkage and typed signatures** — index `files[].symbols[]` entries (and the slim format, `occ code map` / `find` / `index` JSON) carry a `nodeId`, so a file symbol addresses its graph node directly without scanning `nodes`; compiler-backed function and method nodes also retain parameter and explicit return types in `signature`
- **Single-symbol source reads** via `occ code source` — read one symbol body by stable `nodeId` (from `occ code map` / `find` / `index` JSON) or a disambiguated name, reading file content on demand and refusing paths that escape the repo root
- **Contract-only symbol reads** via `occ code doc` / `readCodeDocs` / `session.readDocs` — batchable signature, leading documentation, parameters, and `bodyTokens` without returning the body; regex-fallback languages report `unsupported` instead of guessing. JSON keeps full per-result honesty by default; `--compact-honesty` deduplicates it into a measured batch baseline plus lossless per-result deltas.
- **Detailed entity search** via `occ code entities` / entity-session `searchDetailed` — JSON returns total matches, display omissions, freshness, index truncation, coverage counts, measured ambiguity, and bounded wide evidence gaps by default; `--no-envelope` restores the legacy CLI array, while library `search()` remains an array
- **Entity hotspots** via `occ code hotspots` / entity-session `hotspots` / `createOcc().code.entityHotspots` — rank current code entities by `logicChangeCount × tokenCount` (falling back to line span), keep neutral/unknown counts separate, retain the numeric historical cosmetic field only for JSON compatibility, optionally blend PageRank, and carry freshness/truncation/window coverage, omissions, ambiguity, and wide evidence gaps in an honesty block
- **Entity temporal coupling** via `occ code cochange [entity]` / entity-session `cochange` / `createOcc().code.entityCochange` — group proved logic-changing events by commit over durable lineage ids; named queries return that entity's partners, while a bare query ranks repository pairs above `--min-count` and `--min-confidence`. Each pair carries `cochangeCount`, `aChangeCount`, directional confidence, and `lastCoChange`, while the result carries `windowCommits` and freshness/truncation/filter coverage plus omissions, ambiguity, and wide evidence gaps
- **Documentation/entity drift** via `occ code drift` / entity-session `drift` / `createOcc().code.entityDrift` — scan repository Markdown with the shared fence-aware resolver and compare each section's committed last touch with later proved logic events. For generated/private Markdown, use entity-session `driftForDocuments` / `createOcc().code.entityDriftForDocuments` or NDJSON `occ code drift-documents`: each `{id, content, baseCommit}` resolves against entity state at that exact indexed commit, never a guessed fallback or a working-tree document. Both variants retain exact ambiguity/not-found splits, bounded diagnostics, and freshness/truncation/evidence-gap honesty. Feature-detect the external variant with `code.drift.documents.v1`.
- **Symbol verification** via `occ code symbol-hash` / `hashCodeSymbols` / `session.hashSymbols` — preserves the frozen full-line `bodyHash`, adds `exactSpanHash` for compiler/Tree-sitter byte-exact declarations plus versioned verification tiers, and returns a mechanical verdict when the expected tuple is supplied. Exact-span equality prevents an adjacent same-line declaration from creating false drift; normalized equality defaults to `normalized-equal` but remains only a token-identity heuristic (`--no-normalized-equal-verdict` restores `cosmetic-drift`); declaration-only tiers return `unknown-tier`; `--resolve-gone` alone pays for lineage lookup and may name a successor
- **Seam enumeration** via `occ code seams` / `listCodeSeams` / `resolveCodeSeams` — derive cross-module import/call seams at query time (no new index node/edge types), optionally join a `getGitCochange` summary for lift-weighted ranking, and re-check persisted `seamKey`s where `missing` means drift
- **Structural facts** via `occ code facts` / `queryCodeFacts` / `session.facts` (`createOcc().code.facts`) — dispatch named index predicates with bounded rows and an honesty block. Import-dependent predicates exclude languages without static local-import resolution through typed `capabilityGaps`; `exported-unreferenced` refuses languages whose calls never resolve, retained rows count unresolved calls naming the symbol, and the roll-up makes unresolved calls partial coverage. `untested-entrypoints` uses entity impact when available and self-labels its reverse-import fallback `bestEffort`; `layer-violations` refuses to infer architecture and requires a JSON `--layers` manifest
- **Structural queries** via `occ code tsquery` / `queryTreeSitter` / `session.tsquery` (`createOcc().code.tsquery`) — run caller-supplied tree-sitter queries within result/token bounds and attach the smallest containing index `nodeId`; `occ code ast --snippet` / `createOcc().code.ast` prints a bounded parse tree before writing a query. By default, an over-budget capture is skipped so a smaller later one can still fit; `--budget-early-exit` / `budgetEarlyExit` opts into stopping instead and reports partial coverage
- **Pattern matching** via `occ code pattern` / `queryCodePattern` / `session.pattern` (`createOcc().code.pattern`) — match ast-grep patterns and rule objects (relational, composite, constraint clauses) over the same vendored grammars, with the same bounds, honesty block, and `nodeId` span joins; `occ code facts --rules` / `queryCustomCodeFacts` (`createOcc().code.rulesFacts`) evaluates a user-supplied JSON rule manifest as custom fact predicates — like `layer-violations`, OCC refuses to infer the rules. Pattern and custom-rule scans expose the same opt-in budget early exit and smaller-later-result tradeoff
- **Language-server-free syntax checks** via `occ code check` — TS/JS, Vue SFC, Python, and the vendored tree-sitter languages; exits nonzero only when `valid` is false
- **Call analysis** with explicit `resolved`, `ambiguous`, and `unresolved` states
- **Receiver-aware method resolution** for `this`, `super`, `self`, and `cls`
- **Dependency analysis** grouped into local, external, and unresolved imports
- **Module coupling analysis** with afferent/efferent coupling, instability, and key classes
- **Chain analysis** that reports when a path is blocked by ambiguity instead of silently returning nothing
- **Shared CLI ergonomics** with `--path`, `--format`, `--output`, `--exclude-dir`, and `.gitignore` support

Graph-backed `occ code` commands support `--format tabular|json` (`find` also accepts `--format citations`, and the evidence streams `blob-structure`, `coordinate-verify`, and `graph-export` are NDJSON-only). Most symbol-targeted commands also support `--file` for disambiguation. JSON output includes repository metadata, query metadata, results, repository stats, declared per-language capability flags plus per-language `observedCapabilities` minima with degraded-file counts, and `meta.loadSource` reporting whether the persisted index (`cache`) or a fresh build (`build`) answered the query.

## Programmatic Usage

The code exploration module is available as a library via subpath exports:

```ts
import { buildCodebaseIndex } from '@cesarandreslopez/occ/code/build';
import { discoverCodeFiles } from '@cesarandreslopez/occ/code/discover';
import { findByName, analyzeCalls } from '@cesarandreslopez/occ/code/query';
import type { CodebaseIndex, CodeNode } from '@cesarandreslopez/occ/code/types';

const index = await buildCodebaseIndex({ repoRoot: './my-repo' });
const results = findByName(index, 'UserService');
```

For a stateful session that caches the index across queries:

```ts
import { createCodeQuerySession } from '@cesarandreslopez/occ/code/session';

const session = await createCodeQuerySession({ repoRoot: './my-repo' });
session.findByName('UserService');
session.analyzeCalls('bootstrap');
session.searchSymbols('usrsvc', { limit: 10 }); // fuzzy match across name, container, and path
session.projectContext(); // per-file exports + local import graph + external dependency roots
session.chunk({ maxChunkWords: 200 });
await session.refresh(); // rebuild index when files change (accepts an optional AbortSignal)
```

For persistent caching across sessions with automatic freshness checks:

```ts
import { openCodeIndexStore, resolveCodeIndexCacheDir } from '@cesarandreslopez/occ/code/store';

const store = openCodeIndexStore({
  repoRoot: './my-repo',
  cacheDir: resolveCodeIndexCacheDir(),
});

// Probe the persisted cache cheaply — before the first getSession() and without
// deserializing the index or reparsing files (both return null when no usable
// cache exists yet). Handy for long-running hosts deciding whether to refresh.
const meta = await store.peekMetadata(); // persisted metadata, validated against repo/options/version
const freshness = await store.isFresh(); // stat-only working-tree vs. manifest diff

// First call builds + caches; subsequent calls load from cache. A fresh full
// entry can also satisfy an excerpt request without a duplicate build.
const session = await store.getSession({ strategy: 'prefer-cache' });
session.findByName('UserService');

// Check freshness via file manifests before returning cache
await store.getSession({ strategy: 'ensure-fresh' });

// Force a full rebuild
await store.refresh();
```

Or use the unified facade for all OCC APIs from a single import:

```ts
import { createOcc } from '@cesarandreslopez/occ';

const occ = createOcc();
const session = await occ.code.createSession({ repoRoot: './my-repo' });
const description = await occ.workspace.describe('./my-project');
const analysis = await occ.workspace.analyze('./my-project', { includeCode: true });
const doc = await occ.doc.inspect('report.docx', {});
const status = await occ.health(); // version, capability flags, and a `features` map for probing
const docFormats = status.features['doc.inspect.formats']; // ['docx', 'pdf', 'odt']
```

The facade also exposes the evidence streams and verified collectors directly: `occ.code.atoms` / `collectAtoms`, `occ.code.verifyCoordinates` / `collectCoordinateVerification`, and `occ.code.entityGraph` / `collectEntityGraph`. It also exposes `searchSymbols`, `context`, changed maps, directory trees, module clusters, flow traces, contract reads, entity hotspots/co-change/obligations, immutable blob inspection, symbol verification, and seam resolution. Current producers advertise `code.blobStructure.v2`, `code.atoms.v2`, `code.coordinateVerification.v1`, and `code.entityGraph.v2`; the V1 stream keys remain advertised because their schemas and explicit readers are retained for persisted receipts. Health keys are append-only, so a missing key means unavailable.

Entity sessions are safe to share across concurrent callers. Use
`session.update(changedFiles)` when the host already knows the exact
working-tree paths, `session.refresh()` after history moves, and
`session.contextMany(queries, { tokenBudget })` to admit whole, deduplicated
entity bodies under one shared budget. The signal passed to construction stops
applying once construction resolves; later I/O operations accept their own
signal.

Entity diffs expose a versioned whole-diff proof, and the same session can
compose the body-free blob instrument with historical lineage at a committed
ref. Blob inspection is an async event stream; preserve its complete receipt:

```ts
import { collectGitBlobStructureBatch, createOcc } from '@cesarandreslopez/occ';

const occ = createOcc();
const entitySession = await occ.code.createEntitySession({ repoRoot });
const status = await occ.health();

const diff = await entitySession.diff({ base, head });
const advertisedWholeDiffProofs = status.features?.['code.entity.diff.wholeDiffSemanticVerdict'];
const admitsWholeDiffV4 =
  Array.isArray(advertisedWholeDiffProofs) &&
  advertisedWholeDiffProofs.length === 1 &&
  advertisedWholeDiffProofs[0] === 'whole-file-cst-v4';
const wholeDiff = diff.wholeDiffSemantic;
if (
  admitsWholeDiffV4 &&
  wholeDiff?.proof === 'whole-file-cst-v4' &&
  wholeDiff.verdict === 'semantic-no-op' &&
  wholeDiff.coverage === 'complete'
) {
  // Positive bounded syntactic proof for exactly wholeDiff.gitScope.
}

const batch = await collectGitBlobStructureBatch(occ.code.inspectGitBlobs(requests, { repoPath: repoRoot }));

const lineage = await entitySession.resolveBlobLineage({
  ref: head,
  ...batch,
});
```

The example deliberately checks both the exact health value and the result's
`proof`. Feature-detect the current blob-lineage contract separately with
`status.features?.['code.entity.blobLineage.v2'] === true`; the V1 key remains
advertised for consumers that only decode persisted receipts. Persisted V1,
V2, and V3 whole-diff proof names remain decodable, but they never gain V4's
trivia classifications retroactively and must not pass the V4 health gate.

For large or untrusted repositories, preview the size first, then build the index in an isolated subprocess with a budget. Pair with the slim variant when the consumer only needs the graph (no source content):

```ts
import { createOcc, CodeIndexBudgetExceededError } from '@cesarandreslopez/occ';

const occ = createOcc();

const preview = await occ.code.previewSize({ repoRoot: './my-repo', maxFiles: 5_000, maxBytes: 32 * 1024 * 1024 });
if (preview.exceedsBudget) {
  console.warn('Repo exceeds preview budget:', preview.exceedsBudget);
}

try {
  const slim = await occ.code.buildIndexIsolated({
    repoRoot: './my-repo',
    contentMode: 'excerpt',
    maxFiles: 5_000,
    maxBytes: 32 * 1024 * 1024,
    onBudgetExceeded: 'truncate',
    slim: true,
  });
  if (slim.truncated) console.warn('Index truncated:', slim.truncated);
} catch (error) {
  if (error instanceof CodeIndexBudgetExceededError) {
    console.error('Build budget exceeded:', error.budget);
  } else {
    throw error;
  }
}
```

For workspace-level analysis:

```ts
import { analyzeWorkspace } from '@cesarandreslopez/occ/workspace/analyze';
import { describeWorkspace } from '@cesarandreslopez/occ/workspace/describe';
import { inspectWorkspaceDocumentSet } from '@cesarandreslopez/occ/workspace/documents';

const description = await describeWorkspace('./my-project');
const analysis = await analyzeWorkspace('./my-project', { includeCode: true });
const docs = await inspectWorkspaceDocumentSet('./my-project', { maxFiles: 20 });
```

For a single end-to-end workspace bundle (description + analysis + documents + code preview + slim code index + outline + cross-references in one call):

```ts
import { createOcc } from '@cesarandreslopez/occ';

const occ = createOcc();
const bundle = await occ.workspace.bundle('./my-project', {
  includeDocumentChunks: true,
  includeCorpusChunks: true, // unified, deterministically-ordered code + document chunks
  cooperative: true, // yield during in-process CPU work so callers sharing the event loop stay responsive
  maxCodeFiles: 5_000,
  maxCodeBytes: 32 * 1024 * 1024,
});

console.log(bundle.outline); // root → projects → modules → documents → sections
console.log(bundle.codeDocumentReferences); // per-symbol matches inside markdown content
console.log(bundle.documentChunks?.length); // heading-aware token-budgeted document chunks
console.log(bundle.corpusChunks?.length); // merged code + document chunks (WorkspaceCorpusChunk[]) for RAG
```

`bundleWorkspace` also supports `offThread: true`, which runs the whole bundle in a forked child process. Use it with `cacheDir` (or no store); a caller-provided `store` instance cannot cross the process boundary. When `includeCodeChunks` or `includeCorpusChunks` is enabled, chunks contain source text, so OCC reads full code content to produce them. By default it retains that content for every indexed file at once; set `streamCodeChunks: true` to read each file on demand instead, keeping the retained `codeIndex` slim (`contentMode: 'none'`) so peak memory stays proportional to a single file rather than the whole corpus. Either way you can also lower `maxCodeFiles`/`maxCodeBytes` or scope `codeChunk.files` to bound transient memory.

For heading-aware token-budgeted document chunking (RAG-friendly):

```ts
import { chunkDocument } from '@cesarandreslopez/occ/doc/chunk';

const chunks = await chunkDocument('./report.docx', { maxTokens: 800, overlapTokens: 80 });
for (const chunk of chunks) {
  console.log(chunk.chunkId, chunk.headingPath.join(' › '), chunk.tokenEstimate);
}
```

For Mermaid diagrams and module summaries from a code index:

```ts
import { createOcc } from '@cesarandreslopez/occ';

const occ = createOcc();
const session = await occ.code.createSession({ repoRoot: './my-repo' });
const summary = session.summarizeModule('src/code', { maxFunctions: 15 });
const importGraph = session.toMermaid('import-graph', 'src/code');
const classDiagram = session.toMermaid('class-hierarchy', 'src/code');
const callGraph = session.toMermaid('call-graph', 'bootstrap');
```

Available subpath exports:

| Import path                                     | Description                                                                                                                                                                                                                                                                                                                                               |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@cesarandreslopez/occ/code/build`              | `buildCodebaseIndex` — graph construction (with optional `maxFiles`/`maxBytes`/`onBudgetExceeded` budget controls and `CodeIndexBudgetExceededError`); also `parseCodeFiles` (bounded-concurrency parse pool) + `assembleCodebaseIndex` for staged indexing                                                                                               |
| `@cesarandreslopez/occ/code/types`              | TypeScript types (`CodebaseIndex`, `CodeNode`, `CodeEdge`, `IndexTruncation`, etc.)                                                                                                                                                                                                                                                                       |
| `@cesarandreslopez/occ/code/query`              | Query functions (`findByName`, `analyzeCalls`, `analyzeDeps`, etc.)                                                                                                                                                                                                                                                                                       |
| `@cesarandreslopez/occ/code/discover`           | `discoverCodeFiles` — code file discovery (defaults to the shared `DEFAULT_EXCLUDE_DIRS`, re-exported here and from the package root — now also covering `out`, `.next`, `__pycache__`, and `.venv`)                                                                                                                                                      |
| `@cesarandreslopez/occ/code/preview`            | `previewCodebaseSize` — cheap size + per-language estimate without parsing, with budget pressure reporting                                                                                                                                                                                                                                                |
| `@cesarandreslopez/occ/code/isolated`           | `buildCodebaseIndexIsolated` — runs `buildCodebaseIndex` in a forked subprocess, optionally returning a slim index; also `chunkFromStoreIsolated` — runs store-backed code chunking in a forked subprocess (options `ChunkFromStoreIsolatedOptions`, `SerializableCodeChunkOptions`)                                                                      |
| `@cesarandreslopez/occ/code/incremental`        | `computeManifestDiff`, `classifyChangedFiles`, `findResolutionImpactedFiles`, `spliceIndexInputs` — primitives behind incremental `update()`/`ensureFresh()` (manifest diff + resolution-impact + graph splice)                                                                                                                                           |
| `@cesarandreslopez/occ/code/slim`               | `slimifyIndex`, `parseSlimIndex`, `validateSlimIndex` — content-free `CodebaseIndexSlim` for graph-only consumers                                                                                                                                                                                                                                         |
| `@cesarandreslopez/occ/code/chunk`              | `chunkCodebase`, `chunkFromIndex`, `chunkFromIndexCooperative`, `chunkFromIndexStreaming` — semantic code chunking (word- or token-based via `maxTokens`/`countTokens`; the cooperative variant yields the event loop, the streaming variant reads each file on demand from a slim/`contentMode: 'none'` index)                                           |
| `@cesarandreslopez/occ/code/session`            | `createCodeQuerySession` — stateful code query session (sync `chunk()` plus async `chunkCooperative()` that yields the event loop while chunking)                                                                                                                                                                                                         |
| `@cesarandreslopez/occ/code/store`              | `openCodeIndexStore`, `openChunkCodeIndexStore` — persistent index store with cache strategies (the chunk variant pins `contentMode: 'full'`; `update(changedFiles?)` does a true incremental refresh — manifest diff + targeted re-parse + graph splice; `chunkIsolated(options?)` chunks the cached index in a forked subprocess)                       |
| `@cesarandreslopez/occ/code/cache`              | Index caching utilities (legacy — prefer `./code/store`)                                                                                                                                                                                                                                                                                                  |
| `@cesarandreslopez/occ/code/diff`               | `computeCodeDiff`, `joinHunksToSymbols` — map a git diff range to changed code symbols (added/removed/modified, new/removed exports, removed-symbol recovery)                                                                                                                                                                                             |
| `@cesarandreslopez/occ/code/source`             | `readCodeSource` — one symbol body by id or name, with typed ambiguity instead of a guess                                                                                                                                                                                                                                                                 |
| `@cesarandreslopez/occ/code/source-inline`      | Verified inline source snapshots — `attachSourceInlineManifest`, digest-checked `inlineSourceFromLines` / `inlineSourceFromText`, and `sourceIdentityForBytes` for citation-grade excerpts                                                                                                                                                                |
| `@cesarandreslopez/occ/code/check`              | `checkCodeSyntax` — language-server-free syntax checking for TS/JS, Vue SFC, and the vendored tree-sitter languages                                                                                                                                                                                                                                       |
| `@cesarandreslopez/occ/code/blob-structure`     | `inspectGitBlobStructures` plus `collectGitBlobStructureBatch` — ordered, bounded structural observations for caller-owned immutable Git blob references and a verified complete receipt                                                                                                                                                                  |
| `@cesarandreslopez/occ/code/atoms`              | `emitAtoms` plus `collectAtomsRun` — resumable, source-body-free full-DAG episodes and a verified V2 receipt; explicit V1 readers remain for persisted receipts                                                                                                                                                                                           |
| `@cesarandreslopez/occ/code/coordinates`        | `verifyGitCoordinates` plus `collectGitCoordinateVerificationBatch` — body-free OID/path/span/digest verification, optionally bound to a pin                                                                                                                                                                                                              |
| `@cesarandreslopez/occ/code/entity-graph`       | `exportEntityGraph` plus `collectEntityGraph` — pinned lineage, co-change, incidence, and explicit seam graph NDJSON with a verified V2 receipt; explicit V1 readers remain for persisted receipts                                                                                                                                                        |
| `@cesarandreslopez/occ/code/entity`             | Entity intelligence sessions and contracts, including the authoritative whole-diff proof, legacy entity-record semantics, and committed blob-lineage composition                                                                                                                                                                                          |
| `@cesarandreslopez/occ/code/tests`              | Test recognition contracts — `OccTestReason` / `OccTestSignal` schemas, reason codes, and the default test directory/file-pattern/call-name tables                                                                                                                                                                                                        |
| `@cesarandreslopez/occ/code/formats`            | Hand-written JSON/YAML/TOML/Markdown/CSV entity extractors (`FormatEntity`, `extractYamlEntities`, `FORMAT_EXTENSIONS`, etc.)                                                                                                                                                                                                                             |
| `@cesarandreslopez/occ/git`                     | Git context API — `getGitChangedFiles`, `getGitDiffSummary`, `getGitDiffPatch`, `getGitDiffHunks`, `getGitDiffFunctionContext`, `getGitCommitHistory`, `getGitFileHistory`, `getGitChurnSummary`, `getGitCochange`, `resolveGitRange` (also `./git/types`, `./git/api`, `./git/client`, `./git/parse`)                                                    |
| `@cesarandreslopez/occ/git/capture`             | `captureGitRepository` — deterministic, source-body-free full-DAG Git capture with per-parent physical deltas, pinned-tree entries, provenance, and completeness receipts                                                                                                                                                                                 |
| `@cesarandreslopez/occ/doc/inspect`             | `inspectDocument` — document metadata and content extraction                                                                                                                                                                                                                                                                                              |
| `@cesarandreslopez/occ/doc/types`               | Document inspection types                                                                                                                                                                                                                                                                                                                                 |
| `@cesarandreslopez/occ/doc/discover`            | Document file discovery (now includes prose formats by default; opt into data files via `includeDataFiles`; new `discoverDocumentSet` returns `{ documents, skipped }`)                                                                                                                                                                                   |
| `@cesarandreslopez/occ/doc/batch`               | Batch document inspection                                                                                                                                                                                                                                                                                                                                 |
| `@cesarandreslopez/occ/doc/chunk`               | `chunkDocument` / `chunkDocumentFromMarkdown` — heading-aware, token-budgeted document chunker for DOCX/PDF/PPTX/XLSX/ODT/ODS/ODP/MD/MDX/TXT/RST/AsciiDoc (the `FromMarkdown` variant chunks pre-converted markdown without re-parsing)                                                                                                                   |
| `@cesarandreslopez/occ/doc/entities`            | Entity and keyword extraction                                                                                                                                                                                                                                                                                                                             |
| `@cesarandreslopez/occ/doc/references`          | Cross-reference detection                                                                                                                                                                                                                                                                                                                                 |
| `@cesarandreslopez/occ/workspace/analyze`       | `analyzeWorkspace` — workspace-level analysis                                                                                                                                                                                                                                                                                                             |
| `@cesarandreslopez/occ/workspace/describe`      | `describeWorkspace` — fast directory classification                                                                                                                                                                                                                                                                                                       |
| `@cesarandreslopez/occ/workspace/documents`     | `inspectWorkspaceDocumentSet` — document summaries and cross-references                                                                                                                                                                                                                                                                                   |
| `@cesarandreslopez/occ/workspace/types`         | Workspace analysis types                                                                                                                                                                                                                                                                                                                                  |
| `@cesarandreslopez/occ/workspace/prepare`       | `prepareWorkspaceContext` — combined code indexing + document inspection                                                                                                                                                                                                                                                                                  |
| `@cesarandreslopez/occ/workspace/prepare-types` | Workspace preparation types (`WorkspacePrepareOptions`, `WorkspacePreparedContext`, etc.)                                                                                                                                                                                                                                                                 |
| `@cesarandreslopez/occ/workspace/bundle`        | `bundleWorkspace` — single-call versioned `WorkspaceBundle` (description + analysis + documents + slim code index + outline + cross-refs + optional document / code / unified corpus chunks via `WorkspaceCorpusChunk`)                                                                                                                                   |
| `@cesarandreslopez/occ/markdown/convert`        | `documentToMarkdown` — document-to-markdown conversion (now reads MD/MDX/TXT/RST/AsciiDoc/YAML/JSON/TOML directly)                                                                                                                                                                                                                                        |
| `@cesarandreslopez/occ/structure/extract`       | `extractFromMarkdown` — heading tree extraction                                                                                                                                                                                                                                                                                                           |
| `@cesarandreslopez/occ/structure/types`         | Structure types and helpers                                                                                                                                                                                                                                                                                                                               |
| `@cesarandreslopez/occ/sheet/inspect`           | `inspectWorkbook` — XLSX/ODS workbook inspection                                                                                                                                                                                                                                                                                                          |
| `@cesarandreslopez/occ/sheet/types`             | Sheet inspection types                                                                                                                                                                                                                                                                                                                                    |
| `@cesarandreslopez/occ/slide/inspect`           | `inspectPresentation` — presentation inspection                                                                                                                                                                                                                                                                                                           |
| `@cesarandreslopez/occ/table/inspect`           | Table extraction from documents                                                                                                                                                                                                                                                                                                                           |
| `@cesarandreslopez/occ/table/types`             | Table extraction types                                                                                                                                                                                                                                                                                                                                    |
| `@cesarandreslopez/occ/health`                  | `health()` — build manifest with capability flags, boolean feature keys, and authoritative result-capable format arrays such as `doc.inspect.formats`                                                                                                                                                                                                     |
| `@cesarandreslopez/occ/probe`                   | `probe()` — runtime readiness for git, repository/cache state, tree-sitter grammars, and document parser module loading. Builds no index and parses no document                                                                                                                                                                                           |
| `@cesarandreslopez/occ/mcp`                     | MCP server embedding — `createOccMcpServer` / `runMcpServer`, `createSessionHolder`, and the tool name/input-schema/example manifests (`OCC_MCP_TOOL_NAMES`, `OCC_MCP_INPUT_SCHEMAS`, `MCP_RESPONSE_FORMATS`)                                                                                                                                             |
| `@cesarandreslopez/occ/errors`                  | `OccAbortError`, `OCC_ABORTED`, `isOccAbortError` — typed abort error that survives `instanceof` across forked subprocesses                                                                                                                                                                                                                               |
| `@cesarandreslopez/occ/types`                   | Shared types (`ConfidenceLevel`, `ParseResult`, `ParserOutput`, etc.)                                                                                                                                                                                                                                                                                     |
| `@cesarandreslopez/occ/tokens`                  | Token estimation utilities                                                                                                                                                                                                                                                                                                                                |
| `@cesarandreslopez/occ/progress-event`          | Progress event types (`ProgressPhase`, `ProgressEvent` with optional `scope`/`currentPath`/`bytesProcessed`/`totalBytes`/`startedAt`/`elapsedMs`, plus off-thread bundle-read timing fields `section`/`parentReadStartedAt`/`parentReadFinishedAt`/`parentReadDurationMs`/`sectionStartedAt`/`sectionFinishedAt`/`sectionDurationMs`/`cleanupDurationMs`) |
| `@cesarandreslopez/occ/stats`                   | Stats types (`StatsRow`, `AggregateResult`) and `aggregate()`                                                                                                                                                                                                                                                                                             |

TypeScript ships with OCC as a direct dependency, so the code exploration module works after a normal install. You only need a separate TypeScript setup if your own project uses `tsc`.

## Document Inspection

`occ doc inspect` extracts metadata, risk flags, content stats, heading structure, and a content preview from DOCX and ODT documents.

```bash
# Document overview with content preview
occ doc inspect report.docx

# Machine-readable payload
occ doc inspect report.docx --format json

# More paragraphs in the preview
occ doc inspect report.docx --sample-paragraphs 10
```

Current document inspection surfaces:

- **Document properties** — title, author, dates, keywords
- **Risk flags** — comments, tracked changes, hyperlinks, embedded objects, macros, tables, encryption
- **Content stats** — words, pages, paragraphs, characters, tables, images
- **Heading structure** — tree with section codes and depth
- **Content preview** — first N paragraphs with heading detection
- **Token estimates** — preview and full-document token estimates

## Spreadsheet Inspection

`occ sheet inspect` is a lightweight XLSX/ODS preflight command aimed at both humans and agents. It helps answer "is this workbook worth reading in depth?" before spending tokens serializing cells or opening the file in a spreadsheet application.

```bash
# Workbook-level summary + per-sheet schema/sample preview
occ sheet inspect finance.xlsx

# Machine-readable inspection payload
occ sheet inspect finance.xlsx --format json
occ sheet inspect finance.ods --format json

# Narrow to one sheet and reduce preview width
occ sheet inspect finance.xlsx --sheet Revenue --sample-rows 3 --max-columns 8
```

Current XLSX/ODS inspection highlights:

- **Workbook metadata** — file size, workbook properties, custom properties, workbook-scoped names
- **Sheet inventory** — visible / hidden / very hidden sheets, used ranges, cell counts, formula/comment/link counts
- **Schema preview** — detected header row, inferred column types, coverage ratios, example values
- **Lightweight sampling** — small row previews designed for preflight rather than full extraction
- **Token estimates** — sample and full-sheet token estimates to guide downstream agent reads

## Presentation Inspection

`occ slide inspect` provides presentation metadata, risk flags, per-slide inventory, and content previews for PPTX and ODP files.

```bash
# Presentation overview with slide preview
occ slide inspect deck.pptx

# Machine-readable payload
occ slide inspect deck.pptx --format json

# Inspect a specific slide
occ slide inspect deck.pptx --slide 3
```

Current presentation inspection surfaces:

- **Presentation properties** — title, author, dates
- **Risk flags** — comments, speaker notes, hyperlinks, embedded media, animations, macros, charts, tables
- **Slide inventory** — per-slide title, word count, notes, images, tables, charts
- **Content preview** — text preview for sample slides
- **Token estimates** — preview and full-presentation token estimates

## Table Extraction

`occ table inspect` extracts structured table content from DOCX, XLSX, PPTX, ODT, and ODP documents. For AI agents, this is the primary way to read financial summaries, comparison matrices, and data tables without parsing raw XML.

```bash
# Extract all tables as JSON
occ table inspect report.docx --format json

# Tabular preview of table content
occ table inspect finance.xlsx

# Extract a specific table
occ table inspect finance.xlsx --table 1

# Limit sample rows
occ table inspect report.docx --sample-rows 5
```

Current table extraction highlights:

- **Multi-format support** — DOCX (via mammoth HTML), XLSX (via SheetJS), PPTX (from slide XML), ODT and ODP (from content.xml)
- **Auto-detected headers** — first row is treated as headers when values are unique strings
- **Merged cell support** — colspan and rowspan are preserved in the output
- **Sample row limits** — configurable maximum rows per table (default: 20)
- **Table filtering** — extract a specific table by index with `--table N`
- **Token estimates** — per-table and total token estimates
- **PDF graceful degradation** — returns empty tables with an informative note instead of unreliable heuristic output

## Workspace Analysis

`occ workspace` provides fast directory description plus combined analysis of code, documents, and structures — useful for AI agents that need a complete workspace overview.

```bash
# Quick workspace description from fast signals
occ workspace describe
occ workspace describe --format json

# Convenience alias for one or more directories
occ describe ./repo-a ./repo-b --quiet

# Full workspace analysis (code + documents + structures)
occ workspace analyze --format json

# Skip code analysis
occ workspace analyze --no-code --format json

# Document summaries with cross-reference detection
occ workspace documents --format json

# Limit documents and include markdown content
occ workspace documents --max-files 20 --include-markdown --format json
```

`occ workspace describe` returns a `schemaVersion: 1` JSON envelope containing a classification summary, file composition, manifest/framework signals, nested project summaries, and recommended next OCC commands. It uses fast file and manifest signals only: it does not parse document contents or run `scc`. `occ workspace analyze` returns code metrics (via scc), document aggregates, heading structures, skipped files, and errors. `occ workspace documents` returns per-document summaries with cross-references (filename mentions, hyperlinks, citations) and unresolved mentions detected across the document set.

For combined code indexing and document inspection with progress tracking:

```ts
import { prepareWorkspaceContext } from '@cesarandreslopez/occ/workspace/prepare';

const context = await prepareWorkspaceContext(
  './my-project',
  {
    includeCode: true,
    includeDocuments: true,
    executionMode: 'auto', // 'auto' | 'inline' | 'subprocess'
  },
  event => {
    console.log(`[${event.scope}] ${event.stage}: ${event.completed}/${event.total}`);
  }
);

// context.code?.index  — full CodebaseIndex
// context.documents    — WorkspaceDocumentSet with cross-references
// context.elapsedMs    — total wall time
// context.errors       — collected errors from both phases
```

## Immutable Git Evidence

Use these machine-first streams when reproducibility matters more than a summary of the current checkout.

```bash
# Full reachable history and pinned HEAD tree. NDJSON is the only stdout format.
occ git capture --path . --ref HEAD > repository-capture.ndjson

# Parse one exact blob without checking it out or returning its body.
oid=$(git rev-parse HEAD:src/index.ts)
printf '{"requestId":"index","oid":"%s","relativePath":"src/index.ts"}\n' "$oid" |
  occ code blob-structure --path .

# One body-free candidate work episode per parent-child edge, with a receipt.
occ atoms --path . --ref HEAD > repository-atoms.ndjson

# Verify stored coordinates and bind them to the same pin; requests are NDJSON.
occ code coordinate-verify --path . --ref HEAD < coordinates.ndjson

# Whole observed lineage/co-change/incidence/seam graph at the same pin.
occ code graph-export --path . --ref HEAD > entity-graph.ndjson
```

`git capture` resolves the ref once, disables replacement objects, graft rewrites, and lazy fetching, preserves all parents, and applies no vendor/build exclusions or rename heuristics. A missing footer means interruption; `footer.complete` is true only when history, every parent delta, and the pinned tree were fully acquired.

`code blob-structure` accepts one NDJSON request per line and emits a V2 header, one ordered result per occurrence, and a footer. Results contain declarations, imports, calls, inheritance, parser provenance, canonical half-open UTF-8 byte spans, bounds, and typed gaps—never source bodies, absolute paths, entity lineage, or content-derived identity. Pass the complete stream through `collectGitBlobStructureBatch`, then supply its `{ header, blobs, footer }` receipt and an exact ref to an entity session's `resolveBlobLineage` operation. Persisted V1 receipts remain decodable through the V1 schemas/collector and the lineage adapter, but their line-only parser@1 evidence can never prove V2 completeness. Unframed `{ ref, blobs }` input is also explicitly incomplete.

`occ atoms` resolves the pin once and observes all parents in deterministic parents-before-children order. Its V2 stream pins the parser@3 evidence ladder used by the entity index. A bounded first pass builds a lifetime-aware state overlay: accepted unchanged matches carry an entity through unrelated blob/line movement, identical branch states converge at a merge, and delete/re-add lifetimes remain distinct. A second pass emits episodes, pinned `lineage-head` mappings, and the footer. Measures explicitly count gross added/deleted Git-patch payload, while `module_pairs_touched` is only a changed-directory observation—not a static seam. Every cursor binds the pin and effective policy; V1 cursors and parser@2 V2 cursors remain readable for receipt verification but cannot resume the parser@3 contract. `--since` and `--resume` warm-replay the full bounded observation window before filtering output. Raise `--max-commits` for a full-history corpus and require complete coverage before treating absence as observed.

Coordinate roles are deliberately separate. `{ oid, path, span, span_digest }` is native, immutable, self-verifying identity and is safe to persist. `dag1:*` is all-parent, run-scoped correlation; `ent1:*` is the existing first-parent entity lineage and is attached only through a uniquely resolved pinned head mapping. A checkout `nodeId` is only a current-graph locator and must never be persisted. `occ code coordinate-verify` physically rereads the stated object, recomputes the LF-normalized span digest, and optionally proves that the pin's tree maps the path to that OID. Mismatch and unavailable are explicit and never mean no-op.

`occ code graph-export` emits a V2 receipt over the V2 atoms and blob-structure contracts. It includes all bounded run lineages. Explicit seam records use the same cross-module import/call basis as `occ code seams`, including import-only seams; inheritance remains directed incidence only. Unified entity edges carry logic co-change count/lift over every parent-child transition, directed call/inheritance incidence, and membership only in declared seams. Historical endpoints explicitly report static structure as unavailable. OCC supplies observations; it does not score relevance, rank importance, infer a boundary hierarchy, or execute tests.

For reproducible version-zero current-index and document import, use a clean checkout of the selected pin. Prefer body-free indexes and targeted inspection; `bundleWorkspace` materializes content and is not the core pointer-only import path.

All five evidence streams accept `--require-complete`, which exits nonzero when the emitted stream's coverage receipt is anything less than complete — the CI-friendly way to refuse partial evidence.

Programmatic callers use `createOcc().git.capture(...)`; the blob, atom, coordinate, and graph streams plus their collectors are exposed under `createOcc().code`. Dedicated imports are `./git/capture`, `./code/blob-structure`, `./code/atoms`, `./code/coordinates`, and `./code/entity-graph`.

## Git Context

`occ git` inspects git changes, history, and churn over a typed, shell-injection-safe git client (it shells out to `git` with argument arrays, validates refs, and classifies failures like missing-git / not-a-repo / bad-ref). The summary commands (`changed`, `diff`, `history`, `churn`, `cochange`) share `--path <repo-root>` (default: current directory), `--base <ref>`, `--head <ref>`, `--staged`, `--format tabular|json`, and `-o, --output <file>`; `capture` is the exception — it takes only `--path`, `--ref`, and its acquisition bounds, and emits NDJSON as its sole output format. The diff range resolves from `--base`/`--head`/`--staged`, defaulting to the working-tree changes when unspecified. The history-flavored commands (`history`, `churn`, `cochange`) additionally accept `--scope range|history`: the default diff range is empty on a clean tree sitting exactly on its base branch, and `--scope history` aggregates over full HEAD history instead (pair it with `--since` to bound the window).

```bash
# List the files changed in the resolved diff range
occ git changed --base main
occ git changed --staged --format json

# Summarize the diff, or render a token-bounded raw patch
occ git diff --base main --format json
occ git diff --base main --patch --map-tokens 2048 --tokenizer o200k_base

# Commit history for a range, or per-file history (with line ranges)
occ git history --since 2025-01-01 --format json
occ git history src/cli.ts --limit 10 --follow
occ git history src/cli.ts --line-start 10 --line-end 50

# Rank changed files by churn to find hotspots
occ git churn --sort churn --limit 20 --format json
occ git cochange --target src/cli.ts --limit 20 --format json

# Aggregate over full HEAD history instead of the diff range
occ git churn --scope history --since "90 days ago" --format json

# Capture immutable repository evidence rather than a bounded summary
occ git capture --path . --ref HEAD
```

Current git context highlights:

- **`occ git changed`** — changed files for the resolved range with status, rename/copy metadata, and binary flags
- **`occ git diff`** — per-file churn summary, or the raw unified patch with `--patch`, token-bounded via `--map-tokens` / `--tokenizer` (degrades gracefully, reporting `filesOmitted`, when the diff exceeds the git buffer)
- **`occ git history`** — commit history for a range (or full HEAD history with `--scope history`; JSON reports the resolved `range`), or per-file history with `--follow`, `--since`, `--limit`, and line-scoped `git log -L` via `--line-start` / `--line-end`
- **`occ git churn`** — files ranked by `--sort churn|commits|added|deleted|net` (default `churn`) with commit, addition, deletion, net, and last-touched metrics; `--scope history` ranks hotspots over full HEAD history
- **`occ git cochange`** — file pairs ranked by historical co-change count and lift, with `--scope history` for a real history window, `--target` for one-file impact context, and `--max-commit-files` to ignore sweeping commits
- **`occ git capture`** — canonical NDJSON over all reachable commits, raw per-parent deltas, and every tracked pinned-tree entry; configured bounds and repository hazards are explicit in the header/footer
- **Symbol-level changes** — pair with `occ code diff` to see which _symbols_ (not just files and lines) a diff touched

## Entity Intelligence

Files and line ranges are the wrong unit for a lot of questions. `git log --follow src/map.ts` tells you about a file; it cannot tell you that `buildRepoMap` was extracted from another function, moved to a new module, and later had its signature changed — nor which of the three functions now named `format` you meant.

`occ code` answers those questions about **entities**: functions, methods, classes, and data-format keys. Each gets a durable lineage id that survives renames, moves between files, and container changes.

```bash
# What entities exist, with the id that survives a rename
occ code entities buildRepoMap --format json

# Which entities a change touched, and which ones have proved logic drift
occ code diff --entities --base main --format json

# Which current entities changed logic most often, sized by token cost
occ code hotspots --limit 20 --format json

# Which current functions historically change logic together
occ code cochange --min-count 3 --min-confidence 0.5 --format json
occ code cochange buildRepoMap --format json

# Which documentation sections predate proved logic changes to what they name
occ code drift --dirs docs/,README.md --format json
occ code drift --dirs docs/ --exit-code

# Generated/private Markdown: one {id,content,baseCommit} object per line
printf '%s\n' '{"id":"wiki://guide","content":"# Guide\\nUse `buildRepoMap`.","baseCommit":"HEAD~1"}' | \
  occ code drift-documents --path .

# What breaks if I change this — and which tests actually cover it
occ code impact buildRepoMap --scope tests --inline-context 1 --format json

# Who last observably changed each entity (unproved reformats fail closed)
occ code blame src/code/map.ts --format json

# How this function got to its current form, across renames and moves
occ code log buildRepoMap --limit 10 --format json

# The function plus its callers, under a hard token budget
occ code context buildRepoMap --token-budget 4000 --inline-context 2
```

What it does and does not claim:

- **Lineage is evidence-based.** Matching runs an ordered ladder — exact identity, git rename, content hash, comment-blind hash, structure-blind hash, signature, qualified name, then bounded fuzzy similarity. Every match records the rung and confidence that produced it.
- **Ambiguity is refused, not guessed.** Two indistinguishable candidates stay separate lineages. A name that matches several entities returns `ambiguous` with every candidate listed — never a silent first pick.
- **Entity-record classification remains useful but scoped.** Compatible manifest-pinned CST evidence can prove `modified_logic`; otherwise a changed body is `modified`/unknown. `modified_cosmetic` remains decodable for persisted evidence but is not newly emitted, and normalized/structural hashes remain identity heuristics rather than no-op proof.
- **Whole-diff proof fails closed outside its policy.** Vendored whole-file CSTs can prove non-trivia structural drift, ordinary comment-only drift, and whitespace-only drift in grammars whose whitespace semantics are policy-approved. Directive comments, BOM/encoding changes, unsafe whitespace grammars, unsupported formats, and unavailable evidence remain `unknown`.
- **Tests come from the call graph.** Affected-test discovery uses reverse traversal, not filename similarity.
- **Blame does not fabricate.** Untracked files, shallow clones, and uncommitted entities get a typed state (`untracked`, `shallow-history`, `uncommitted`) and no invented commit metadata.
- **Bounds are declared.** Every limit reached produces a diagnostic; a bounded result is never presented as a complete one.
- **Inline source is snapshot-bound.** Full-content indexes use held bytes. Reduced indexes consult the working tree only when its byte size and SHA-256 still match the parsed manifest; drift omits source and emits `inline-context-stale` instead of showing unrelated current bytes. Context-bundle surrounding lines count against the same token budget.
- **Context closure is mechanical.** Context bundles report `closed`, `open`, or `unknown` reference closure over resolved 1-hop edges under the pinned index, with fixed reason codes, resolved/unresolved edge counts, omitted-target counts, and bounded handles. Unresolved or unreachable edges, missing graph nodes, regex fallback, and clipped entities force `unknown`.
- **Nothing is written into your repository.** The lineage cache defaults to `$XDG_CACHE_HOME/occ/entity` (or `~/.cache/occ/entity`). A new commit appends only its commit/event tails and atomically replaces the live state; parsed blobs live in a contract-addressed partition shared across compatible option fingerprints and patch releases. Metadata is committed last, so a torn append is rebuilt rather than served.

Entity diffs carry two deliberately different summaries:

| Field               | Scope and safe use                                                                                         |
| ------------------- | ---------------------------------------------------------------------------------------------------------- |
| `semantic`          | Legacy emitted entity-record/hash evidence. Its `semantic-no-op` is never a whole-file or whole-diff gate. |
| `wholeDiffSemantic` | Authoritative `whole-file-cst-v4` proof for the exact physical Git scope recorded in `gitScope`.           |

The whole-diff aggregate is asymmetric. Any proved non-trivia structural file
drift yields `logic-change`; coverage remains `partial` if another file is
unknown. Under V4, ordinary comment-only changes and whitespace-only changes in
policy-approved grammars are `cosmetic-change/complete`; their aggregate is
`semantic-no-op/complete` when no logic or unknown rows remain. Directive
comments, BOM transitions, missing blobs, invalid encoding, binary or
unsupported modifications, unsafe whitespace grammars, parse errors, bounds,
untracked or unmerged default-scope evidence, and concurrent mutation fail
closed. Relevant `assume-unchanged` or `skip-worktree` paths make an
included worktree scope partial with `index-visibility-hidden`, even when the
flagged path appears unmodified. “Logic change” means proved non-trivia
structural source drift, not observational program inequivalence.

OCC now emits only `whole-file-cst-v4`. Public types retain V1-V3 so persisted
receipts remain representable, and the MCP decoder accepts V3/V4. Older proofs
never retroactively authorize V4's `cosmetic-change` arm. “Logic change,”
“normalized equal,” and “cosmetic” describe bounded syntactic evidence, not
observational program equivalence.

The ordinary CLI exit gate uses `wholeDiffSemantic` and remains nonzero only
for `logic-change`; `unknown` can therefore exit zero, meaning “no structural
drift was proved,” never “a no-op was proved.” Only
`semantic-no-op` with `coverage: 'complete'` is a positive no-op proof, and only
for the recorded Git scope—not an unstated workspace. Entity and blob-lineage
V1 path strings are valid-UTF-8-only: invalid Git path bytes and unpaired
UTF-16 surrogates fail closed instead of being replaced or joined lossily.

A miss or an ambiguity exits **0**: an entity that is simply not there should not break a pipeline. Pass `--strict` if you want the opposite.

## MCP Server

The same capabilities are available to MCP clients over stdio, as thirteen tools:

```bash
occ mcp --root /path/to/repo
```

```json
{
  "mcpServers": {
    "occ": {
      "command": "occ",
      "args": ["mcp", "--root", "/path/to/repo"]
    }
  }
}
```

Tools: `occ_doc`, `occ_pattern`, `occ_entities`, `occ_hotspots`, `occ_cochange`, `occ_diff`, `occ_impact`, `occ_blame`, `occ_log`, `occ_context`, `occ_status`, `occ_source`, `occ_anchor`. Each returns structured content typed by the same public types as the programmatic API, plus a compact text rendering. `occ_source` reads one body by node id or disambiguated name, counts its tokens, carries the standard freshness/coverage footer, and refuses a multi-match name instead of choosing one. `occ_anchor` accepts exactly one of `name`, `lineageId`, or `nodeId` and captures the entity as a verifiable memory anchor — durable lineage id, symbol key, hash tuple, and a proved `baseCommit` when available — nested under an `anchor` subtree that survives the concise projection; verification runs through `occ code verify-anchors`. `occ_entities` returns the detailed search envelope and retains `count` as the number of returned rows. `occ_status` answers about OCC rather than about the code — what the index covers, whether bounds truncated it, whether the wide entity evidence set is complete, and whether it still describes the repository — which is how a client tells an empty result that is a fact about the code from one that is a fact about the index. Its additive contract fields identify the code-index schema and entity parser contract; `parserEvidence` counts versioned, legacy, checker-backed, checker-fallback, syntax-recovered, regex-fallback, and degraded files so parser loss is visible without inspecting every file record.

Every tool accepts optional `response_format: "detailed" | "concise"`; `detailed` is the default and preserves the existing response. `concise` applies one shared post-handler projection to structured content: it removes blob/span digests and internal lineage/parser provenance, prefers `nodeId` as the one stable handle for each live element (falling back to a lineage/entity id when no node exists), and keeps coverage, truncation, freshness, verdicts, diagnostics, and the existing compact text rendering unchanged. Each advertised tool description includes schema-checked minimal, partial, or full argument examples from the same constants table used by the server tests. Feature-detect the contract through `health.features['mcp.responseFormat.v1']`.

For `occ_diff`, `structuredContent.wholeDiffSemantic` is authoritative for whole-diff no-op decisions. The sibling `semantic` field covers emitted entity records only. Admit V4 only when health advertises exactly `['whole-file-cst-v4']` and the result's `proof` is `whole-file-cst-v4`. Safe whitespace and ordinary comments may then contribute `cosmetic-change`; directives, BOM/encoding changes, `unknown`, and partial/unavailable coverage remain evidence gaps. Persisted V3 MCP receipts stay decodable but never satisfy the V4 gate; public types retain V1-V3. The MCP envelope requires V4 grammar/trivia digests and cosmetic subcounts, cross-checks complete coverage against unknowns and gaps, and rejects counts below the floor established by known file verdicts while tolerating future additive arms and count ceilings.

The process is **non-resident**: it starts no daemon, opens no socket, makes no network call, sends no telemetry, and exits when the client disconnects. It answers only about the repository given by `--root`; paths outside it are refused. It re-checks freshness before each call and reindexes when the repository moved under it. For first contact with a large repository, set an explicit bound such as `--max-commits 200`, allow that build to finish, then call `occ_status` to inspect truncation. A bounded build plus the resulting warm cache is the retry-livelock mitigation. Count-based `notifications/progress` are visibility only and extend a timeout only in clients that request and honor them.

## Documentation

Full documentation is available at [cesarandreslopez.github.io/occ](https://cesarandreslopez.github.io/occ/), including:

- [Installation](https://cesarandreslopez.github.io/occ/getting-started/installation/)
- [Quick Start](https://cesarandreslopez.github.io/occ/getting-started/quick-start/)
- [CLI Reference](https://cesarandreslopez.github.io/occ/usage/cli-reference/)
- [Output Formats](https://cesarandreslopez.github.io/occ/usage/output-formats/)
- [Architecture](https://cesarandreslopez.github.io/occ/architecture/overview/)
- [Changelog](https://cesarandreslopez.github.io/occ/changelog/)

## Why OCC?

Tools like `scc`, `cloc`, and `tokei` give you instant visibility into codebases — lines, languages, complexity. But most projects also contain Word documents, PDFs, spreadsheets, and presentations that are invisible to these tools. OCC fills that gap.

### For Humans

- **Project audits** — instantly see how much documentation lives alongside your code: total word counts, page counts, spreadsheet sizes, and presentation lengths
- **Tracking documentation growth** — run OCC in CI to monitor how documentation scales over time, catch bloat early, or enforce minimums
- **Onboarding** — new team members get a quick sense of a project's documentation footprint before diving in
- **Migration planning** — when moving to a new platform, know exactly what you're dealing with across hundreds of files and formats

### For AI Agents

- **Context budgeting** — LLMs have finite context windows. OCC's word and page counts let agents estimate how much of a document set they can ingest before hitting token limits
- **Prioritization** — an agent deciding which documents to read can use OCC's JSON output to rank files by size, word count, or type, focusing on the most relevant content first
- **RAG chunk mapping** — `--structure --format json` outputs heading trees with character offsets, enabling chunk-to-section mapping, scoped retrieval, and citation paths in RAG pipelines
- **Document triage** — `occ doc inspect --format json` surfaces risk flags, content stats, structure, and token estimates before an agent reads the full document
- **Spreadsheet triage** — `occ sheet inspect --format json` exposes sheet visibility, formulas, links, comments, schema hints, and token estimates before an agent expands workbook contents
- **Presentation triage** — `occ slide inspect --format json` provides slide inventory, risk flags, and content previews for quick assessment
- **Table extraction** — `occ table inspect --format json` extracts structured table data (headers, rows, cells) from documents, giving agents direct access to tabular content without parsing raw XML
- **Repository mapping** — agents exploring an unfamiliar codebase can combine `occ --format json` for document inventory with `occ code ... --format json` for symbol and relationship data
- **Pipeline integration** — JSON output pipes directly into agent toolchains for automated document analysis, summarization, or compliance checking

## How It Works

OCC is written in TypeScript and uses [fast-glob](https://github.com/mrmlnc/fast-glob) for file discovery, dispatches to format-specific parsers (mammoth for DOCX, pdf-parse for PDF, SheetJS for XLSX/ODS inspection, JSZip + officeparser for PPTX/ODF metrics), aggregates metrics, and renders output via cli-table3. For code metrics, it shells out to a vendored [scc](https://github.com/boyter/scc) binary (auto-downloaded during `npm install`, with PATH fallback).

For structure extraction (`--structure`), documents are first converted to markdown (mammoth + [turndown](https://github.com/mixmark-io/turndown) for DOCX, pdf-parse's per-page text with `[Page N]` markers for PDF), then headers are extracted and assembled into a tree with dotted section codes.

For `occ code`, OCC opens a freshness-checked, sectioned on-disk index and falls back to (or is forced into, via `--no-cache`) a direct build when no valid entry exists. JavaScript and TypeScript are parsed with the TypeScript compiler API, Vue Single-File Components are split with `@vue/compiler-sfc` and forwarded into the same TS pipeline, the other supported languages use vendored tree-sitter grammars, and the query engine resolves symbols, imports, calls, inheritance, ambiguities, and dependency categories. There is still no daemon or background service: the persisted index lives in an external cache directory, is validated against the working tree before reuse, and `occ cache prune` removes old or superseded entries.

## Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions and guidelines.

## License

[MIT](LICENSE)
