Skip to content

Repository files navigation

CodeQA

Static code analysis tends to enforce style but miss structural problems: functions growing too complex, naming conventions drifting, copy-paste spreading quietly across files. CodeQA surfaces these patterns using statistical metrics — entropy, compression ratios, vocabulary analysis, cyclomatic complexity proxies — without requiring language-specific parsers.

Works with Python, Ruby, JavaScript, TypeScript, Elixir, C#, Java, C++, Go, Rust, PHP, Swift, Kotlin, and Shell.


Table of Contents


Prerequisites

  • Elixir 1.16+ and Erlang/OTP 26+ (only needed for building from source or running the CLI directly)
  • For GitHub Actions usage: no local setup required

Quick Start

As a GitHub Action (recommended):

- uses: num42/codeqa-action@v1with:
command: health-reportcomment: true

As a CLI (build from source):

mix deps.get && mix escript.build
# Graded health report
./codeqa health-report --format plain ./lib
# Compare current branch against main
./codeqa compare --base-ref origin/main --head-ref HEAD --format markdown ./
# Full raw metrics (JSON)
./codeqa analyze ./lib > metrics.json

GitHub Action

The composite action downloads (or builds) the codeqa binary and runs a command against your repository. It can post results as a sticky PR comment.

Basic usage

name: Code Qualityon: [push, pull_request]jobs:
health-report:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v6
- uses: num42/codeqa-action@v1with:
command: health-reportcomment: truefail-grade: C

PR quality diff

name: Code Quality Diffon: pull_requestjobs:
compare:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v6with:
fetch-depth: 0
- name: Get fork pointid: fork-pointrun: echo "sha=$(git merge-base HEAD ${{ github.event.pull_request.base.sha }})" >> "$GITHUB_OUTPUT"
- uses: num42/codeqa-action@v1with:
command: comparebase-ref: ${{ steps.fork-point.outputs.sha }}comment: true

Inputs

InputRequiredDefaultDescription
commandyesCLI command to run: health-report, compare, analyze, history, correlate, or diagnose
pathno.Directory to analyze
commentnofalsePost results as a sticky PR comment
fail-gradenoFail the action if overall grade is below this (e.g. C)
base-refnoPR base SHABase git ref for compare command
detailnodefaultDetail level for health-report: summary, default, or full
topno5Worst-offender files to show per category
formatnomarkdownOutput format for compare: json or markdown
confignoPath to .codeqa.yml config file
ignore-pathsnoYAML list of glob patterns to exclude
extra-argsnoAdditional CLI flags passed through to codeqa
versionnolatestVersion of codeqa binary to download
buildnoreleaserelease (download prebuilt binary) or source (build from source)

Outputs

OutputDescription
report-filePath to the output file
gradeOverall grade from health-report (e.g. B+)

Configuration

CodeQA reads .codeqa.yml from the project root automatically. CLI flags always take precedence over file values.

ignore_paths

