Skip to main content

Configuration

All configuration lives in .ovecc/config.toml in the analyzed repository. Every key is optional; ovecc init writes a fully commented template where the commented values are the defaults.

The template

# ovecc configuration - every key is optional; commented values are the defaults.
# Machine-readable reference: `ovecc capabilities`.

[output]
# text | json | ndjson | markdown (sarif / codeclimate via --format)
# default_format = "text"

[index]
# Extra paths to skip, on top of the built-ins (node_modules, target, dist, .venv, ...).
# exclude = ["vendored"]
# Flag manifest dependencies that no indexed file imports (off by default:
# config-only usages cause false positives).
# detect_unused_deps = true
# LCOV tracefile for line coverage. Unset looks in coverage/lcov.info,
# lcov.info, coverage.lcov; finding none is not an error.
# coverage = "coverage/lcov.info"

# --- how modules are derived from the directory tree ---
# [architecture]
# Path segments below src/ (or packages/, apps/, ...) that define a module.
# Raise for monorepos that nest everything under one directory.
# module_depth = 1

# --- governance: declarative architecture rules, enforced at index time ---
# [[rules.boundaries]]
# name = "billing must not depend on user"
# source = "billing"
# target = "user"
# allowed = false
# severity = "high"

# [[rules.banned_imports]]
# name = "no-deprecated-lodash"
# pattern = "lodash"
# message = "use es-toolkit instead"
# severity = "medium"

# --- architecture diagnosis thresholds ---
# [diagnose]
# min_confidence = 0.5

[output]

KeyDefaultEffect
default_format"text"Format used when --format isn't passed: text, json, ndjson, or markdown (sarif/codeclimate remain flag-only)

[index]

KeyDefaultEffect
include[]Globs to restrict indexing to, e.g. ["src/**", "packages/**"]. Empty means the whole repository
exclude[]Extra globs to skip, on top of the built-ins (node_modules, target, dist, .venv, …). The --exclude flag adds to this per run
max_file_size_bytes5 MiBSkip files larger than this. A file above it is almost always a generated or vendored blob, and parsing one costs memory and latency for no signal
index_generatedfalseIndex files that look generated or vendored (minified bundles, WASM glue, @generated / DO NOT EDIT markers). Off by default: they are the dominant false-positive source in complexity, dead-code, and security
detect_unused_depsfalseReport manifest dependencies no indexed file imports (unused-dependency, unused-dev-dependency, unused-optional-dependency). Off by default because config-only usages (tools loaded by name from a config file) cause false positives
coverageunsetLCOV tracefile to read line coverage from, relative to the repository root

Coverage

When coverage is unset, ovecc looks in the conventional places — coverage/lcov.info, lcov.info, coverage.lcov — which is where nyc, Jest, and Vitest write by default, and the two names the Rust coverage tools are usually pointed at. Finding nothing there is not an error, just a run without coverage.

With a tracefile indexed, line coverage joins the hotspots rows, and a component's min_coverage floor in the architecture contract becomes checkable. Without one, a component is unmeasured rather than at 0%.

[architecture]

KeyDefaultEffect
module_depth1How many path segments below a recognized source container (src/, packages/, apps/, …) define a module
module_strategyautoHow modules are inferred; explicit mappings go in [[architecture.modules]]
ownership_sources[]Where to read ownership from, e.g. ["CODEOWNERS", ".github/CODEOWNERS"]

module_depth = 1 groups src/<name>/… as <name>. Raise it for monorepos that nest the whole tree under one directory: VS Code keeps everything under src/vs, so depth 1 collapses the repo into a single vs module, while depth 2 recovers the real boundaries (vs/editor, vs/workbench, vs/platform).

This is the knob to reach for when diagnose reports components that feel too coarse. For the graph-derived alternative that ignores the directory tree entirely, see components.

[[rules.boundaries]]

Forbid (or document as allowed) a module-to-module dependency. Evaluated at index time; violations surface as CrossDomainDependency findings under your rule's name.

KeyRequiredMeaning
nameyesHuman name — becomes the finding's rule label
sourceyesModule the dependency originates from
targetyesModule being depended on
allowedyesfalse forbids the edge
severityyeslow / medium / high / critical

Modules are inferred from directory structure — check yours with ovecc export graph or ovecc query "module <name>".

[[rules.banned_imports]]

Ban imports by specifier pattern.

KeyRequiredMeaning
nameyesRule label (findings read banned-import/<name>)
patternyesexact, prefix*, *suffix, or *infix* — matched against the import specifier, so lodash* catches lodash/groupBy too
messagenoGuidance shown with the finding
severityyeslow / medium / high / critical

[diagnose]

KeyDefaultEffect
min_confidence0.5Findings below this deterministic confidence are dropped from diagnose

Versioning the config

ovecc init git-ignores the whole .ovecc/ directory. To share rules with your team, switch the entry to ignore the directory's contents and re-include the config (Git cannot re-include files under a fully ignored directory):

# ovecc local state (database + parse cache)
.ovecc/*
!.ovecc/config.toml
  • Governance guide — boundaries, banned imports, suppressions, and the baseline ratchet in practice
  • capabilities — the machine-readable version of everything configurable