---
name: occ
description: >-
  Use occ to inspect unfamiliar repositories and office documents efficiently
  for coding tasks. It emits token-budgeted, JSON-first workspace reconnaissance
  ("occ describe", "occ workspace analyze"); DOCX/PDF/XLSX/PPTX/ODF and table
  triage ("occ doc|sheet|slide|table inspect"); and structural code exploration
  across JS/TS, Vue, Python, Go, Rust, Java, C/C++, Kotlin, and other
  tree-sitter languages ("occ code map|find|doc|source|check|analyze|diff").
  Use it to track entities across renames, inspect Git evidence and history,
  emit pinned work episodes or entity graphs ("occ atoms", "occ code
  graph-export"), serve MCP clients, understand a codebase without reading it
  all, or whenever the user mentions occ.
metadata:
  version: 0.20.0
license: MIT
---

# occ — Office Cloc and Count

`occ` is a **read-only** analysis CLI that helps an agent understand a repository
or a set of office documents _cheaply_, before spending context reading files in
full. It never modifies the target project. It shells out to a vendored `scc`
for code metrics and to `git` for git context.

Design principles to lean on:

- **JSON-first** — pass `--format json` to almost any command for compact,
  machine-parseable output. Add global `--pretty` only when a human needs
  indentation; parse the JSON instead of depending on its bytes.
- **Token-budgeted** — `occ code map/pack` and `occ code diff` accept `--map-tokens <n>`
  (and the root scan accepts `--token-budget <n>`). Pair with `--tokenizer o200k_base`
  (or `cl100k_base`) for an _exact_ BPE budget instead of the default heuristic estimate.
  The ceiling covers the complete emitted format, including envelopes and markers. Over-budget
  root JSON stays parseable by omitting whole rows and reporting `truncated`/`omitted`; text carries
  a priced `[truncated at N tokens]` marker. If a map or entity-context envelope cannot fit at all,
  follow its structured narrowing `argv`; `projectedTokens` is guidance, not measured usage.
- **Structural for named symbols/relations, shell for text/config/quick facts** — use
  `occ code map`, `occ code find name`, `occ code source`, and `occ code analyze callers`
  when the target is a symbol, call path, class tree, or import relationship. Use `rg`,
  `grep`, or direct file reads for strings, config keys, generated files, and one-off facts.
- **Stream large output to a file** — for big maps/packs/analyses, add `-o <file>` and
  read it back selectively rather than flooding the conversation.
- **Reuse freshness-checked indexes** — code commands persist their sectioned
  graph outside the target repository and report `meta.loadSource` in JSON;
  use `--no-cache` only when you deliberately want a direct build.

## Invocation

```bash
occ <command> ...            # if installed globally (npm i -g @cesarandreslopez/occ)
npx @cesarandreslopez/occ <command> ...   # without a global install
```

Run `occ --help` or `occ <group> --help` to see every flag.

## Decision table — pick the right command

| If you need to…                                          | Start with                                                                                          | Deep reference                                   |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| Tell what kind of project a directory is                 | `occ describe <dir> --format json`                                                                  | [reference/workspace.md](reference/workspace.md) |
| Inventory a whole workspace (code + docs + structure)    | `occ workspace analyze <dir> --format json -o ws.json`                                              | [reference/workspace.md](reference/workspace.md) |
| Inventory / cross-reference office docs in a tree        | `occ workspace documents <dir> --format json`                                                       | [reference/workspace.md](reference/workspace.md) |
| Get document + code metrics for some directories         | `occ <dirs> --format json --structure`                                                              | [reference/workspace.md](reference/workspace.md) |
| Preflight one DOCX / PDF / ODT before reading it         | `occ doc inspect <file> --format json`                                                              | [reference/documents.md](reference/documents.md) |
| Preflight an XLSX / ODS workbook (schema, sheets, risks) | `occ sheet inspect <file> --format json`                                                            | [reference/documents.md](reference/documents.md) |
| Preflight a PPTX / ODP deck                              | `occ slide inspect <file> --format json`                                                            | [reference/documents.md](reference/documents.md) |
| Extract structured table data from a document            | `occ table inspect <file> --format json`                                                            | [reference/documents.md](reference/documents.md) |
| Pull entities/keywords (emails, URLs, dates) from a doc  | `occ doc entities <file>`                                                                           | [reference/documents.md](reference/documents.md) |
| Check shipped features or runtime readiness              | `occ health --format json` · `occ probe . --format json`                                            | [reference/commands.md](reference/commands.md)   |
| Check entity-cache freshness without building            | `occ code status --path . --format json`                                                            | [reference/code.md](reference/code.md)           |
| Bound or remove superseded OCC caches                    | `occ cache prune --max-age 30 --format json`                                                        | [reference/commands.md](reference/commands.md)   |
| Get oriented in an unfamiliar codebase                   | `occ code map --path . --map-tokens 8000 --tokenizer o200k_base -o map.md`                          | [reference/code.md](reference/code.md)           |
| Embed a repo slice in a cached prompt layer              | `occ code map --path . --map-tokens 4096 --layout stable`                                           | [reference/code.md](reference/code.md)           |
| See directory shape or source-token spend                | `occ code dirtree --path . --tokens --top 10 --format json`                                         | [reference/code.md](reference/code.md)           |
| Pull file _contents_ within a token budget               | `occ code pack --path . --map-tokens 8000 --tokenizer o200k_base -o pack.md`                        | [reference/code.md](reference/code.md)           |
| Find a symbol / concept (best-effort)                    | `occ code find fused "<query>" --format json`                                                       | [reference/code.md](reference/code.md)           |
| Find an exact symbol by name or type (typed signatures)  | `occ code find name <Name> --format json`                                                           | [reference/code.md](reference/code.md)           |
| Read a symbol contract without its body                  | `occ code doc <name> --file <path> --format json` (`--compact-honesty` for batches)                 | [reference/code.md](reference/code.md)           |
| Read one known symbol body                               | `occ code source --node-id <nodeId> --format json`                                                  | [reference/code.md](reference/code.md)           |
| Verify exact/normalized-token symbol identity            | `occ code symbol-hash --file <path> --name <name> --format json`                                    | [reference/code.md](reference/code.md)           |
| Check parse syntax after edits                           | `occ code check <file> --format json`                                                               | [reference/code.md](reference/code.md)           |
| See who calls X / what X calls                           | `occ code analyze callers <fn>` · `occ code analyze calls <fn>`                                     | [reference/code.md](reference/code.md)           |
| Inspect imports / module coupling                        | `occ code analyze deps <target>` · `occ code analyze coupling <target>`                             | [reference/code.md](reference/code.md)           |
| Discover module clusters from the import graph           | `occ code clusters --path . --format json`                                                          | [reference/code.md](reference/code.md)           |
| Trace bounded call flows from ranked entry points        | `occ code flows --path . --format json`                                                             | [reference/code.md](reference/code.md)           |
| List / re-check cross-module seams (+ co-change)         | `occ code seams --since "90 days ago" --format json` · `occ code seams --resolve <seamKey>`         | [reference/code.md](reference/code.md)           |
| Check named structural facts                             | `occ code facts --list` · `occ code facts <predicate> --format json`                                | [reference/code.md](reference/code.md)           |
| Run a custom structural AST query                        | `occ code ast --lang <x> --snippet '<code>'` · `occ code tsquery --lang <x> --query '<scm>'`        | [reference/code.md](reference/code.md)           |
| Match a code-shaped pattern or custom rules              | `occ code pattern --lang <x> --pattern '<code with $META>'` · `occ code facts --rules rules.json`   | [reference/code.md](reference/code.md)           |
| See which _symbols_ changed in a diff                    | `occ code diff --base <ref> --map-tokens 4096 --format json`                                        | [reference/code.md](reference/code.md)           |
| Find durable entities across renames and moves           | `occ code entities <query> --format json`                                                           | [reference/entity.md](reference/entity.md)       |
| Rank logic-changing entity hotspots                      | `occ code hotspots --limit 20 --format json`                                                        | [reference/entity.md](reference/entity.md)       |
| Find functions whose logic changes land together         | `occ code cochange [entity] --min-count 3 --format json`                                            | [reference/entity.md](reference/entity.md)       |
| Find docs that predate proved changes to named entities  | `occ code drift --dirs docs/,README.md --format json`                                               | [reference/entity.md](reference/entity.md)       |
| Check generated/private docs from their source commit    | `occ code drift-documents --path .` (NDJSON stdin)                                                  | [reference/entity.md](reference/entity.md)       |
| Capture a verifiable memory anchor for an entity         | `occ code anchor <entity> --format json`                                                            | [reference/entity.md](reference/entity.md)       |
| Grade stored memory anchors against proved history       | `occ code verify-anchors --path .` (NDJSON stdin)                                                   | [reference/entity.md](reference/entity.md)       |
| Compare entity-level changes between refs or trees       | `occ code diff --entities --base <ref> --head <ref> --format json`                                  | [reference/entity.md](reference/entity.md)       |
| Gate on proved semantic entity drift                     | `occ code diff --entities --file <path> --exit-code`                                                | [reference/entity.md](reference/entity.md)       |
| Find untested logic and touched module seams             | `occ code diff --obligations --base <ref> --format json`                                            | [reference/entity.md](reference/entity.md)       |
| Find affected entities and runnable tests                | `occ code impact <entity> --scope tests --format json`                                              | [reference/entity.md](reference/entity.md)       |
| Attribute or follow one entity through history           | `occ code blame <file>` · `occ code log <entity>`                                                   | [reference/entity.md](reference/entity.md)       |
| Bundle one entity and its graph neighbours               | `occ code context <entity> --token-budget 8000 --format json`                                       | [reference/entity.md](reference/entity.md)       |
| Serve entity intelligence to an MCP client               | `occ mcp --root <repo>`                                                                             | [reference/entity.md](reference/entity.md)       |
| List changed files / bounded patch / churn / co-change   | `occ git changed` · `occ git diff --patch --map-tokens 2048` · `occ git churn` · `occ git cochange` | [reference/git.md](reference/git.md)             |
| Capture immutable repository evidence as NDJSON          | `occ git capture --path . --ref HEAD`                                                               | [reference/git.md](reference/git.md)             |
| Parse exact Git blobs without checking them out          | `occ code blob-structure --path .` (NDJSON requests on stdin)                                       | [reference/code.md](reference/code.md)           |
| Emit resumable, body-free work episodes at a pin         | `occ atoms --path . --ref HEAD`                                                                     | [reference/entity.md](reference/entity.md)       |
| Verify persisted Git coordinates at an optional pin      | `occ code coordinate-verify --path . --ref HEAD`                                                    | [reference/entity.md](reference/entity.md)       |
| Export the pinned entity co-change/incidence graph       | `occ code graph-export --path . --ref HEAD`                                                         | [reference/entity.md](reference/entity.md)       |

## Recommended agent workflows

- **Land in a new repo:** `occ describe . --format json` → `occ code map --path . --map-tokens 8000 --tokenizer o200k_base -o map.md`, read the map, then drill in with `occ code find` / `occ code analyze`.
- **Read a symbol precisely:** `occ code find name <X> --format json` → take the unique `nodeId` → `occ code source --node-id <nodeId> --format json`; narrow the find with `--file` or `--type` when needed.
- **Find name then read:** `occ code find name TypeName --format json` → if one match, `occ code source --node-id <nodeId>`; if ambiguous, rerun with `--file` or `--type`.
- **Return prompt-ready references:** add `--inline-context 2` to `find name`, `find fused`, `analyze callers`, `analyze deps`, `seams`, `impact`, or `context`. For compact score-free find output, use `--format citations` (not `--citations --format json`, which errors); it states zero-hit coverage and refuses stale working-tree source rather than showing unverified bytes.
- **Trace impact:** `occ code impact targetFn --scope all --format json` when durable identity or affected tests matter; use `occ code analyze callers targetFn --format json` for a graph-only caller listing. Before treating a missing dependent or test as absence, require full `coverage` and inspect diagnostics (or run `occ code status --format json`) for bounded or degraded evidence.
- **First contact on a large repo:** start the CLI with `occ code entities --max-commits 200 --format json`, then run `occ code status --max-commits 200 --format json` and inspect `truncated`/reasons. For MCP, start `occ mcp --root . --max-commits 200`, let the first request finish, then call `occ_status`; progress notifications help only clients that honor them, while the explicit bound and warm cache prevent retry livelock.
- **Post-edit syntax gate:** run `occ code check <changed-file> --format json`; it exits nonzero only when `valid` is `false`.
- **Search by code shape, not name:** when the target is a pattern rather than a symbol ("every `await` inside a `catch`", "switch without a `default`"), prefer `occ code pattern --lang <x> --pattern '<code with $META>'` — patterns are written as example code, and `--rule-file` adds relational (`inside`/`has`) and negated (`not`) clauses. Drop to `occ code ast` + `occ code tsquery --query-file q.scm` when you need raw grammar-node precision. Resolved hits carry a `nodeId` for follow-up `source`/`impact` queries. For a known name use `find name`; for plain text use `rg`.
- **Review a change:** `occ git changed` → `occ code diff --base <base> --format json` for symbol-level scope → `occ git diff --patch --map-tokens 4096` for a bounded patch.
- **Gate on proved structural drift:** `occ code diff --entities --file <path> --exit-code`; read the authoritative `wholeDiffSemantic` summary. Only `semantic-no-op` with complete coverage proves a no-op for its recorded Git scope; `unknown` stays zero but is not a no-op — add `--fail-on-unknown` when CI must refuse unproven evidence.
- **Check verification obligations:** `occ code diff --obligations --base <ref> --exit-code`; this implies entity diff and fails only when a complete reverse traversal proves that changed logic reaches no test. With `--fail-on-unknown`, partial obligation coverage also fails. Read `seamCrossings` before choosing integration checks. (The NDJSON evidence streams take `--require-complete` for the same fail-on-partial stance.)
- **Estimate blast radius:** `occ git cochange --target <path> --format json` for historically coupled files, then use `occ code dirtree --focus-path <dir> --mode map` for structural neighborhood context.
- **Find semantic fellow-travellers:** `occ code cochange <entity> --format json` follows lineage ids through renames, filters cosmetic/identity-only commits, and states both the entity-change and indexed-commit denominators.
- **Pin a symbol, compare identity later:** `occ code symbol-hash --file <path> --name <name> --format json`, persist `key` + the nested hash tuple (including `exactSpanHash` when present), then pass it back as `expected`. Normalized-token matches now grade `normalized-equal` by default (`--no-normalized-equal-verdict` restores the legacy `cosmetic-drift` label); neither label proves a semantic no-op, and `semantic-drift` proves only that normalized tokens differ. Add `--resolve-gone` only when a lineage successor is worth the indexing cost.
- **Import repository experience without source bodies:** pin a commit, run `occ atoms --path . --ref <oid>`, and validate the whole stream with `collectAtomsRun`. Persist Git coordinates as identity, keep all-parent `dag1:*` separate from first-parent `ent1:*`, and accept their relation only from a resolved pinned `lineage-head`. Resume and `--since` warm-replay the bounded run before filtering output.
- **Verify a stored pointer:** send `{ request_id, coordinate }` NDJSON to `occ code coordinate-verify --path . --ref <oid>`. Require `verified`; `mismatch` and `unavailable` are explicit failures to re-use the pointer.
- **Discover boundaries from observed structure:** run `occ code graph-export --path . --ref <oid>` after episode import and validate with `collectEntityGraph`. Co-change uses every parent edge; seams are pinned import/call module pairs, while calls and inheritance remain directed incidence.
- **Map the strongest module relationships:** `occ code seams --since "90 days ago" --format json` ranks cross-module seams by co-change lift; persist `seamKey` and re-check with `occ code seams --resolve <seamKey>` (a `missing` answer is drift, not clean).
- **Process a document drop:** `occ <dir> --format json` for the inventory → `occ doc/sheet/slide inspect --format json` per file → `occ table inspect` to pull tabular data → read only what matters.

## Notes

- For the full flag list of every command, read [reference/commands.md](reference/commands.md).
- Languages with first-class code support: JavaScript, TypeScript, Vue SFC, Python, Go, Rust, Java, C/C++, Kotlin, Ruby, PHP, C#, Scala, and Swift.
- `--format json` is the compact integration surface; tabular output and JSON
  `--pretty` are for humans. NDJSON evidence streams do not use `--pretty`.
- Exit codes differ by family: entity commands (`entities`, `hotspots`, `cochange`, `impact`, `blame`, `log`, `context`, `diff --entities`) treat a miss or ambiguity as a normal answer and exit 0 unless `--strict`; `occ code drift --exit-code` fails only for a row with subsequent CST-proved logic drift; `occ code drift-documents --strict` fails when any input document is refused; `occ code verify-anchors --strict` fails on refusals only (`--fail-on-unknown` gates unknown verdicts separately); `occ code source`, `occ code doc`, `occ code symbol-hash`, and `occ code seams --resolve` exit nonzero on any non-resolution.
- The first entity command on a repository walks git history and is the slow one; bound first contact deliberately on a large repo, inspect status for truncation, and reuse the cache (outside the repo) so later runs are incremental.
- Code exploration also caches outside the repo and validates the working-tree
  manifest before reuse. `occ code status` reports aggregate bytes/entries;
  only `occ cache prune` deletes old or superseded entries.
- The `OCC_TOKENIZER` environment variable overrides the default `heuristic` tokenizer wherever `--tokenizer` is accepted — except `occ atoms`, whose patch measures are always exact (`o200k_base` by default, `cl100k_base` opt-in) and ignore the environment variable.
- Embedding `occ` in a long-running host (an editor/agent integration that holds an index across turns)? The in-process APIs include fuzzy code search, maps and trees, plus concurrency-safe entity sessions with freshness, explicit changed-file updates, and shared-budget batched context. See [reference/code.md](reference/code.md) and [reference/entity.md](reference/entity.md); feature-detect formats and APIs through `health().features`.

## Reporting occ issues upstream

If you hit an occ bug (wrong output, a crash, a doc/CLI mismatch, a misleading honesty block) or a capability gap that would have helped your task, report it upstream at <https://github.com/cesarandreslopez/occ/issues> so it gets fixed.

1. Search for an existing report first: `gh issue list --repo cesarandreslopez/occ --search "<keywords>" --state all`.
2. Confirm with the user before filing — creating an issue is a public action on their behalf.
3. File with `gh issue create --repo cesarandreslopez/occ --title "<summary>" --body "<details>"`. If `gh` is unavailable or unauthenticated, hand the user the drafted title/body and the issues URL instead.

Include in the body: `occ --version` output, OS and Node version, the exact command with flags, expected vs. actual behavior (trim JSON to the relevant part, keep any `honesty` block), and a minimal reproduction. For enhancement ideas, describe the task you were doing and what occ could not answer.