ignore_paths:
- priv/samples/**
- tools/**
- test/**
- deps/**

ignore_paths is a YAML list of glob patterns. Paths matching any pattern are excluded from all analysis.

Custom categories (health-report)

categories:
Naming:
name: Namingmetrics:
- name: vowel_densityweight: 1.5good: "high"thresholds:
a: 0.42b: 0.38c: 0.32d: 0.25

Category-level keys: name (display name), metrics (list of metric overrides), top (worst-offender count override).

Metric-level keys: name (metric key), weight (relative weight within the category), good ("high" or "low" — direction where higher values are better or worse), source (metric path), thresholds (map of letter-grade cutoffs: a, b, c, d).

Grade scale override

grade_scale:
- min: 90grade: "A"
- min: 80grade: "B"
- min: 70grade: "C"
- min: 0grade: "F"

impact

Impact weights used when computing the overall score. The 9 keys below are the built-in defaults; any category not listed falls back to 1. These weights apply to both primary and behavior categories.

impact:
complexity: 5file_structure: 4function_design: 4code_smells: 3naming_conventions: 2error_handling: 2consistency: 2documentation: 1testing: 1# override any category key:# variable_naming: 2

combined_top

Controls how many worst-offender files are shown per behavior category in health-report (default: 2).

combined_top: 3

near_duplicate_blocks

Configures codebase-level near-duplicate block detection (used by analyze).

near_duplicate_blocks:
max_pairs_per_bucket: 50
KeyDescription
max_pairs_per_bucketMaximum duplicate pairs reported per similarity bucket (default: unlimited)

cosine_significance_threshold

Minimum cosine similarity required for a behavior category match to be considered significant. Matches below this threshold are treated as noise and excluded from scoring. Default: 0.15.

cosine_significance_threshold: 0.25

CLI Reference

Build the escript first: mix deps.get && mix escript.build

analyze

Computes raw statistical metrics for every file and outputs JSON.

./codeqa analyze [OPTIONS] <path>
OptionDescription
--workers NParallel worker count
--progressShow per-file progress
--cacheCache computed metrics to disk
--cache-dir PATHDirectory for cached metrics (default: .codeqa_cache)
--timeout MSPer-file timeout in milliseconds (default: 5000)
--show-filesInclude per-file metrics in output
--show-file-paths PATHSComma-separated list of specific file paths to include
--ignore-paths GLOBSComma-separated glob patterns to exclude
--show-ncdInclude NCD similarity matrix
--ncd-top NTop similar pairs per file
--ncd-paths PATHSComma-separated paths to compare for NCD
--output FILEWrite output to file (default: stdout)

Example:

./codeqa analyze --workers 8 --show-files ./src > metrics.json

health-report

Produces a graded quality report grouped into behavior categories with worst-offender file lists.

./codeqa health-report [OPTIONS] <path>
OptionDescription
--format FORMATOutput format: plain or github (default: plain)
--config PATHPath to config file (default: .codeqa.yml)
--detail LEVELReport detail: summary, default, or full (default: default)
--top NWorst-offender files to show per category (default: 5)
--progressShow per-file progress
--ignore-paths GLOBSComma-separated glob patterns to exclude
--output FILEWrite output to file (default: stdout)

Example:

./codeqa health-report --detail full --top 10 --format github ./lib

diagnose

Identifies likely code quality issues by scoring behavior profiles using cosine similarity. Useful for understanding why a codebase scores poorly without running a full health report.

./codeqa diagnose --path <path> [OPTIONS]

--path is required. Note: unlike health-report, the path is passed as a named flag (--path), not a positional argument.

OptionDescription
--path PATH(Required) File or directory to analyze
--mode MODEaggregate (default) or per-file
--top NNumber of top issues to show (default: 15)
--format FORMATOutput format: plain or json (default: plain)
--combined-top NWorst-offender files per behavior in per-file mode (default: 2)

Example:

./codeqa diagnose --path ./lib --mode aggregate --top 10
./codeqa diagnose --path ./lib --mode per-file --format json

compare

Compares code quality metrics between two git refs. Designed for PR workflows.

./codeqa compare [OPTIONS] <path>

--base-ref is required.

OptionDescription
--base-ref REF(Required) Git ref for the base (e.g. origin/main)
--head-ref REFGit ref for the head (default: HEAD)
--format FORMATOutput format: json, markdown, or github (default: json)
--output MODEOutput mode: auto, summary, or changes (default: auto)
--changes-onlyOnly analyze files changed between refs
--all-filesAnalyze all source files at both refs (default)
--workers NParallel worker count
--progressShow per-file progress
--cacheCache computed metrics to disk
--cache-dir PATHDirectory for cached metrics (default: .codeqa_cache)
--timeout MSPer-file timeout in milliseconds (default: 5000)
--show-ncdInclude NCD similarity matrix
--ncd-top NTop similar pairs per file
--ncd-paths PATHSComma-separated paths to compare for NCD
--show-filesInclude per-file metrics in output
--show-file-paths PATHSComma-separated list of specific file paths to include
--ignore-paths GLOBSComma-separated glob patterns to exclude

Example:

./codeqa compare --base-ref origin/main --head-ref HEAD --format markdown ./

history

Tracks codebase metrics across multiple commits, writing per-commit JSON snapshots to disk.

./codeqa history [OPTIONS] <path>

--output-dir is required. Either --commits or --commit-list is required.

OptionDescription
--output-dir PATH(Required) Directory to write JSON snapshots
--commits NNumber of recent commits to analyze
--commit-list SHASComma-separated list of explicit commit SHAs
--workers NParallel worker count
--progressShow per-file progress
--cacheCache computed metrics to disk
--cache-dir PATHDirectory for cached metrics (default: .codeqa_cache)
--timeout MSPer-file timeout in milliseconds (default: 5000)
--show-ncdInclude NCD similarity matrix
--ncd-top NTop similar pairs per file
--ncd-paths PATHSComma-separated paths to compare for NCD
--show-filesInclude per-file metrics in output
--show-file-paths PATHSComma-separated list of specific file paths to include
--ignore-paths GLOBSComma-separated glob patterns to exclude

correlate

Finds metric correlations across history snapshots produced by history. Run history first.

./codeqa correlate [OPTIONS] <history_dir>
OptionDescription
--top NNumber of top correlations to show (default: 20)
--hide-exactHide perfect 1.0 and -1.0 correlations
--all-groupsInclude correlations between metrics in the same group
--min FLOATMinimum correlation threshold
--max FLOATMaximum correlation threshold
--combined-onlyShow only combined-metric correlations
--max-steps NMaximum number of correlation pairs to evaluate

Metrics Reference

All metrics are computed per file and aggregated at the codebase level.

Raw Metrics

MetricDescription
EntropyShannon entropy at character and token level — measures information density
HalsteadSoftware-science metrics: operators, operands, vocabulary, volume, difficulty, effort, estimated bugs
ReadabilityAdapted Flesch and Fog indices based on identifier and token complexity
Branching densityCyclomatic-complexity proxy — ratio of branching constructs to total tokens
Compression ratiozlib compression ratio — higher ratios indicate more repetitive or boilerplate-heavy code
Vocabulary (TTR)Type-to-token ratio — ratio of unique tokens to total tokens
Lexical concentrationYule's K and Simpson's D — length-invariant vocabulary concentration. High yule_k = a few tokens dominate; simpson_d = probability two random tokens are identical
ZipfHow closely token frequency follows Zipf's law
N-gram analysisBigram/trigram total count, unique count, repetition rate, and hapax fraction — high repetition may indicate copy-paste patterns
Heaps lawFits power-law curve V = k·N^β to vocabulary growth; reports beta, k, and R-squared — beta near 0.5 is typical
Casing entropyShannon entropy of identifier casing styles (camelCase, snake_case, PascalCase, MACRO_CASE, kebab-case) — high entropy = mixed conventions, low = consistent
Indentation varianceStandard deviation of indentation depth across lines
Identifier length varianceStandard deviation of identifier lengths
Symbol densityRatio of punctuation/operator symbols to total tokens
Vowel densityRatio of vowels in identifiers — low values correlate with terse or abbreviated naming
Magic number densityRatio of numeric literals that appear to be unnamed constants
Function metricsFunction count, average and maximum function line count, average and maximum parameter count
Cross-file similaritycross_file_density: overall codebase redundancy via combined compression ratio. ncd_pairs (opt-in via --show-ncd): Normalized Compression Distance between similar file pairs using winnowing fingerprints
Near-duplicate blocksCodebase-level detection of near- and exact-duplicate code blocks using token-based similarity. Reports duplicate pairs grouped by bucket, with source locations. Configurable via near_duplicate_blocks: in .codeqa.yml.
Block impact & refactoring potentialsPer-file node tree enriched with leave-one-out impact scores and refactoring potentials. Added to each file entry as "nodes" in analyze JSON output. Surfaces the highest-impact blocks to refactor.

Health Report Categories

The health-report command evaluates your codebase using two complementary scoring models:

  • 6 primary categories — graded using configurable thresholds against raw metrics (Readability, Complexity, Structure, Duplication, Naming, Magic Numbers)
  • 12 behavior categories — graded using cosine similarity against behavior profiles (see Behavior Categories)

The overall score is a weighted average of all 18 categories. Primary category weights are set via weight: in .codeqa.yml; behavior category weights are configured via impact:.

CategoryWhat it measures
ReadabilityFlesch/Fog indices, avg tokens per line, avg line length
ComplexityHalstead difficulty, effort, volume, and estimated bugs
StructureBranching density, indentation depth, function length, parameter counts
DuplicationCompression redundancy, bigram/trigram repetition rates
NamingCasing entropy, identifier length variance, avg sub-words per identifier
Magic NumbersMagic number density

Cosine scoring breakpoints (used for behavior categories):

Cosine similarityScoreApprox. grade
≥ 0.590–100A
≥ 0.270–90B–A-
≥ 0.050–70C–B-
≥ −0.330–50D–C-
≥ −1.00–30F–D-

Category definitions and thresholds are configurable via .codeqa.yml.

Behavior Categories

In addition to the 6 primary categories, health-report grades 12 behavior categories using cosine similarity against behavior profiles. These contribute to the overall score alongside the primary categories.

CategoryChecks
Code SmellsDebug prints, dead code after return, FIXME comments, nested ternaries, inconsistent quote style
Naming ConventionsClass name is a noun, file name matches primary export, function naming patterns, test name starts with verb
Variable NamingClarity, length, and consistency of variable names
Function DesignFunction length and complexity
DocumentationComment and docstring presence and quality
File StructureFile length and organization
Scope & AssignmentVariable scope and assignment patterns
Type & ValueType annotation and value literal usage
ConsistencyCross-file style consistency
TestingTest file coverage and naming patterns
DependenciesImport and dependency patterns
Error HandlingError handling completeness

These categories are graded in the health-report output using cosine similarity scoring and contribute to the overall score.

Output Formats

FormatCommandsDescription
jsonanalyze, compare, diagnoseFull metrics structure, suitable for tooling
markdowncompareGitHub-flavored markdown tables
plainhealth-report, diagnoseHuman-readable terminal output
githubhealth-report, compareMarkdown optimized for GitHub PR comments

Grading

health-report assigns grades based on weighted-average scores (0–100) per category and for the overall codebase.

Grade scale (15 grades):

GradeScore range
A≥ 93
A-≥ 85
B+≥ 78
B≥ 72
B-≥ 67
C+≥ 63
C≥ 55
C-≥ 48
D+≥ 42
D≥ 35
D-≥ 25
E+≥ 18
E≥ 12
E-≥ 6
F< 6

The overall score is a weighted average across all categories. Primary category weights use the weight: field inside each category definition in .codeqa.yml. Behavior category weights are configured via impact: (defaults range from 1–5; categories not listed fall back to 1). See Configuration for examples.

The fail-grade action input causes a non-zero exit when the overall grade falls below the specified threshold.

Contributing & Issues

Found a bug? Open a bug report GitHub Action not behaving? File an Action bug report Have an idea? Request a feature Metric scoring wrong? File a metric accuracy report New language? Request language support New combined-metrics sample? Submit a sample Docs unclear? Report a documentation issue Have a question? Ask in Discussions

Want to contribute code? Fork the repo, make your changes, and open a pull request. See Quick Start for build instructions.

🤖 Automated tool integration

See AUTOMATION.md for machine-readable issue template links and label schema.

About

Language agnostic suite of tools to measure and ensure code-quality of entire codebases

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages