
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
git-contributor-stats
Advanced tools
CLI to compute contributor and repository statistics from a Git repository (commits, lines added/deleted, frequency, heatmap, bus-factor), with filters and multiple output formats.
A powerful, fast Node.js CLI and library to analyze Git repository contributions with detailed statistics, charts, and multiple output formats.
📦 Modular & Tree-Shakeable
This package uses subpath exports for optimal bundle sizes. Import only what you need:
git-contributor-stats/stats- Core statisticsgit-contributor-stats/charts- Chart generationgit-contributor-stats/reports- Report generationgit-contributor-stats/output- Console outputgit-contributor-stats/workflow- GitHub Actions workflowSee Technical Docs for architecture details and Quick Start for usage examples.
Analyze your Git repository to gain insights into contributor activity, code ownership, commit patterns, and project health. Get comprehensive statistics including commits, lines added/deleted, file changes, temporal patterns, bus factor analysis, and beautiful visualizations.
Requirements: Node.js 18+ (ESM-only)
90.days, 2.weeks, etc.)npm install -g git-contributor-stats
npm install git-contributor-stats
💡 New to this tool? See Quick Start Guide for detailed use cases and examples
# Analyze current repository
git-contributor-stats
# Top 10 contributors
git-contributor-stats --top 10
# Last 90 days with JSON output
git-contributor-stats --since 90.days --json
# Generate all reports and charts (most popular!)
git-contributor-stats --out-dir reports --md --html --charts
# Specific folder analysis
git-contributor-stats src/ --top 20
// Import only what you need using subpath exports
import { getContributorStats } from 'git-contributor-stats/stats';
const stats = await getContributorStats({
repo: '.',
since: '90.days',
countLines: false
});
console.log(`Total commits: ${stats.totalCommits}`);
console.log(`Top contributor: ${stats.topContributors[0].name}`);
git-contributor-stats [options] [paths...]
Arguments:
[paths...] - Optional pathspec(s) to limit analysis to certain files/directories# Show help
git-contributor-stats --help
# Show version
git-contributor-stats --version
# Analyze current repository (default: table output)
git-contributor-stats
# Analyze specific repository
git-contributor-stats --repo /path/to/repo
# Analyze specific paths only
git-contributor-stats src/ lib/
| Option | Description | Example |
|---|---|---|
-r, --repo <path> | Path to Git repository | --repo /path/to/repo |
-b, --branch <name> | Branch or commit range | --branch main or --branch main..feature |
| Option | Description | Example |
|---|---|---|
--since <when> | Only commits after date | --since 2024-01-01 or --since 90.days |
--until <when> | Only commits before date | --until 2024-12-31 or --until 1.week |
Supported relative time formats:
30.days, 1.day2.weeks, 1.week3.months, 1.month1.year, 2.yearsExample:
# Last quarter
git-contributor-stats --since 90.days
# Specific date range
git-contributor-stats --since 2024-01-01 --until 2024-06-30
# Last 2 weeks on main branch
git-contributor-stats -b main --since 2.weeks
| Option | Description | Example |
|---|---|---|
-a, --author <pattern> | Filter by author (string/regex) | --author "John" |
--include-merges | Include merge commits | --include-merges |
Example:
# Contributions from specific author
git-contributor-stats --author "jane@example.com"
# Include merge commits (excluded by default)
git-contributor-stats --include-merges
| Option | Description | Default | Values |
|---|---|---|---|
-g, --group-by <field> | Group contributors by | email | email, name |
-s, --sort-by <metric> | Sort contributors by | changes | changes, commits, additions, deletions |
-t, --top <n> | Limit to top N contributors | All | Any number |
Example:
# Group by name instead of email
git-contributor-stats --group-by name
# Sort by commit count, show top 15
git-contributor-stats --sort-by commits --top 15
# Sort by net lines added
git-contributor-stats --sort-by additions --top 10
| Option | Description | Output |
|---|---|---|
-f, --format <kind> | Format for stdout | table, json, csv |
--json | Comprehensive JSON analysis | Full analysis object |
Example:
# Table output (default)
git-contributor-stats
# JSON to stdout
git-contributor-stats --json
# CSV to stdout
git-contributor-stats --format csv
# Compact table with top 10
git-contributor-stats --format table --top 10
| Option | Description |
|---|---|
--csv <path> | Write CSV report to file |
--md <path> | Write Markdown report to file |
--html <path> | Write HTML dashboard to file |
--out-dir <path> | Directory for all outputs (uses default names) |
Example:
# Individual file outputs
git-contributor-stats --csv stats.csv --md report.md --html dashboard.html
# Use output directory (creates contributors.csv, report.md, report.html)
git-contributor-stats --out-dir reports
# Combine with specific names
git-contributor-stats --out-dir reports --md reports/custom-report.md
| Option | Description | Default |
|---|---|---|
--charts | Generate charts | Disabled |
--charts-dir <path> | Directory for charts | ./charts or --out-dir |
--chart-format <fmt> | Chart format | svg |
Chart formats:
svg - Scalable Vector Graphics (recommended)png - Portable Network Graphicsboth - Generate both SVG and PNGGenerated charts:
top-commits.svg/png - Bar chart of top contributors by commit counttop-net.svg/png - Bar chart of top contributors by net linesheatmap.svg/png - Activity heatmap (weekday × hour)Example:
# Generate SVG charts in default location
git-contributor-stats --charts
# Generate PNG charts
git-contributor-stats --charts --chart-format png
# Generate both formats in custom directory
git-contributor-stats --charts --charts-dir ./output/charts --chart-format both
# Charts with reports
git-contributor-stats --out-dir reports --md --html --charts
Control which metrics appear in the "Top Stats" section of reports and stdout:
| Option | Description | Default |
|---|---|---|
--top-stats <list> | Comma-separated metrics to show | All metrics |
--no-top-stats | Omit Top Stats section entirely | Enabled |
Available metrics:
commits - Most commitsadditions - Most lines addeddeletions - Most lines deletednet - Best net contribution (additions - deletions)changes - Most total changes (additions + deletions)Example:
# Show only commits and net in Top Stats
git-contributor-stats --top-stats commits,net --md report.md
# Omit Top Stats entirely (faster, cleaner output)
git-contributor-stats --no-top-stats --html dashboard.html
# Default: all metrics shown
git-contributor-stats --md report.md
| Option | Description |
|---|---|
--alias-file <path> | Path to alias mapping JSON |
--similarity <0..1> | Name merge similarity threshold (default: 0.85) |
Example:
# Use custom alias file
git-contributor-stats --alias-file config/aliases.json
# Adjust similarity threshold (higher = stricter matching)
git-contributor-stats --similarity 0.9
# Combine with reports
git-contributor-stats --alias-file aliases.json --out-dir reports --md --html
See Identity Management section for alias file format.
| Option | Description | Impact |
|---|---|---|
--no-count-lines | Skip total LOC counting | Faster analysis |
Example:
# Skip LOC counting for large repos (significant speed improvement)
git-contributor-stats --no-count-lines --json
# Fast report generation
git-contributor-stats --out-dir reports --md --html --no-count-lines
| Option | Description |
|---|---|
--generate-workflow | Create GitHub Actions workflow file |
-v, --verbose | Enable verbose logging (stderr) |
Example:
# Generate GitHub Actions workflow
git-contributor-stats --generate-workflow
# Debug mode
git-contributor-stats --verbose --json
# See what git commands are being run
git-contributor-stats -v --since 30.days
Use git-contributor-stats as a library in your Node.js/TypeScript projects.
import { getContributorStats } from 'git-contributor-stats/stats';
// Analyze current repository
const stats = await getContributorStats({
repo: '.',
since: '90.days',
countLines: false
});
console.log(`Total commits: ${stats.totalCommits}`);
console.log(`Contributors: ${Object.keys(stats.contributors).length}`);
console.log(`Top contributor: ${stats.topContributors[0].name}`);
getContributorStats(options)Returns a Promise that resolves to a comprehensive analysis object.
Options:
interface ContributorStatsOptions {
// Repository options
repo?: string; // Path to repository (default: '.')
branch?: string; // Branch or range (e.g., 'main..feature')
paths?: string | string[]; // Pathspec(s) to limit analysis
// Filtering options
since?: string; // Date or relative time (e.g., '90.days')
until?: string; // Date or relative time
author?: string; // Author pattern (string/regex)
includeMerges?: boolean; // Include merge commits (default: false)
// Grouping & sorting
groupBy?: 'email' | 'name'; // Group by field (default: 'email')
labelBy?: 'email' | 'name'; // Display label (default: 'name')
sortBy?: 'changes' | 'commits' | 'additions' | 'deletions';
top?: number; // Limit to top N contributors
// Identity management
similarity?: number; // Name merge threshold (default: 0.85)
aliasFile?: string; // Path to alias JSON file
aliasConfig?: AliasConfig; // Inline alias configuration
// Performance
countLines?: boolean; // Count total LOC (default: true)
verbose?: boolean; // Enable verbose logging (default: false)
}
Return Value:
interface ContributorStatsResult {
meta: {
generatedAt: string; // ISO timestamp
repo: string; // Repository path
branch: string | null; // Branch name
since: string | null; // Since date/time
until: string | null; // Until date/time
};
totalCommits: number; // Total commit count
totalLines: number; // Total lines of code
contributors: Record<string, ContributorsMapEntry>;
topContributors: TopContributor[];
topStats: {
byCommits: TopContributor | null;
byAdditions: TopContributor | null;
byDeletions: TopContributor | null;
byNet: TopContributor | null;
byChanges: TopContributor | null;
};
commitFrequency: {
monthly: Record<string, number>;
weekly: Record<string, number>;
};
heatmap: number[][]; // 7x24 grid (weekday x hour)
busFactor: {
filesSingleOwner: Array<{
file: string;
owner: string;
changes: number;
}>;
};
basic: {
contributors: TopContributor[];
meta: ContributorsMeta;
groupBy: 'email' | 'name';
};
}
import { getContributorStats } from 'git-contributor-stats/stats';
const stats = await getContributorStats({
repo: '/path/to/repo',
since: '2024-01-01',
until: '2024-06-30',
branch: 'main'
});
console.log('Q1-Q2 2024 Stats:');
console.log(`- Commits: ${stats.totalCommits}`);
console.log(`- Active contributors: ${stats.topContributors.length}`);
import { getContributorStats } from 'git-contributor-stats/stats';
const stats = await getContributorStats({
repo: '.',
author: 'jane@example.com',
paths: ['src/', 'lib/'],
since: '30.days'
});
console.log(`Jane's contributions in src/ and lib/ (last 30 days):`);
console.log(`- Commits: ${stats.topContributors[0]?.commits || 0}`);
console.log(`- Files changed: ${Object.keys(stats.topContributors[0]?.files || {}).length}`);
import { getContributorStats } from 'git-contributor-stats/stats';
import { generateReports } from 'git-contributor-stats/reports';
const stats = await getContributorStats({
repo: '.',
since: '90.days',
countLines: false
});
// Generate reports
await generateReports(stats, {
outDir: 'reports',
md: 'reports/quarterly-report.md',
html: 'reports/quarterly-report.html',
csv: 'reports/contributors.csv'
});
console.log('Reports generated in ./reports/');
import { getContributorStats } from 'git-contributor-stats/stats';
import { generateCharts } from 'git-contributor-stats/charts';
const stats = await getContributorStats({
repo: '.',
since: '90.days'
});
// Generate SVG charts
await generateCharts(stats, {
charts: true,
chartsDir: 'output/charts',
chartFormat: 'svg'
});
// Or PNG charts
await generateCharts(stats, {
charts: true,
chartsDir: 'output/charts',
chartFormat: 'png'
});
// Or both
await generateCharts(stats, {
charts: true,
chartsDir: 'output/charts',
chartFormat: 'both'
});
import { getContributorStats } from 'git-contributor-stats/stats';
const stats = await getContributorStats({
repo: '.',
aliasConfig: {
groups: [
['jane@example.com', 'jane.doe@example.com', 'Jane Doe'],
['john@example.com', 'john.smith@example.com']
],
canonical: {
'jane@example.com': {
name: 'Jane Doe',
email: 'jane@example.com'
},
'john@example.com': {
name: 'John Smith',
email: 'john@example.com'
}
}
},
similarity: 0.9
});
import { getContributorStats } from 'git-contributor-stats/stats';
const stats = await getContributorStats({
repo: '.',
since: '1.year',
groupBy: 'name',
sortBy: 'commits'
});
// Custom analysis
const topContributor = stats.topContributors[0];
const busFactorFiles = stats.busFactor.filesSingleOwner.length;
const avgCommitsPerMonth = stats.totalCommits / 12;
console.log('Annual Report:');
console.log(`Top contributor: ${topContributor.name}`);
console.log(`- Commits: ${topContributor.commits}`);
console.log(`- Net lines: ${topContributor.net}`);
console.log(`\nRisk Analysis:`);
console.log(`- Single-owner files: ${busFactorFiles}`);
console.log(`- Avg commits/month: ${avgCommitsPerMonth.toFixed(1)}`);
// Access monthly breakdown
const monthlyActivity = stats.commitFrequency.monthly;
console.log('\nMonthly Activity:');
Object.entries(monthlyActivity)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([month, commits]) => {
console.log(`${month}: ${commits} commits`);
});
Full TypeScript definitions are included:
import type {
ContributorStatsOptions,
ContributorStatsResult,
TopContributor,
TopStatsSummary,
BusFactorInfo
} from 'git-contributor-stats/stats';
import { getContributorStats } from 'git-contributor-stats/stats';
const options: ContributorStatsOptions = {
repo: '.',
since: '90.days',
countLines: false
};
const stats: ContributorStatsResult = await getContributorStats(options);
// Type-safe access
const topContributor: TopContributor = stats.topContributors[0];
const busFactor: BusFactorInfo = stats.busFactor;
// From 'git-contributor-stats/stats'
export async function getContributorStats(
options?: ContributorStatsOptions
): Promise<ContributorStatsResult>
// From 'git-contributor-stats/reports'
export async function generateReports(
stats: ContributorStatsResult,
options?: ReportOptions
): Promise<void>
// From 'git-contributor-stats/charts'
export async function generateCharts(
stats: ContributorStatsResult,
options?: ChartOptions,
outDir?: string
): Promise<void>
// From 'git-contributor-stats/output'
export function handleStdoutOutput(
stats: ContributorStatsResult,
options?: OutputOptions
): void
// From 'git-contributor-stats/workflow'
export async function generateWorkflow(repo: string): Promise<void>
Consolidate multiple emails and names for the same person using alias mapping.
The tool automatically looks for .git-contributor-stats-aliases.json in the repository root.
# Use default file (if exists)
git-contributor-stats
# Use custom file
git-contributor-stats --alias-file config/aliases.json
Map aliases to canonical identities:
{
"jane@example.com": "jane.doe@example.com",
"Jane Doe": "jane.doe@example.com",
"john@example.com": "john.smith@example.com",
"J. Smith": "john.smith@example.com"
}
More control with groups and canonical details:
{
"map": {
"jane@old-company.com": "jane.doe@example.com",
"jdoe@example.com": "jane.doe@example.com"
},
"groups": [
["john@example.com", "jsmith@example.com", "john.smith@example.com"],
["alice@example.com", "alice.dev@example.com"]
],
"canonical": {
"jane.doe@example.com": {
"name": "Jane Doe",
"email": "jane.doe@example.com"
},
"john.smith@example.com": {
"name": "John Smith",
"email": "john.smith@example.com"
}
}
}
Shorthand for groups:
[
["jane@example.com", "jane.doe@example.com", "Jane Doe"],
["john@example.com", "john.smith@example.com", "John Smith"],
["alice@old.com", "alice@new.com", "alice@example.com"]
]
Use regex patterns for flexible matching:
{
"map": {
"/^jane\\.doe@.+$/i": "jane.doe@example.com",
"/^(John Smith|J\\.? Smith)$/": "john.smith@example.com"
}
}
Pattern format: Strings starting and ending with / are treated as regex patterns.
Control automatic name merging:
# Default threshold (0.85)
git-contributor-stats
# Stricter matching (higher threshold)
git-contributor-stats --similarity 0.95
# More permissive (lower threshold)
git-contributor-stats --similarity 0.75
Range: 0.0 (merge everything) to 1.0 (exact match only)
Recommended: 0.80 - 0.90
Currently, the tool uses command-line options and alias files. Environment variables are not used.
| Setting | Default | Description |
|---|---|---|
| Repository | Current directory (.) | Can override with --repo |
| Output format | table | Can change with --format |
| Group by | email | Can change with --group-by |
| Sort by | changes | Can change with --sort-by |
| Similarity | 0.85 | Can change with --similarity |
| Count lines | true | Disable with --no-count-lines |
| Include merges | false | Enable with --include-merges |
| Top stats | true | Disable with --no-top-stats |
# Generate comprehensive quarterly report with all outputs
git-contributor-stats \
--since 90.days \
--out-dir reports/q4-2024 \
--md reports/q4-2024/report.md \
--html reports/q4-2024/dashboard.html \
--csv reports/q4-2024/contributors.csv \
--charts \
--chart-format both \
--no-count-lines
# Analyze backend team contributions in src/backend/
git-contributor-stats \
src/backend/ \
--since 1.year \
--alias-file config/team-aliases.json \
--out-dir reports/backend-team \
--md --html \
--charts \
--top-stats commits,net
# Compare two releases
git-contributor-stats \
--branch v1.0.0..v2.0.0 \
--json > v1-to-v2-stats.json
# Analyze specific release period
git-contributor-stats \
--since 2024-01-01 \
--until 2024-03-31 \
--out-dir reports/v2.0 \
--md --html --charts
# Fast analysis for large repos
git-contributor-stats \
--no-count-lines \
--since 6.months \
--top 20 \
--format table
# Only show commits and net contribution
git-contributor-stats \
--top-stats commits,net \
--out-dir reports \
--md reports/simple-report.md
# Generate GitHub Actions workflow
git-contributor-stats --generate-workflow
# Run in CI (example)
git-contributor-stats \
--since 7.days \
--out-dir artifacts \
--md artifacts/weekly-report.md \
--charts \
--no-count-lines
import { getContributorStats } from 'git-contributor-stats/stats';
async function checkRepoHealth() {
const stats = await getContributorStats({
repo: '.',
since: '90.days'
});
const activeDevelopers = stats.topContributors.length;
const singleOwnerFiles = stats.busFactor.filesSingleOwner.length;
const totalFiles = Object.keys(
stats.topContributors.reduce((acc, c) => ({ ...acc, ...c.files }), {})
).length;
const busFactorRisk = singleOwnerFiles / totalFiles;
console.log('Repository Health Check:');
console.log(`Active developers (90d): ${activeDevelopers}`);
console.log(`Bus factor risk: ${(busFactorRisk * 100).toFixed(1)}%`);
if (busFactorRisk > 0.3) {
console.warn('⚠️ High bus factor risk - consider knowledge sharing');
}
if (activeDevelopers < 3) {
console.warn('⚠️ Low active developer count');
}
}
import { generateReports } from 'git-contributor-stats/reports';
import { generateCharts } from 'git-contributor-stats/charts';
import { getContributorStats } from 'git-contributor-stats/stats';
import { generateReports } from 'git-contributor-stats/reports';
import { generateCharts } from 'git-contributor-stats/charts';
async function generateDashboard() {
const [weekly, monthly, quarterly] = await Promise.all([
getContributorStats({ since: '7.days' }),
getContributorStats({ since: '30.days' }),
getContributorStats({ since: '90.days' })
]);
await generateReports(weekly, {
outDir: 'dashboard/weekly',
md: 'dashboard/weekly/report.md',
html: 'dashboard/weekly/report.html'
});
await generateReports(monthly, {
outDir: 'dashboard/monthly',
md: 'dashboard/monthly/report.md',
html: 'dashboard/monthly/report.html'
});
await generateCharts(monthly, {
charts: true,
chartsDir: 'dashboard/monthly/charts'
});
await generateReports(quarterly, {
outDir: 'dashboard/quarterly',
md: 'dashboard/quarterly/report.md',
html: 'dashboard/quarterly/report.html'
});
await generateCharts(quarterly, {
charts: true,
chartsDir: 'dashboard/quarterly/charts',
chartFormat: 'both'
});
console.log('✓ Multi-period dashboard generated');
}
generateDashboard();
Top stats:
- Most commits: John Smith <john@example.com> (234)
- Most additions: Jane Doe <jane@example.com> (15,432)
- Most deletions: Alice Dev <alice@example.com> (8,901)
- Best net contribution: Jane Doe <jane@example.com> (12,345)
- Most changes: Jane Doe <jane@example.com> (24,333)
┌─────┬────────────────┬─────────┬──────────┬──────────┬─────────┐
│Rank │ Contributor │ Commits │ Additions│ Deletions│ Changes │
├─────┼────────────────┼─────────┼──────────┼──────────┼─────────┤
│ 1 │ Jane Doe │ 156 │ 15,432 │ 3,087 │ 18,519 │
│ 2 │ John Smith │ 234 │ 8,901 │ 4,523 │ 13,424 │
│ 3 │ Alice Dev │ 145 │ 6,234 │ 8,901 │ 15,135 │
└─────┴────────────────┴─────────┴──────────┴──────────┴─────────┘
Comprehensive analysis object with all metrics (see API Reference).
Rank,Name,Email,Commits,Additions,Deletions,Net,Changes
1,Jane Doe,jane@example.com,156,15432,3087,12345,18519
2,John Smith,john@example.com,234,8901,4523,4378,13424
3,Alice Dev,alice@example.com,145,6234,8901,-2667,15135
Interactive HTML report with:
# Skip LOC counting (significant speedup)
git-contributor-stats --no-count-lines
# Limit time range
git-contributor-stats --since 6.months
# Limit to specific paths
git-contributor-stats src/ --no-count-lines
# Analyze only recent commits
git-contributor-stats --since 30.days --top 10
# Specific branch only
git-contributor-stats -b main --since 90.days
# Exclude merge commits (default, but explicit)
git-contributor-stats --no-include-merges
# Fast CI run
git-contributor-stats \
--since 7.days \
--no-count-lines \
--format json > stats.json
Typical performance on a medium-sized repository (10k commits):
| Operation | With --count-lines | With --no-count-lines |
|---|---|---|
| Full analysis | ~15-20s | ~3-5s |
| Last 90 days | ~8-12s | ~2-3s |
| Last 30 days | ~5-8s | ~1-2s |
Performance varies based on repository size, file count, and system resources.
git clone https://github.com/vikkrantxx7/git-contributor-stats.git
cd git-contributor-stats
npm install
# Build the project
npm run build
# Run tests
npm test
# Run linter
npm run biome
# Fix linting issues
npm run biome:fix
# Generate types
npm run build:types
# Development mode (uses source files)
node dist/cli.mjs --help
# Generate sample reports
npm run report
git-contributor-stats/
├── src/
│ ├── features/
│ │ ├── stats.ts # Core statistics (tree-shakeable)
│ │ ├── charts.ts # Chart generation (tree-shakeable)
│ │ ├── reports.ts # Report generation (tree-shakeable)
│ │ ├── output.ts # Console output (tree-shakeable)
│ │ └── workflow.ts # GitHub Actions workflow (tree-shakeable)
│ ├── cli/
│ │ ├── entry.ts # CLI entry point
│ │ ├── index.ts # CLI logic
│ │ └── options.ts # Command-line options
│ ├── analytics/
│ │ ├── aggregator.ts # Data aggregation
│ │ ├── aliases.ts # Identity resolution
│ │ └── analyzer.ts # Core analysis logic
│ ├── charts/
│ │ ├── renderer.ts # Chart rendering (PNG)
│ │ └── svg.ts # SVG generation
│ ├── git/
│ │ ├── parser.ts # Git log parsing
│ │ └── utils.ts # Git operations
│ ├── reports/
│ │ ├── csv.ts # CSV generation
│ │ ├── html.ts # HTML generation
│ │ └── markdown.ts # Markdown generation
│ ├── utils/
│ │ ├── dates.ts # Date parsing
│ │ ├── files.ts # File operations
│ │ └── formatting.ts # Output formatting
│ └── api.ts # TypeScript types
├── dist/ # Built files
│ ├── features/ # Feature modules (separate entry points)
│ └── chunks/ # Shared code chunks
├── tests/ # Test files
├── package.json
├── tsconfig.json
├── vite.config.ts
└── vitest.config.ts
git-contributor-stats/charts - Chart generation with Chart.js (~260KB with charts)git-contributor-stats/reports - Report generation: CSV, Markdown, HTML (~200KB)git-contributor-stats/output - Console output formatting (table, JSON, CSV)git-contributor-stats/workflow - GitHub Actions workflow generator (~5KB)git-contributor-stats/cli - CLI entry point (combines all features)Bundle Size Comparison:
| Import | Bundle Size | Reduction |
|---|---|---|
| Core stats only | ~80KB | 84% smaller |
| Stats + Reports | ~200KB | 60% smaller |
| Stats + Charts | ~260KB | 48% smaller |
| Full features (CLI) | ~400KB | 20% smaller |
Compared to the previous monolithic bundle of ~500KB
See Technical Documentation for architecture details, tree-shaking verification, and migration guide
# Run all tests
npm test
# Run specific test
npm test -- tests/e2e/api.test.ts
# Watch mode
npm test -- --watch
# Coverage
npm test -- --coverage
📚 Complete documentation is available in the docs/ directory:
We welcome contributions! Please see our Contributing Guide for details.
Quick steps:
git checkout -b feature/amazing-feature)npm test && npm run lint)git commit -m 'feat: add amazing feature')npx changeset)📝 This project uses Conventional Commits and Changesets for version management.
Generate a workflow file:
git-contributor-stats --generate-workflow
This creates .github/workflows/git-contributor-stats.yml:
name: Git Contributor Stats
on:
schedule:
- cron: '0 0 * * 0' # Weekly on Sunday
workflow_dispatch:
jobs:
stats:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install git-contributor-stats
run: npm install -g git-contributor-stats
- name: Generate reports
run: |
git-contributor-stats \
--since 90.days \
--out-dir reports \
--md reports/report.md \
--html reports/report.html \
--charts \
--no-count-lines
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: contributor-stats
path: reports/
🔐 This project publishes packages with NPM provenance enabled, providing cryptographic proof of build authenticity.
For security issues, please see SECURITY.md for our security policy and how to report vulnerabilities responsibly.
MIT License - see LICENSE file for details.
Made with ❤️ for better repository insights
FAQs
CLI to compute contributor and repository statistics from a Git repository (commits, lines added/deleted, frequency, heatmap, bus-factor), with filters and multiple output formats.
We found that git-contributor-stats demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.