npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

git-diff-stat-extended

v0.9.0

Published

Extended git diff stats with implementation/tests/comments breakdown and strict reconciliation.

Readme

git-diff-stat-extended

Extended git diff stats for local workflows, exposed as the gdsx CLI.

gdsx preserves authoritative git totals and adds a categorized breakdown:

  • implementation
  • tests
  • comments
  • documentation
  • configuration

It enforces strict reconciliation:

  • implementation.insertions + tests.insertions + comments.insertions + documentation.insertions + configuration.insertions = total.insertions
  • implementation.deletions + tests.deletions + comments.deletions + documentation.deletions + configuration.deletions = total.deletions

If reconciliation fails, gdsx prints diagnostics and exits non-zero.

Table of Contents

Motivation

git diff --shortstat gives trustworthy totals, but not the context needed to quickly understand where change effort went. gdsx keeps git as the source of truth while adding a practical implementation/test/comment breakdown that still reconciles exactly to global insertions and deletions.

Features

  • Uses git CLI as source of truth (--raw -z, --shortstat, and patch hunks)
  • Handles add/modify/delete/rename/copy
  • Safe path handling via NUL-delimited parsing and literal pathspecs
  • Comment detection for JS/TS (via @babel/parser) and 30+ other languages (regex-based)
  • Repeatable include/exclude glob filters
  • Text table output with net column and git-style color defaults
  • JSON mode for machine-readable integration

Category classification

Each changed line is assigned to exactly one category. Classification is determined by file path, evaluated in priority order:

| Priority | Category | Matches | | -------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | tests | Files inside test/, tests/, or __tests__/ directories, or filenames containing .test.* or .spec.* | | 2 | documentation | .md, .txt, .rst, .adoc extensions, or bare filenames LICENSE, LICENCE, CHANGELOG, CHANGES, AUTHORS, CONTRIBUTORS, README | | 3 | configuration | .json, .jsonc, .yaml, .yml, .toml, .ini, .env, .properties extensions; any dotfile (basename starting with .); or filenames matching *.config.* or *.rc.* | | 4 | comments | Lines identified as comments in supported languages (see below) | | 5 | implementation | Everything else (default) |

Earlier rules take precedence. A .test.js file is always tests, never comments or implementation. Comment detection only applies to files that are not already matched by a higher-priority rule.

Comment detection languages

| Parser | Extensions | Comment syntax | | ------- | ---------------------------------------------------------------------------------------------- | -------------------------------- | | Babel | .js, .jsx, .ts, .tsx, .mjs, .cjs, .mts, .cts | Full AST-based parsing | | Generic | .c, .cpp, .h, .hpp, .cs, .go, .java, .rs, .swift, .kt, .scala, .groovy | // line, /* */ block | | Generic | .py, .sh, .bash, .rb, .pl, .r | # line | | Generic | .html, .htm, .xml, .svg, .vue | <!-- --> block | | Generic | .css, .scss, .less | /* */ block | | Generic | .sql, .lua, .hs | -- line | | Generic | .php | // and # line, /* */ block |

Installation

npm install -g git-diff-stat-extended

For development installation, see docs/development.md.

Usage

gdsx [options] [<git-diff-args>...]

gdsx is a thin wrapper around git diff. Any arguments not consumed by gdsx are forwarded directly to git diff, so commits, ranges, and git-specific flags work exactly as you would expect.

Default comparison

Running bare gdsx with no arguments is equivalent to git diff HEAD, which shows all uncommitted changes (staged and unstaged) compared to the last commit.

Options

| Flag | Type | Default | Description | | ----------------------- | ------- | ------- | --------------------------------------------------------------------------- | | --include <glob> | string | | Include glob pattern (repeatable). For renames/copies, matches the new path | | --exclude <glob> | string | | Exclude glob pattern (repeatable). For renames/copies, matches the new path | | --json | boolean | false | Emit structured JSON output | | --show-reconciliation | boolean | false | Show the reconciliation line when it passes (always shown on fail) | | --group-by-extension | boolean | false | Group the category breakdown by file extension |

Examples

# All uncommitted changes vs last commit (default)
gdsx

# Last commit
gdsx HEAD~1..HEAD

# Compare branch tip against main
gdsx main..HEAD

# Symmetric range expression
gdsx main...HEAD

# Include only src and tests
gdsx --include 'src/**' --include 'tests/**' main..HEAD

# Exclude generated files
gdsx --exclude '**/*.snap' --exclude 'dist/**'

# JSON output
gdsx --json main..HEAD

Output

Default text mode

Prints a category table with a header showing files changed and the comparison range:

