Skip to content

Add --summary flag for aggregate error/warning count output #891

Description

@fuleinist

Summary

xo's output flags (--reporter, --quiet, --max-warnings, --fix) are great for humans reading lint output, but there's no built-in way to emit a single aggregate summary line. CI status checks, status badges, and pre-commit hooks have to wrap xo (or shell-count the output) to get a pass/fail count.

Problem

Today, after xo finishes, the only ways to know how many problems were found are:

  1. Parse the multi-line pretty reporter output (or json, compact, codeframe, etc.) with wc -l, grep, or a JSON parser — fragile because each reporter has a different shape
  2. Run xo twice — once for output, once with --quiet + --max-warnings 0 to get the exit code — wasteful
  3. Wrap xo in a shell script that counts occurrences of the warning/error indicator — stringly-typed and breaks when xo updates its format

The data is already there: cli.ts lines 171–174 declares errorCount, warningCount, fixableErrorCount, fixableWarningCount on the report object, and lines 187–198 aggregate them across results. None of those counts are exposed in a scriptable form.

Proposed Solution

Add a --summary (or --stats) flag that prints one aggregate line to stderr (alongside the existing reporter output), e.g.:

$ xo --summary src/
... [existing pretty reporter output] ...
✖ 12 problems (4 errors, 8 warnings) — 5 fixable

Behavior:

  • Default off — zero behavior change
  • Stderr (so it composes with xo --reporter json | jq pipelines that capture stdout)
  • --no-color aware (respect the existing color flag)
  • Exit codes unchanged: 0 clean, 1 problems found, 2 invalid flag, 3 fatal
  • Composes with --quiet (summary still printed), --max-warnings (summary reflects the actual count, not the threshold), --fix (summary counts the remaining issues after fixes)

Implementation Sketch

// in cli.ts meow flags:
summary: {
  type: 'boolean',
  default: false,
},

// in the log() function, after the existing reporter output (around line 215):
if (cliOptions.summary) {
  const parts = [];
  if (report.errorCount > 0) parts.push(`${report.errorCount} errors`);
  if (report.warningCount > 0) parts.push(`${report.warningCount} warnings`);
  if (report.fixableErrorCount + report.fixableWarningCount > 0) {
    parts.push(`${report.fixableErrorCount + report.fixableWarningCount} fixable`);
  }
  if (parts.length === 0) {
    console.error('✔ 0 problems');
  } else {
    console.error(`✖ ${report.errorCount + report.warningCount} problems (${parts.join(', ')})`);
  }
}

~12 lines + a --summary mention in the meow help block. All counts already exist on report — no new ESLint API calls needed.

Alternatives Considered

Alternative Why I rejected it
New --format summary reporter Overloads the reporter system for a non-report concern; --reporter json already exists for machine consumers
Extend --reporter json with a --summary field Mixes metadata with the result list; consumers parsing JSON would need to ignore it
Document a shell pipeline (xo --quiet --max-warnings=0 && echo "clean" or xo 2>&1 | wc -l) Fragile — --quiet filters warnings from output but exit code still reflects them; wc -l breaks if xo reformats
Pre-existing open PR/issue with this proposal None found (open issues #733, #889, #890 cover unrelated topics)

Use Cases

  • CI status checks (GitHub Actions, GitLab CI, Buildkite): xo --summary --reporter compact src/ > /dev/null and grep stderr for "0 problems" / "✖ N problems"
  • Pre-commit hooks: parse the summary line for a single pass/fail decision without grepping pretty output
  • Status badges / dashboards: xo --summary --quiet 2>&1 | tail -1 for a one-line status string
  • Editor LSP integrations: surface the aggregate count in a status line without re-implementing the per-file aggregation

Related

Mirrors the same gap pattern recently identified in:

Both tools are linters that emit a list of problems but offer no aggregate flag — the data is already aggregated in memory; exposing it is the missing control surface.


Filing from fuleinist, an automated GitHub-issue helper. Substance review welcome.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions