Output formats
Every command renders via --format <FORMAT> (default text, configurable through
[output] default_format):
| Format | For | Notes |
|---|---|---|
text | Humans in a terminal | The default; examples throughout these docs |
json | Tools and agents | One envelope object (below) |
ndjson | Streaming pipelines | A meta record first, then one JSON object per item |
markdown | PR comments, wikis, reports | review --format markdown is a ready-to-post PR comment |
sarif | GitHub code scanning | SARIF 2.1.0; for finding-shaped commands |
codeclimate | GitLab Code Quality | For finding-shaped commands |
Two universal properties:
- Determinism — an unchanged database renders byte-identical output in every format.
- Path normalization — repo-relative paths with POSIX separators, on every platform.
The JSON envelope
{
"schema_version": 1,
"tool": { "name": "ovecc", "version": "0.1.0" },
"command": "summary",
"meta": {
"metrics": {
"coupling_density": {
"description": "Realized module edges over all possible directed edges.",
"range": "[0, 1]",
"interpretation": "lower is looser coupling"
}
},
"rules": { "...": {} }
},
"data": {
"repository_root": "~/projects/acme-shop",
"files": 11,
"modules": 5,
"circular_dependencies": 1,
"coupling_density": 0.35,
"hotspots": [
{ "module": "services", "score": 10, "fan_in": 2, "fan_out": 2, "instability": 0.5 }
]
}
}
| Field | Contract |
|---|---|
schema_version | Integer. Additive changes never bump it — detect new fields by key presence, not by comparing the number |
tool | Name + version of the emitting binary |
command | Which command produced this payload |
meta | Metric/rule definitions so values are interpretable standalone. Omit with --no-meta (the MCP server does automatically) |
data | The command-specific payload |
JSON keeps raw values (full-precision floats); text/markdown round for readability.
NDJSON
One line per item, with a leading meta record — ideal for jq-style streaming:
{"type":"meta","schema_version":1,"tool":{...},"command":"violations","meta":{"rules":{...}}}
{"id":"finding:69a8faef…","kind":"hardcoded_secret","severity":"critical","rule_name":"security/secret","title":"Hardcoded secret: Stripe secret key","evidence":[{"file_path":"src/services/billing.ts","line":5,"detail":"Stripe secret key"}],"type":"violation"}
{"id":"finding:ac8a7ed6…","kind":"tainted_flow","severity":"critical","rule_name":"taint/command","title":"Potential tainted flow: GET /admin/ping -> command (command)","evidence":[...],"type":"violation"}
ovecc violations --format ndjson | jq -r 'select(.type=="violation" and .severity=="critical") | .title'
SARIF
--format sarif emits SARIF 2.1.0 with the full rule catalog embedded, ready for
GitHub code scanning upload:
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [{ "tool": { "driver": { "name": "ovecc", "version": "0.1.0", "rules": [ ... ] } } }]
}
See CI integration.
Code Climate
--format codeclimate emits the Code Quality report format GitLab renders on merge
requests — see the GitLab recipe.
Pipes
A downstream reader closing the pipe early (ovecc report | head, quitting a pager)
is not an error: output stops quietly and the exit code is 0.