Skip to content

Output formats

Codefang supports six output formats. Each is suited to a different use case, from human review to CI pipelines to interactive exploration. Select a format with the --format flag:

codefang run -a static/complexity --format text .

Format overview

Format Flag Value Content Type Best For
Text text Plain text Human review in a terminal
JSON json application/json Programmatic consumption, CI pipelines
YAML yaml text/yaml Human-readable structured data, config integration
Compact compact Plain text Quick summaries, log ingestion
NDJSON ndjson application/x-ndjson Streaming DWH ingestion (ClickHouse, BigQuery)
Time Series timeseries application/json Chronological analysis, dashboards
Plot plot text/html Interactive charts, reports, presentations

Text

Flag: --format text

Human-readable table output with optional color. This is the most readable format for terminal review. Static analyzers render section headers, aligned columns, and summary lines. History analyzers print the codefang (v2): version header once, then one section per analyzer: its id (history/devs:) followed by a summary box with the key figures and the top items (top contributors, most coupled files, typo fixes, anomalous ticks, …).

Use --no-color (or NO_COLOR=1) to strip ANSI escape codes (useful when piping to a file).

codefang run -a static/complexity --format text --no-color .
Example Output
Complexity Analysis
===================

File                          Functions   Avg Complexity   Max Complexity
----------------------------  ----------  ---------------  --------------
internal/framework/runner.go       12          4.2              11
internal/analyzers/burndown/...    8           3.8              9
pkg/gitlib/repository.go      15          3.1              7
cmd/codefang/commands/run.go  22          2.9              8

Summary
-------
Total files:       47
Total functions:   312
Average:           2.6
Maximum:           11 (internal/framework/runner.go:RunStreaming)

When to Use

  • Reviewing results directly in a terminal session
  • Quick manual inspection during development
  • Sharing results in pull request comments (with --no-color)

JSON

Flag: --format json

Structured JSON output. This is the default format. The output is wrapped in a versioned envelope with metadata, per-analyzer schema manifests, and reports. Each analyzer's report contains typed arrays of records with consistent identifiers (source_file, language, directory on function records; start_time/end_time on time-series ticks; split name/email on developer records).

codefang run --format json .
Example Output (Combined Static + History)
{
  "version": "codefang.run.v1",
  "metadata": {
    "repo_path": "/home/user/sources/myproject",
    "repo_name": "myproject",
    "analyzed_at": "2026-04-07T23:33:00Z",
    "codefang_version": "0.1.0"
  },
  "analyzers": [
    {
      "id": "static/complexity",
      "mode": "static",
      "schema": {
        "function_complexity": {
          "type": "list",
          "grain": "function",
          "description": "Per-function cyclomatic and cognitive complexity"
        },
        "aggregate": {
          "type": "aggregate",
          "description": "Summary statistics"
        }
      },
      "report": {
        "function_complexity": [
          {
            "name": "RunStreaming",
            "source_file": "internal/framework/runner.go",
            "language": "go",
            "directory": "internal/framework",
            "cyclomatic_complexity": 11,
            "cognitive_complexity": 15,
            "nesting_depth": 3,
            "lines_of_code": 85,
            "complexity_density": 0.129,
            "risk_level": "MEDIUM"
          }
        ],
        "aggregate": {
          "total_functions": 312,
          "average_complexity": 2.6,
          "max_complexity": 11,
          "health_score": 82.5
        }
      }
    },
    {
      "id": "history/sentiment",
      "mode": "history",
      "schema": {
        "time_series": {
          "type": "time_series",
          "grain": "tick",
          "description": "Per-tick sentiment scores"
        }
      },
      "report": {
        "time_series": [
          {
            "tick": 0,
            "start_time": "2024-01-15T10:30:00Z",
            "end_time": "2024-01-16T08:45:00Z",
            "sentiment": 0.72,
            "classification": "positive",
            "comment_count": 5,
            "commit_count": 12
          }
        ]
      }
    }
  ]
}

Key output fields added for analytics/DWH consumption:

