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

@edcalderon/versioning

v1.5.13

Published

A comprehensive versioning and changelog management tool for monorepos

Readme

@edcalderon/versioning

npm version npm downloads GitHub

A comprehensive versioning and changelog management tool designed for monorepos and single repositories. It provides automated version bumping, changelog generation using conventional commits, and version synchronization across multiple packages.


📋 Latest Changes (v1.5.13)

Bug Fixes

  • release: require a current README release entry and matching package version before tagged publication
  • release: block accidental public npm publishes outside the tagged GitHub Actions workflow
  • release: skip an already-published version instead of failing a rerun or recovery workflow

For full version history, see CHANGELOG.md and GitHub releases


Features

  • 🚀 Automated version bumping (patch, minor, major, prerelease)
  • 🌿 Optional branch-aware versioning (main, develop, feature/*, hotfix/*)
  • 📝 Conventional commit-based changelog generation
  • 🔄 Version synchronization across monorepo packages
  • 🎯 Works with both monorepos and single repositories
  • 📦 NPM publishable
  • 🏷️ Git tagging and committing
  • ✅ Validation of version sync
  • 🧭 Changelog validation before release
  • 🔌 Extensible plugin system for subdirectory-based extensions
  • 🔒 Security Checks with automatic Husky integration
  • 🧹 Repository Cleanup to keep root directory organized
  • 🗂️ .agents/ task tracking with reentry snapshot sync

Installation

npm install -g @edcalderon/versioning
# or
pnpm add -g @edcalderon/versioning
# or
yarn global add @edcalderon/versioning

Extensions

The versioning tool supports a composable extension system that allows you to add custom business logic and commands. Extensions can:

  • Add new CLI commands
  • Hook into existing workflows (pre/post version bumps, releases, etc.)
  • Integrate with external services
  • Implement custom versioning strategies

Extensions are loaded automatically from:

  • Built-in extensions in subdirectories of src/extensions/ (e.g. src/extensions/changelog-guard/index.ts, src/extensions/reentry-status/index.ts, src/extensions/tasks/index.ts)
  • External packages listed in versioning.config.json

Creating Extensions

Extensions are TypeScript modules that implement the VersioningExtension interface:

import { Command } from 'commander';
import { VersioningExtension } from '@edcalderon/versioning';

const extension: VersioningExtension = {
  name: 'my-extension',
  description: 'My custom extension',
  version: '1.0.0',

  register: async (program: Command, config: any) => {
    // Add custom commands here
    program
      .command('my-command')
      .description('My custom command')
      .action(async () => {
        console.log('Custom command executed!');
      });
  },

  hooks: {
    preVersion: async (type: string, options: any) => {
      console.log(`About to bump ${type} version...`);
    },
    postVersion: async (type: string, version: string, options: any) => {
      console.log(`Version bumped to ${version}`);
    }
  }
};

export default extension;

Extension Hooks

Extensions can hook into the versioning lifecycle:

  • preVersion: Called before version bump
  • postVersion: Called after version bump
  • preRelease: Called before release creation
  • postRelease: Called after release creation
  • preChangelog: Called before changelog generation
  • postChangelog: Called after changelog generation
  • preSync: Called before version sync
  • postSync: Called after version sync

Built-in Extensions

Workspace Env Extension

Adds first-class workspace environment orchestration for monorepos:

versioning env sync
versioning env doctor
versioning env validate --target landing

Key capabilities:

  • Canonical root env sources: .env then .env.local
  • Alias resolution for legacy variable names
  • Minimal per-target runtime env generation
  • Root and per-target example file generation from one manifest
  • Deterministic output with generated headers and no rewrites when content is unchanged
  • CI-friendly validation and dry-run sync checks

Manifest default lookup order:

  • config/env/manifest.ts
  • config/env/manifest.cjs
  • config/env/manifest.js
  • config/env/manifest.json

Supported manifest styles:

  • Legacy map-based manifest:
{
  sources: ['.env', '.env.local'],
  variables: {
    SUPABASE_URL: {
      description: 'Supabase URL',
      required: true,
      targets: {
        landing: 'NEXT_PUBLIC_SUPABASE_URL'
      }
    }
  },
  targets: {
    landing: {
      path: 'apps/landing'
    }
  }
}
  • Spec-style manifest:
{
  rootExampleFile: '.env.example',
  variables: [
    {
      key: 'SUPABASE_URL',
      description: 'Supabase URL'
    },
    {
      key: 'OPENAI_API_KEY',
      aliases: ['LEGACY_OPENAI_KEY'],
      secret: true
    }
  ],
  targets: [
    {
      id: 'landing',
      outputFile: 'apps/landing/.env.local',
      exampleFile: 'apps/landing/.env.example',
      entries: [
        {
          source: 'SUPABASE_URL',
          target: 'NEXT_PUBLIC_SUPABASE_URL',
          required: true
        },
        {
          source: 'OPENAI_API_KEY'
        }
      ]
    }
  ]
}

CLI options:

versioning env sync --target landing --check
versioning env sync --json
versioning env doctor --target landing --json
versioning env validate --all --strict-unused

Basic config (versioning.config.json):

{
  "extensionConfig": {
    "workspace-env": {
      "enabled": true,
      "manifestPath": "config/env/manifest.cjs"
    }
  }
}

Lifecycle Hooks Extension

Demonstrates all available hooks with example business logic:

versioning hooks list    # List available hooks
versioning hooks run pre-deploy  # Manually run a hook

NPM Publish Extension

Handles NPM publishing with custom logic:

versioning publish-package --tag latest
versioning publish-local --registry http://localhost:4873

Features:

  • Automatic package building
  • Prepublish checks
  • Publication verification
  • 2FA/OTP support
  • Local registry support
  • Dry-run mode

Re-entry Status + Roadmap Extension

Maintains a fast re-entry layer (current state + next micro-step) and a slow roadmap/backlog layer (long-term plan).

Canonical files:

Single-project (default):

  • .versioning/reentry.status.json (machine)
  • .versioning/REENTRY.md (generated, minimal diffs)
  • .versioning/ROADMAP.md (human-first; only a small managed header block is auto-updated)

Multi-project (scoped by --project <name>):

  • .versioning/projects/<project>/reentry.status.json
  • .versioning/projects/<project>/REENTRY.md
  • .versioning/projects/<project>/ROADMAP.md

Smart Features:

  • Auto-Update: versioning reentry update infers the project phase and next step from your last git commit.
    • feat: ... → Phase: development
    • fix: ... → Phase: maintenance
  • Git Context: Automatically links status to the latest branch, commit, and author.

Commands:

# Fast layer
versioning reentry init
versioning reentry update        # Auto-update status from git commit
versioning reentry show          # Show current status summary
versioning reentry sync

# Fast layer (scoped)
versioning reentry init --project trader
versioning reentry update --project trader
versioning reentry show --project trader

# Slow layer
versioning roadmap init --title "My Project"
versioning roadmap list
versioning roadmap set-milestone --id "now-01" --title "Ship X"

Cleanup Repo Extension

Keeps your repository root clean by organizing stray files into appropriate directories (docs, scripts, config, archive).

Features:

  • Smart Scanning: Identifies files that don't belong in the root.
  • Configurable Routes: Map extensions to folders (e.g. .sh → scripts/).
  • Safety: Allowlist for root files and Denylist for forced moves.
  • Husky Integration: Auto-scan or auto-move on commit.

Commands:

versioning cleanup scan          # Dry-run scan of root
versioning cleanup move          # Move files to configured destinations
versioning cleanup restore       # Restore a moved file
versioning cleanup config        # View/manage configuration
versioning cleanup husky         # Setup git hook (scan-only by default)

Configuration (versioning.config.json):

{
  "extensionConfig": {
    "cleanup-repo": {
      "enabled": true,
      "defaultDestination": "docs",
      "allowlist": ["CHANGELOG.md"],
      "routes": {
        ".sh": "scripts",
        ".json": "config"
      }
    }
  }
}

Secrets Check Extension

Prevents sensitive data (private keys, tokens, mnemonics) from being committed to the repository.

Features:

  • Pre-defined Patterns: Detects AWS, GitHub, NPM tokens, private keys, and EVM mnemonics.
  • Allowlist: Ignore false positives or specific test keys.
  • Husky Integration: Easy CLI setup to block commits containing secrets.

Commands:

versioning check-secrets         # Scan staged files for secrets
versioning check-secrets husky   # Add blocking secrets check to pre-commit hook

Configuration (versioning.config.json):

{
  "extensionConfig": {
    "secrets-check": {
      "enabled": true,
      "patterns": [
        "CUSTOM_API_KEY=[0-9a-f]{32}"
      ],
      "allowlist": [
        "ETHERSCAN_API_KEY=YOUR_KEY"
      ]
    }
  }
}

README Maintainer Extension

Keeps README.md files aligned with the latest changelog entry and resolves the release-history link from the target project when possible.

Behavior:

  • Uses package.json.repository first
  • Falls back to the git origin remote, then GITHUB_REPOSITORY
  • Omits the releases link when no project repository can be resolved

Override the release link with extensionConfig["readme-maintainer"].releasesUrl or repositoryUrl in versioning.config.json.

External Extensions

To use external extensions, add them to your versioning.config.json:

{
  "extensions": [
    "my-versioning-extension",
    {
      "name": "another-extension",
      "path": "./local-extensions/another-extension"
    }
  ]
}

External extensions should be published as NPM packages with the naming convention *-versioning-extension or implement the VersioningExtension interface.

Extension Development

  1. Create a new TypeScript file in src/extensions/
  2. Implement the VersioningExtension interface
  3. Export the extension as default
  4. The extension will be loaded automatically

For external extensions:

  1. Create a separate NPM package
  2. Export the extension as the main module
  3. Publish to NPM
  4. Install and configure in target projects

Extension API Reference

VersioningExtension Interface

interface VersioningExtension {
  name: string;                    // Extension name
  description: string;             // Extension description
  version: string;                 // Extension version
  register: (program: Command, config: any) => void | Promise<void>;
  hooks?: ExtensionHooks;          // Optional lifecycle hooks
}

ExtensionHooks Interface

interface ExtensionHooks {
  preVersion?: (type: string, options: any) => void | Promise<void>;
  postVersion?: (type: string, version: string, options: any) => void | Promise<void>;
  preRelease?: (version: string, options: any) => void | Promise<void>;
  postRelease?: (version: string, options: any) => void | Promise<void>;
  preChangelog?: (options: any) => void | Promise<void>;
  postChangelog?: (options: any) => void | Promise<void>;
  preSync?: (options: any) => void | Promise<void>;
  postSync?: (options: any) => void | Promise<void>;
}

Extension Context

Extensions can access the versioning context:

import { getExtensionContext } from '@edcalderon/versioning';

const context = getExtensionContext();
if (context) {
  // Access versionManager, changelogManager, etc.
}

Quick Start

  1. Initialize configuration:
versioning init
  1. Bump version and generate changelog:
versioning bump patch
  1. Sync versions across packages (for monorepos):
versioning sync

Edward's Monorepo Example

For this specific monorepo with dashboard app:

# Initialize config
versioning init

# Edit versioning.config.json to:
{
  "packages": ["apps/dashboard"],
  "ignorePackages": ["packages/versioning"]
}

# Sync dashboard with main version
versioning patch --packages "apps/dashboard"

# Versioning package maintains its own version
cd packages/versioning && versioning patch --skip-sync

Internal Versioning

This versioning package uses its own versioning system internally for development and releases:

# Bump version internally
npm run version:patch    # Bump patch version
npm run version:minor    # Bump minor version
npm run version:major    # Bump major version

# Generate changelog
npm run changelog

# Publish to a local registry for testing only
npm run publish:local

# Prepare a production release: bump and sync README
npm run release

# Commit and merge the release to main, then push the tag from main
npm run create-tag

The pushed versioning-v* tag is the only production publishing trigger for this package. Do not run npm publish or npm run publish:npm for a public release.

NPM Publish Extension

The package includes an NPM publishing extension for consumer projects. This repository's own public package release remains GitHub Actions-only.

# Publish to a local registry for testing
npm run publish:local

# Publish to custom local registry
npm run publish:local -- --registry http://localhost:4873

The extension automatically:

  • Builds the package if needed
  • Runs prepublish checks
  • Verifies publication
  • Handles 2FA/OTP if required
  • Supports dry-run mode

Configuration

Create a versioning.config.json file in your project root:

For single repositories:

{
  "rootPackageJson": "package.json",
  "packages": [],
  "changelogFile": "CHANGELOG.md",
  "conventionalCommits": true,
  "syncDependencies": false,
  "ignorePackages": [],
  "branchAwareness": {
    "enabled": false,
    "defaultBranch": "main",
    "branches": {
      "main": {
        "versionFormat": "semantic",
        "tagFormat": "v{version}",
        "syncFiles": ["package.json", "version.production.json"],
        "environment": "production",
        "bumpStrategy": "semantic"
      },
      "develop": {
        "versionFormat": "dev",
        "tagFormat": "v{version}",
        "syncFiles": ["version.development.json"],
        "environment": "development",
        "bumpStrategy": "dev-build"
      },
      "feature/*": {
        "versionFormat": "feature",
        "tagFormat": "v{version}",
        "syncFiles": ["version.development.json"],
        "environment": "development",
        "bumpStrategy": "feature-branch"
      },
      "hotfix/*": {
        "versionFormat": "hotfix",
        "tagFormat": "v{version}",
        "syncFiles": ["version.development.json"],
        "environment": "development",
        "bumpStrategy": "hotfix"
      }
    }
  }
}

For monorepos:

{
  "rootPackageJson": "package.json",
  "packages": ["packages/*", "apps/*"],
  "changelogFile": "CHANGELOG.md",
  "conventionalCommits": true,
  "syncDependencies": true,
  "ignorePackages": []
}

Configuration Options

  • rootPackageJson: Path to the root package.json file
  • packages: Array of glob patterns for packages to sync
  • changelogFile: Path to the changelog file
  • conventionalCommits: Whether to use conventional commits for changelog
  • syncDependencies: Whether to sync internal dependencies
  • ignorePackages: Array of package names to ignore during sync
  • branchAwareness: Optional branch-aware release rules and file sync targets
  • branchAwareness.branches.<pattern>.versionFormat: semantic, dev, feature, hotfix, or custom
  • branchAwareness.branches.<pattern>.syncFiles: Only these files are updated when branch-aware mode is enabled

Branch-Aware Releases

Enable branch-aware mode per command:

versioning patch --branch-aware
versioning patch --branch-aware --target-branch develop
versioning patch --branch-aware --format dev --build 396
versioning minor --branch-aware
versioning major --branch-aware

Behavior summary:

  • Exact branch names are checked first (e.g. main, develop)
  • Wildcard patterns are checked next (e.g. feature/*, hotfix/*)
  • If no match is found, the defaultBranch rule is used
  • --force-branch-aware enables branch-aware behavior even when branchAwareness.enabled is false
  • Full config template: packages/versioning/examples/versioning.config.branch-aware.json

Commands

Release Commands

versioning patch [options]

Create a patch release (bumps 1.0.0 → 1.0.1)

versioning patch
versioning patch --packages "packages/app1,packages/app2" --message "Fix critical bug"

versioning minor [options]

Create a minor release (bumps 1.0.0 → 1.1.0)

versioning minor
versioning minor --packages "apps/dashboard" --message "Add new features"

versioning major [options]

Create a major release (bumps 1.0.0 → 2.0.0)

versioning major --message "Breaking changes"

versioning release <version> [options]

Create a custom release with specific version

versioning release 1.2.3 --message "Custom release"
versioning release 2.0.0-beta.1 --skip-sync

Options for patch, minor, and major:

  • -p, --packages <packages>: Comma-separated list of packages to sync
  • -m, --message <message>: Release commit message
  • -c, --config <file>: Config file path (default: versioning.config.json)
  • --branch-aware: Enable branch-aware release behavior
  • --force-branch-aware: Force branch-aware mode even if disabled in config
  • --target-branch <branch>: Explicit branch to resolve branch rules
  • --format <format>: Override the configured branch version format
  • --build <number>: Override build number for non-semantic branch formats
  • --no-tag: Do not create git tag
  • --no-commit: Do not commit changes

Options for release <version>:

  • -p, --packages <packages>: Comma-separated list of packages to sync
  • -m, --message <message>: Release commit message
  • -c, --config <file>: Config file path (default: versioning.config.json)
  • --no-tag: Do not create git tag
  • --no-commit: Do not commit changes
  • --skip-sync: Skip version synchronization

Other Commands

Bump the version and generate changelog.

Types: patch, minor, major, prerelease

Options:

  • -p, --pre-release <identifier>: Prerelease identifier
  • -c, --config <file>: Config file path (default: versioning.config.json)
  • --no-commit: Don't commit changes
  • --no-tag: Don't create git tag

versioning changelog [options]

Generate changelog from commits.

Options:

  • -f, --from <commit>: From commit
  • -t, --to <commit>: To commit
  • -c, --config <file>: Config file path

versioning sync [options]

Sync versions across all packages.

Options:

  • -v, --version <version>: Target version to sync to
  • -c, --config <file>: Config file path

versioning validate [options]

Validate that all packages have the correct version.

Options:

  • -c, --config <file>: Config file path

versioning init [options]

Initialize a new versioning config file.

Options:

  • -f, --force: Overwrite existing config

Workflow Integration

GitHub Actions

Add to your release workflow:

- name: Bump version
  run: npx @edcalderon/versioning bump patch
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Pre-commit Hooks

Use with husky for automated versioning:

npx husky add .husky/pre-commit "versioning validate"

Conventional Commits

This tool works best with conventional commits. Examples:

  • feat: add new feature (minor bump)
  • fix: resolve bug (patch bump)
  • BREAKING CHANGE: change API (major bump)

Documentation

Publishing & Releases

Automated NPM Publishing

This package uses GitHub Actions as the sole production publisher. Pushing a versioning-v<version> tag starts the publish workflow.

Release Process

  1. Prepare the release commit: Bump the version, generate the changelog, and sync the README.

    npm run version:patch
    npm run update-readme
  2. Commit and merge the release: The version, CHANGELOG, and README must be committed on main.

  3. Publish locally (optional): Test only against a local registry.

    npm run publish:local
  4. Create the release tag: Use the create-tag script to create and push the matching tag.

    npm run create-tag
  5. Monitor GitHub Actions: The workflow verifies the tag, package version, and generated README before publishing. It skips a version already present in npm instead of attempting a duplicate publish.

Quick Release Commands

# Prepare a production release, then commit and merge it to main
npm run release

# After the release commit is on main, create the publishing tag
npm run create-tag

# Local testing release
npm run release:local    # Bump version, changelog, publish locally

Public npm versions are immutable. A direct publish or rerun after a version is already published returns npm E403. The package lifecycle blocks public manual publishes by default. An emergency manual publish requires explicit maintainer approval and both ALLOW_MANUAL_NPM_PUBLISH=1 and MANUAL_PUBLISH_CONFIRM=@edcalderon/versioning@<version>.

NPM Token Setup

To enable automated publishing:

  1. Go to NPM → Access Tokens → Generate New Token
  2. Create a token with Automation scope
  3. Add it only to GitHub repository secrets as NPM_TOKEN; do not keep a production publishing token in local developer configuration.

Version Tags

Tags should follow the format v{major}.{minor}.{patch} for the CLI release flow and versioning-v{major}.{minor}.{patch} for this package's own publish flow (for example, v1.0.0, v1.1.0, versioning-v1.5.7).

The create-tag script will:

  • Read the version from package.json
  • Create an annotated git tag
  • Push the tag to trigger the publish workflow
  • Validate the tag against the current package version and the latest release floor before pushing

Release Guard

Enable release/tag consistency checks in versioning.config.json:

{
  "rootPackageJson": "package.json",
  "packages": ["packages/*", "apps/*"],
  "releaseGuard": {
    "enabled": true,
    "tagPrefix": "v",
    "allowBuildMetadata": true,
    "checkReleaseFloor": true,
    "metadataFiles": ["version.production.json"]
  }
}

This will validate the root package, all configured package directories, and any extra release metadata files before a release tag is published.