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

linus-commits

v0.1.0

Published

CLI tool that enforces git hygiene standards for commit messages, branch names, and PR titles

Readme

linus-commits

A CLI tool that enforces git hygiene standards for commit messages, branch names, and PR titles. Installable via NPM, configurable via cosmiconfig, with git hook support and a GitHub Action wrapper.

Philosophy: Good commit hygiene makes repositories easier to navigate, review, and maintain. linus-commits codifies your team's git standards into enforceable rules that run locally (via git hooks) or in CI (via GitHub Actions).

Installation

# Install globally
npm install -g linus-commits

# Install as a dev dependency
npm install --save-dev linus-commits

# Or run directly with npx
npx linus-commits --help

Requirements: Node.js >= 18

Quick Start

# 1. Initialize a config file
linus-commits init

# 2. Install git hooks for local validation
linus-commits install

# 3. Make a commit — the hook validates your message automatically
git commit -m "TRX-123 Add user authentication module"

Global Flags

These flags are available on all subcommands:

| Flag | Description | |------|-------------| | --config <path> | Path to config file (overrides cosmiconfig discovery) | | --format <format> | Output format: human (default), json, or plain | | --quiet | Suppress all stdout output | | --color | Force colorized output | | --no-color | Disable colorized output | | --version, -V | Print version | | --help, -h | Print help |

Exit Codes

| Code | Constant | Meaning | |------|----------|---------| | 0 | SUCCESS | No violations, or only warnings | | 1 | VALIDATION_FAILURE | One or more error-level violations | | 2 | CONFIG_ERROR | Configuration or usage error | | 3 | GIT_ERROR | Git command failed (not a repo, branch not found, etc.) |

Note: Warnings do not cause a non-zero exit code. Only error-level violations cause exit code 1.

Commands

commit — Validate commit messages

# Validate a single commit message
linus-commits commit --message "TRX-123 Add user authentication module"

# Validate commits in a git range
linus-commits commit --range "main..HEAD"

# Validate all commits on current branch vs base branch (default behavior)
linus-commits commit

Options:

| Flag | Description | |------|-------------| | --message <msg> | Validate a single message (title, or title + blank line + description) | | --range <range> | Validate commits in a git range |

When neither flag is provided, validates all commits on the current branch compared to the configured baseBranch (default: main).

Example output (human format):

  error  imperative-mood  First word "Added" is non-imperative. Use "Add" instead
                          TRX-123 Added user authentication

1 problem (1 error, 0 warnings)

Example output (json format):

linus-commits commit --message "TRX-123 Added auth" --format json
[
  {
    "rule": "imperative-mood",
    "severity": "error",
    "message": "First word \"Added\" is non-imperative. Use \"Add\" instead",
    "subject": "TRX-123 Added auth"
  }
]

branch — Validate branch names

# Validate the current branch name
linus-commits branch

# Validate a specific branch name
linus-commits branch --name "TRX-123-add-user-auth"

Options:

| Flag | Description | |------|-------------| | --name <name> | Branch name to validate (defaults to current branch) |

Example output:

  error  no-gitflow  Branch name must not use gitflow prefixes (feat/, fix/, chore/)
                     feat/TRX-123-add-auth

1 problem (1 error, 0 warnings)

pr — Validate PR titles

# Validate a PR title
linus-commits pr --title "TRX-123 Add user authentication module"

# Auto-fix a PR title (prints corrected title to stdout)
linus-commits pr --title "trx-123 add feature" --fix

# Auto-fix a PR title in GitHub Actions (updates via API)
linus-commits pr --title "trx-123 add feature" --fix --github-token "$GITHUB_TOKEN"

Options:

| Flag | Description | |------|-------------| | --title <title> | Required. PR title to validate | | --fix | Print auto-corrected title to stdout | | --github-token <token> | GitHub token for auto-fixing PR title via API |

Auto-fix behavior:

  • Uppercases the ticket prefix (e.g., trx-123 becomes TRX-123)
  • Normalizes spacing between ticket and description
  • In GitHub Actions with --github-token: automatically updates the PR title via the GitHub API
  • In GitHub Actions without a token: emits a warning to stderr and skips the API call
  • Outside GitHub Actions: only prints the corrected title to stdout

staleness — Check PR staleness

# Check staleness using defaults (72 hours, baseBranch..HEAD)
linus-commits staleness

# Check with a custom range
linus-commits staleness --range "main..HEAD"

# Check with a custom threshold
linus-commits staleness --threshold 48

Options:

| Flag | Description | |------|-------------| | --range <range> | Git range to check (default: baseBranch..HEAD) | | --threshold <hours> | Staleness threshold in hours (overrides config) |

Fails if the PR age (time between earliest and latest commit) exceeds the threshold and no commit in the range has a description.

init — Initialize config file

# Create .linusrc.json with default config
linus-commits init

# Overwrite an existing config file
linus-commits init --force

Options:

| Flag | Description | |------|-------------| | --force | Overwrite existing config file |

install — Install git hooks

# Install default commit-msg hook
linus-commits install

# Install a pre-push hook
linus-commits install --hook pre-push

# Force overwrite existing hook
linus-commits install --force

# Append to an existing hook file
linus-commits install --append

Options:

| Flag | Description | |------|-------------| | --hook <type> | Hook type: commit-msg (default) or pre-push | | --force | Overwrite existing hooks without prompting | | --append | Append to existing hook files |

Husky detection: Automatically detects Husky by checking for a .husky/ directory or husky in package.json dependencies. When Husky is detected, hooks are installed in .husky/ following Husky conventions.

uninstall — Remove git hooks

linus-commits uninstall