Field Present On Description
source_file All function records Relative file path (e.g., "pkg/api/server.go")
language All function records Detected language (e.g., "go", "python")
directory All function records Parent directory (e.g., "pkg/api")
start_time All time-series ticks RFC 3339 tick start timestamp
end_time All time-series ticks RFC 3339 tick end timestamp
email Developer records Separated from name (no more pipe-delimited)
schema Each analyzer section Field type, grain, and description metadata
metadata Top-level envelope Repo name, analysis timestamp, version

When to Use

  • CI/CD pipelines that parse results programmatically
  • Loading into data warehouses (ClickHouse, BigQuery, Snowflake)
  • Building BI dashboards from function-level metrics

YAML

Flag: --format yaml

YAML-formatted output. Produces the same logical structure as JSON but in YAML syntax. Useful when the output will be merged with other YAML-based tooling or when readability of structured data is preferred over plain tables.

codefang run -a static/complexity --format yaml .
Example Output
complexity:
  files:
    - path: internal/framework/runner.go
      functions:
        - name: RunStreaming
          complexity: 11
          lines: 85
          start_line: 42
          end_line: 127
        - name: NewRunnerWithConfig
          complexity: 3
          lines: 22
          start_line: 15
          end_line: 37
      summary:
        total_functions: 12
        average_complexity: 4.2
        max_complexity: 11
  summary:
    total_files: 47
    total_functions: 312
    average_complexity: 2.6
    max_complexity: 11

When to Use

  • Integration with YAML-native workflows (Ansible, Kubernetes configs)
  • Human review of structured data without JSON bracket noise
  • Diffing results across runs with standard text diff tools

Compact

Flag: --format compact

Minimal single-line-per-analyzer output. Each analyzer emits a one-line summary with key metrics. No headers, no detail rows.

codefang run -a 'static/*' --format compact .
Example Output
complexity  files=47  functions=312  avg=2.6  max=11
comments    files=47  ratio=0.18  missing_doc=23
halstead    files=47  avg_volume=842.3  avg_difficulty=12.1
cohesion    files=47  avg_lcom=0.34
imports     files=47  total=189  unique=62

When to Use

  • Log aggregation systems that expect single-line records
  • Quick at-a-glance summaries in scripts
  • Embedding in commit messages or Slack notifications

NDJSON

Flag: --format ndjson

Newline-delimited JSON. Each analyzer produces one compact JSON line. If metadata is present, a metadata line is emitted first. This format enables streaming ingestion into columnar DWH systems like ClickHouse, where each line can be parsed independently without buffering the entire file.

codefang run --format ndjson . > output.ndjson
Example Output
{"version":"codefang.run.v1","metadata":{"repo_name":"myproject","analyzed_at":"2026-04-07T23:33:00Z","codefang_version":"0.1.0"}}
{"id":"static/complexity","mode":"static","report":{"function_complexity":[...],"aggregate":{...}}}
{"id":"static/halstead","mode":"static","report":{"function_halstead":[...]}}
{"id":"history/sentiment","mode":"history","report":{"time_series":[...]}}

Each line is independently parseable JSON. The file can be processed with standard tools:

# Extract a single analyzer
grep '"static/complexity"' output.ndjson | jq .report.aggregate

# Count lines
wc -l output.ndjson

# Stream into ClickHouse
cat output.ndjson | clickhouse-client --query "INSERT INTO codefang FORMAT JSONEachRow"

When to Use

  • Streaming ingestion into ClickHouse, BigQuery, or Kafka
  • Processing large reports without loading the full file into memory
  • Unix pipeline workflows (grep, jq, wc)

Time series

Flag: --format timeseries

A unified chronological JSON array that merges data from all selected history analyzers into a single stream keyed by commit. Each entry contains commit metadata plus per-analyzer data for that commit.

This format is only meaningful for history analyzers. Every history analyzer contributes its per-commit data (typos, which has no per-commit summary, contributes its name only); a static-only selection rejects the format.

codefang run -a history/devs,history/sentiment --format timeseries .

--format timeseries --ndjson emits the document's commits array, one JSON line per commit, with every selected analyzer merged into that line.