┌──────────────────────────────────────────────────────┐
│ 38 files changed  ·  c7729b0..HEAD                   │
├─────────────────┬────────────┬───────────┬───────────┤
│ Category        │ Insertions │ Deletions │       Net │
├─────────────────┼────────────┼───────────┼───────────┤
│ implementation  │      +1940 │      -771 │     +1169 │
├─────────────────┼────────────┼───────────┼───────────┤
│ tests           │       +959 │      -201 │      +758 │
├─────────────────┼────────────┼───────────┼───────────┤
│ comments        │       +406 │        -0 │      +406 │
├─────────────────┼────────────┼───────────┼───────────┤
│ documentation   │         +0 │        -0 │         0 │
├─────────────────┼────────────┼───────────┼───────────┤
│ configuration   │         +0 │        -0 │         0 │
├─────────────────┼────────────┼───────────┼───────────┤
│ total           │      +3305 │      -972 │     +2333 │
└─────────────────┴────────────┴───────────┴───────────┘

When reconciliation fails, a FAIL line and diagnostics block are printed and the process exits non-zero. Use --show-reconciliation to also display the reconciliation line on pass.

Grouped by extension (--group-by-extension)

Breaks down categories within each file extension group, sorted alphabetically:

┌───────────────────────────────────────────────────────┐
│ 38 files changed  ·  c7729b0..HEAD                    │
├───────────────────┬────────────┬───────────┬──────────┤
│ Category          │ Insertions │ Deletions │      Net │
├───────────────────┴────────────┴───────────┴──────────┤
│ .js (13 files)                                        │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │       +880 │      -525 │     +355 │
│   tests           │       +959 │      -201 │     +758 │
│   comments        │       +400 │        -0 │     +400 │
│   documentation   │         +0 │        -0 │        0 │
│   configuration   │         +0 │        -0 │        0 │
├───────────────────┴────────────┴───────────┴──────────┤
│ .json (7 files)                                       │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │         +0 │        -0 │        0 │
│   tests           │         +0 │        -0 │        0 │
│   comments        │         +0 │        -0 │        0 │
│   documentation   │         +0 │        -0 │        0 │
│   configuration   │       +125 │        -9 │     +116 │
├───────────────────┴────────────┴───────────┴──────────┤
│ .jsonc (2 files)                                      │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │         +0 │        -0 │        0 │
│   tests           │         +0 │        -0 │        0 │
│   comments        │         +0 │        -0 │        0 │
│   documentation   │         +0 │        -0 │        0 │
│   configuration   │         +8 │        -0 │       +8 │
├───────────────────┴────────────┴───────────┴──────────┤
│ .md (8 files)                                         │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │         +0 │        -0 │        0 │
│   tests           │         +0 │        -0 │        0 │
│   comments        │         +0 │        -0 │        0 │
│   documentation   │       +877 │       -10 │     +867 │
│   configuration   │         +0 │        -0 │        0 │
├───────────────────┴────────────┴───────────┴──────────┤
│ .mjs (1 file)                                         │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │        +25 │        -0 │      +25 │
│   tests           │         +0 │        -0 │        0 │
│   comments        │         +6 │        -0 │       +6 │
│   documentation   │         +0 │        -0 │        0 │
│   configuration   │         +0 │        -0 │        0 │
├───────────────────┴────────────┴───────────┴──────────┤
│ (no extension) (7 files)                              │
├───────────────────┬────────────┬───────────┬──────────┤
│   implementation  │        +25 │      -227 │     -202 │
│   tests           │         +0 │        -0 │        0 │
│   comments        │         +0 │        -0 │        0 │
│   documentation   │         +0 │        -0 │        0 │
│   configuration   │         +0 │        -0 │        0 │
├───────────────────┼────────────┼───────────┼──────────┤
│ total             │      +3305 │      -972 │    +2333 │
└───────────────────┴────────────┴───────────┴──────────┘

JSON mode (--json)

JSON output includes:

  • shortstatLine
  • total
  • categories
  • reconciliation
  • range
  • filters
  • selectedFiles
  • fileDetails — per-file category breakdowns

Reconciliation guarantees

gdsx compares computed category sums to authoritative git totals.

When mismatch occurs:

  • reconciliation status is FAIL
  • diagnostics are printed
  • process exit code is non-zero

This makes the tool safe for scripting and CI checks.

Contributing

See docs/development.md for setup, testing, and release instructions.

Known limitations

  • For unsupported file extensions, all non-test/doc/config lines are categorized as implementation
  • The generic (non-JS/TS) comment parser uses regex-based scanning with basic string literal awareness; edge cases in complex string/template interpolation may cause misclassification
  • Python docstrings ("""..."""/'''...''') are string literals, not language-level comments, and are classified as implementation
  • Nested block comments (e.g. Haskell {- {- -} -}) are not supported
  • For files with syntax parse failures, comment classification for that side falls back to implementation

License

MIT