Removes all linus-commits hooks. If a hook file contains other content besides linus-commits, only the linus-commits portion is removed.

Full PR validation workflow

To comprehensively validate all aspects of a branch/PR before merge, run all subcommands together:

linus-commits commit && \
linus-commits branch && \
linus-commits pr --title "TRX-123 Add user authentication" && \
linus-commits staleness

This validates commit messages, branch name, PR title, and staleness in sequence, stopping at the first failure.

Configuration

Configuration is loaded via cosmiconfig from these locations (in order of precedence):

  • linus-commits key in package.json
  • .linusrc (JSON or YAML)
  • .linusrc.json
  • .linusrc.yaml
  • linus-commits.config.js
  • linus-commits.config.cjs

The --config <path> flag overrides automatic discovery.

Default Configuration

{
  "rules": {
    "ticket-prefix": "error",
    "capitalization": "error",
    "title-length": "error",
    "title-punctuation": "error",
    "min-words": "error",
    "imperative-mood": "error",
    "no-conventional-commits": "error",
    "fix-requires-description": "error",
    "description-line-length": "warn",
    "description-punctuation": "warn",
    "branch-format": "error",
    "no-gitflow": "error",
    "staleness": "error"
  },
  "ticketRequired": true,
  "ticketPattern": "^[A-Z]{2,}-\\d{1,4}\\s",
  "maxTitleLength": 72,
  "minTitleWords": 3,
  "maxDescriptionLineLength": 78,
  "staleThresholdHours": 72,
  "nonImperativeWords": [
    "adds", "added", "creates", "created",
    "updates", "updated", "fixes", "fixed",
    "moves", "moved", "changes", "changed",
    "removes", "removed", "uses", "used"
  ],
  "exemptPatterns": ["revert", "merge", "\\[snyk\\]"],
  "baseBranch": "main"
}

Configuration Keys

| Key | Type | Default | Description | |-----|------|---------|-------------| | rules | object | See above | Rule severity map ("error", "warn", or "off") | | ticketRequired | boolean | true | Whether a Jira ticket prefix is required | | ticketPattern | string | ^[A-Z]{2,}-\\d{1,4}\\s | Regex pattern for ticket prefix | | maxTitleLength | number | 72 | Maximum title length in characters | | minTitleWords | number | 3 | Minimum word count after ticket prefix | | maxDescriptionLineLength | number | 78 | Maximum description line length | | staleThresholdHours | number | 72 | Hours before a PR is considered stale | | nonImperativeWords | string[] | See above | Words that violate imperative mood | | exemptPatterns | string[] | See above | Regex patterns for exempt commit titles | | baseBranch | string | "main" | Base branch for commit range detection |

Rule Severities

Each rule can be set to one of three severity levels:

  • "error" — Causes exit code 1 (validation failure)
  • "warn" — Reported but does not affect exit code
  • "off" — Rule is completely skipped

Example: disable the ticket-prefix rule:

{
  "rules": {
    "ticket-prefix": "off"
  }
}

Validation Rules

Commit/PR Title Rules

| Rule | Default | Description | |------|---------|-------------| | ticket-prefix | error | Title must start with a Jira ticket (e.g., TRX-123 ) | | capitalization | error | First word after ticket must be capitalized | | title-length | error | Title must not exceed maxTitleLength (72) characters | | title-punctuation | error | Title must not end with ., ?, or trailing whitespace | | min-words | error | At least minTitleWords (3) words after ticket prefix | | imperative-mood | error | First word must be imperative (not past tense) | | no-conventional-commits | error | No feat:, fix:, chore:, etc. prefixes |

Titles matching exemptPatterns (revert, merge, [snyk]) bypass ticket-prefix and title-length checks.

Commit Description Rules

| Rule | Default | Description | |------|---------|-------------| | fix-requires-description | error | "Fix" commits must include a description (except "Fix typo") | | description-line-length | warn | Lines must not exceed maxDescriptionLineLength (78) chars | | description-punctuation | warn | Must start with capital letter and end with . , ? or : |

Description line length exempts: URLs, code blocks (```), backtick lines, and lines with 2+ leading spaces.

Branch Name Rules

| Rule | Default | Description | |------|---------|-------------| | branch-format | error | Must match JIRA-123-kebab-case-description | | no-gitflow | error | No feat/, feature/, fix/, chore/ prefixes |

Staleness Rule

| Rule | Default | Description | |------|---------|-------------| | staleness | error | PRs older than staleThresholdHours must have at least one commit with a description |

GitHub Action

Use linus-commits as a composite GitHub Action in your workflows:

name: Git Hygiene
on:
  pull_request:
    types: [opened, edited, synchronize]

jobs:
  lint-commits:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - uses: your-org/linus-commits@v1
      with:
        base-branch: main
        check: all
        github-token: ${{ secrets.GITHUB_TOKEN }}

Inputs

| Input | Required | Default | Description | |-------|----------|---------|-------------| | base-branch | No | main | Base branch to compare commits against | | config-path | No | | Path to linus-commits config file | | check | No | all | Checks to run: commit, branch, pr, staleness, or all | | github-token | No | | GitHub token for auto-fixing PR titles | | node-version | No | 20 | Node.js version to use |

Outputs

| Output | Description | |--------|-------------| | result | Overall result: pass or fail | | errors | JSON array of violations |

Run specific checks only

- uses: your-org/linus-commits@v1
  with:
    check: commit,branch
    base-branch: develop

Use outputs in subsequent steps

- uses: your-org/linus-commits@v1
  id: lint
  with:
    check: all

- run: echo "Result was ${{ steps.lint.outputs.result }}"

License

MIT