Example Output
{
  "version": "codefang.timeseries.v1",
  "tick_size_hours": 24,
  "analyzers": [
    "devs",
    "sentiment"
  ],
  "commits": [
    {
      "hash": "a1b2c3d4e5f6...",
      "timestamp": "2025-03-15T10:30:00Z",
      "author": "alice@example.com",
      "tick": 0,
      "devs": {
        "added": 142,
        "removed": 38,
        "changed": 5,
        "languages": {
          "Go": { "added": 120, "removed": 30 },
          "YAML": { "added": 22, "removed": 8 }
        }
      },
      "sentiment": {
        "positive": 2,
        "negative": 0,
        "neutral": 1,
        "score": 0.67
      }
    },
    {
      "hash": "f6e5d4c3b2a1...",
      "timestamp": "2025-03-16T14:22:00Z",
      "author": "bob@example.com",
      "tick": 1,
      "devs": {
        "added": 57,
        "removed": 12,
        "changed": 3,
        "languages": {
          "Go": { "added": 57, "removed": 12 }
        }
      },
      "sentiment": {
        "positive": 0,
        "negative": 1,
        "neutral": 0,
        "score": -0.33
      }
    }
  ]
}

Schema details:

Field Type Description
version string Schema version. Always codefang.timeseries.v1.
tick_size_hours float64 Duration of one tick in hours (default: 24).
analyzers []string Ordered list of analyzer flags that contributed data.
commits []object Chronologically ordered commit entries.
commits[].hash string Full commit hash.
commits[].timestamp string ISO 8601 / RFC 3339 timestamp.
commits[].author string Commit author identifier.
commits[].tick int Tick index (integer time bucket).
commits[].<analyzer> object Per-analyzer data; key matches the analyzer flag name.

When to Use

  • Building custom dashboards (Grafana, Jupyter, Observable)
  • Correlating metrics across analyzers over time
  • Feeding into anomaly detection or ML pipelines

Plot

Flag: --format plot

Requires: --output <dir> (-o <dir>)

Multi-page interactive HTML report with charts rendered by go-echarts. Each analyzer gets its own HTML page, plus an index.html with navigation cards. The output directory can be opened in any browser.

Both static and history analyzers produce the same multi-page layout.

# Generate multi-page report
codefang run -a 'static/*' --format plot -o ./report .
open ./report/index.html

# History analyzers
codefang run -a 'history/*' --format plot -o ./report .
open ./report/index.html
What the Output Contains

The generated HTML file includes:

  • Interactive line charts for time-series data (burndown curves, sentiment trends)
  • Bar charts for distribution data (complexity per file, language breakdown)
  • Heatmaps for correlation data (developer coupling matrices)
  • Tooltips with detailed values on hover
  • Zoom and pan controls for large datasets
  • Section headers with analyzer names and descriptions
  • Responsive layout that adapts to browser width

All JavaScript and CSS is inlined -- no external dependencies or CDN requests are made. The file works completely offline.

When to Use

  • Sharing visual reports with stakeholders
  • Presentations and code review meetings
  • Exploratory analysis where interactive drill-down is valuable

Format comparison

The following table summarizes which formats each selection accepts (the same matrix codefang run validates before any analysis starts):

Format Static only History only Mixed static + history
json
yaml
bin
text
compact
ndjson --
timeseries --
plot

Mixed runs

A mixed static+history selection renders json, yaml, bin and ndjson as one unified document. text prints the static sections and then the history text; compact prints every analyzer's compact line, static first. timeseries (with or without --ndjson) is the history time series: static analyzers have no per-commit data, so they are named once on stderr (warning: static analyzers have no per-commit time series; omitted: …).

A format the selection cannot render fails before the walk with Error: format <value> is not supported for <analyzer>. --ndjson is a modifier of --format timeseries only; with any other format it is rejected with Error: invalid --ndjson: ….


Saving a report

Every format except plot is written to stdout by default; -o <file> (--output <file>) writes the same bytes to that file instead (created or truncated). With --format plot, -o names the output directory and is required.

There is no conversion of a saved report into another format: the format is chosen when the analysis runs. Run once per format you need, bounding the history window with --limit / --since to keep each run short:

# JSON for the warehouse
codefang run -a 'history/*' --format json -o report.json .

# YAML of the same window
codefang run -a 'history/*' --format yaml -o report.yaml .

# Interactive pages
codefang run -a 'history/*' --format plot -o ./report .