@arcmantle/prospector
v1.1.2
Published
Automatic semantic versioning from git history for trunk-based development
Maintainers
Readme
Prospector
Semantic versioning made simple. Calculate versions automatically from your git history using trunk-based development.
What is Prospector?
Prospector is a tool that generates semantic versions (semver) for your project based on git commits. Instead of manually updating version numbers, Prospector reads your git history and commit messages to calculate the current version automatically.
Perfect for:
- Trunk-based development workflows
- Automated CI/CD pipelines
- Projects that want automatic versioning without manual intervention
- Teams that need consistent versioning across repositories
Quick Start
# Install
pnpm add -D @arcmantle/prospector
# Get current version
prospector
# Output: 1.2.5
# See what's next
prospector --suggest minor
# Output: 1.3.0Using in GitHub Actions
The primary way to use Prospector is in CI/CD pipelines. Add it to your workflow to automatically version your packages:
name: Publish Package
on:
push:
branches: [main]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required: fetch all history for version calculation
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: https://registry.npmjs.org/
# Calculate version using Prospector
- name: Calculate version
id: version
uses: arcmantle/prospector@v1
with:
dir: '.' # Optional: defaults to repository root
# Use the calculated version
- name: Set package version
run: |
echo "Setting version to ${{ steps.version.outputs.version }}"
npm version ${{ steps.version.outputs.version }} --no-git-tag-version
- name: Publish to NPM
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}GitHub Action Inputs
| Input | Description | Default |
| ------- | ------------- | --------- |
| dir | Repository directory path | '.' |
| branch | Main branch name(s) | 'main' (also recognizes 'master') |
| prefix | Version tag prefix | 'v' |
| no-commit-bumps | Disable commit message bumping | false |
GitHub Action Outputs
| Output | Description |
| -------- | ------------- |
| version | The calculated semantic version (e.g., 1.2.5) |
| branch | Current branch name |
| is-main-branch | 'true' if on main branch, 'false' otherwise |
| commits-since-tag | Number of commits since last version tag |
Example: Conditional Publishing
Only publish on main branch with new commits:
- name: Calculate version
id: version
uses: arcmantle/prospector@v1
- name: Publish to NPM
if: steps.version.outputs.is-main-branch == 'true' && steps.version.outputs.commits-since-tag != '0'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Key Features
- 🚀 Smart Version Calculation: Automatically determines versions from git history
- 💬 Commit Message Bumps: Use
[major],[minor],[patch]in commit messages for explicit version control - 🏷️ Tag-Based Releases: Create git tags for official version markers
- 🌿 Branch-Aware: Different versioning for main branch vs feature branches
- ⚡ Lightning Fast: Optimized for repositories with millions of commits
- 🔧 Flexible: CLI tool or programmatic API
- 📦 Zero Config: Works out of the box with sensible defaults
- ⚙️ GitHub Action: Use in CI/CD pipelines (see GitHub Action docs)
How It Works
Three Simple Rules
- On main branch: Version increments based on commits and tags
- On feature branches: Version gets a prerelease suffix (e.g.,
1.2.3-feature.5) - Git tags set versions: Create tags like
v1.0.0to mark releases
Example
# Start: No tags, 10 commits on main
prospector → 0.0.10
# Tag a release
git tag v1.0.0
# Make 3 more commits
prospector → 1.0.3
# Create feature branch with 2 commits
git checkout -b feature/awesome
prospector → 1.0.1-feature-awesome.2
# Merge back to main
git checkout main
git merge feature/awesome
prospector → 1.0.4Installation
# npm
npm install -D @arcmantle/prospector
# pnpm
pnpm add -D @arcmantle/prospector
# yarn
yarn add -D @arcmantle/prospectorOr use as a GitHub Action - see GitHub Action docs for details.
Usage
Command Line Interface
# Get the current version
prospector
# Output as JSON
prospector --json
# Show detailed information
prospector --detailed
# Suggest next version for a release
prospector --suggest minor
prospector --suggest major
# Use custom repository path
prospector --dir /path/to/repo
# Use custom branch name and tag prefix
prospector --branch master --prefix version-
# Default supports both 'main' and 'master' automatically
# No need to specify --branch unless using a different nameCLI Options
-h, --help- Show help message-d, --dir <path>- Git repository path (default: current directory)-b, --branch <name>- Main/trunk branch name (default: bothmainandmasterare recognized)-p, --prefix <prefix>- Version tag prefix (default:v)--json- Output as JSON--detailed- Output detailed information--suggest <type>- Suggest next version (major,minor, orpatch)--no-commit-bumps- Disable commit message based version bumping
Programmatic API
import { calculateVersion, suggestVersionBump } from '@arcmantle/prospector';
// Get current version
const info = await calculateVersion({
cwd: '/path/to/repo',
tagPrefix: 'v'
});
console.log(info.version); // "1.2.5"
console.log(info.commitBumps); // { major: 0, minor: 2, patch: 1, explicitVersion: null }
// Suggest next version
const next = await suggestVersionBump('minor');
console.log(next); // "1.3.0"Configuration Options
await calculateVersion({
// Repository path (default: current directory)
cwd: '/path/to/repo',
// Main branch names (default: ['main', 'master'])
mainBranch: 'develop',
// Or multiple: mainBranch: ['main', 'master', 'trunk'],
// Tag prefix (default: 'v')
tagPrefix: 'version-',
// Enable commit message bumping (default: true)
enableCommitBumps: true,
// Custom commit patterns
commitBumpPatterns: {
major: /BREAKING|!:/i,
minor: /feature:|feat:/i,
patch: /fix:|bugfix:/i
},
// Progress callback
onProgress: (msg) => console.log(msg)
});Versioning Behavior
Main Branch (Trunk)
On your main branch, Prospector uses commit messages to determine version bumps:
Commit Message Markers
Add these markers to your commit messages for explicit version control:
| Marker | Effect | Example |
|-------------------|------------------------------------|--------------------------------------------------------|
| [major] | Bump major version (2.0.0 → 3.0.0) | git commit -m "[major] Breaking API changes" |
| [minor] | Bump minor version (1.2.0 → 1.3.0) | git commit -m "[minor] Add new feature" |
| [patch] | Bump patch version (1.2.3 → 1.2.4) | git commit -m "[patch] Fix bug" |
| [version:x.y.z] | Set exact version | git commit -m "[version:2.5.0] Release 2.5.0" |
| [v:x.y.z] | Set exact version (short) | git commit -m "[v:1.0.0] Initial release" |
How Bumps Work
- Explicit versions (
[version:x.y.z]) take absolute precedence - Multiple bump indicators accumulate (e.g., 3
[minor]= +3 to minor version) - When major bumps, minor and patch reset to 0
- When minor bumps, patch resets to 0
- If no explicit bumps found, falls back to commit count
Optimized Scanning (Default)
Prospector is extremely fast even with millions of commits. It uses git's internal indexes to find only commits with bump markers:
Why it's fast:
- Only fetches commits containing
[major],[minor],[patch], or[version:x.y.z] - Uses
git log --grep(built-in git optimization) - Early stops when explicit version found
- Typical repositories: <1% of commits have markers
Performance examples:
- 100K commits, 50 with markers → ~0.2s, ~500KB memory
- 1M commits, 100 with markers → ~0.3s, ~1MB memory
- 10M commits, 200 with markers → ~0.5s, ~2MB memory
No configuration needed - it just works fast out of the box!
Legacy Scan Limit (Optional)
For edge cases or specific performance requirements, you can enable a scan limit:
// Only if you experience performance issues
calculateVersion({ maxCommitScan: 1000 })When maxCommitScan is set, Prospector falls back to the legacy scanning mode that fetches all commits up to the limit. This is generally not needed with the optimized approach.
Tagging Best Practices
Use git tags to mark official releases:
# Work with commit markers
git commit -m "[minor] Add feature A"
git commit -m "[patch] Fix bug"
git commit -m "[minor] Add feature B"
# Mark official release
git tag v1.5.0
git push --tags
# Continue development
git commit -m "[patch] Quick fix"
prospector → 1.5.1Why tag?
- Tags mark stable release points
- Makes version history clear
- Allows easy rollback to specific versions
- Prevents hundreds of bump markers from accumulating
Feature Branches
Feature branches automatically get prerelease versions:
Format: {base_version}-{branch_name}.{commit_count}
Example:
# On main: v1.2.0 exists
git checkout -b feature/awesome-thing
# Make 3 commits
prospector → 1.2.1-feature-awesome-thing.3How it works:
- Find last version tag (
v1.2.0) - Increment patch by 1 (
1.2.1) - Add branch name (sanitized) and commit count as prerelease
This makes it clear the version is:
- Not an official release
- Based on version 1.2.0
- From the "feature-awesome-thing" branch
- 3 commits ahead
No Tags (Initial State)
When no git tags exist:
- Main branch:
0.0.{total_commits}- Example: 15 commits →
0.0.15
- Example: 15 commits →
- Feature branch:
0.0.1-{branch_name}.{total_commits}- Example: 8 commits on
feature/init→0.0.1-feature-init.8
- Example: 8 commits on
Create your first tag when ready to release:
git tag v1.0.0
git push --tagsAdvanced Usage
Disable Commit Bumps (Faster)
For maximum speed, disable commit message scanning:
# CLI
prospector --no-commit-bumps
# API
await calculateVersion({ enableCommitBumps: false })This uses only commit count, no message parsing. Version is simply {tag} + {commit_count}.
Custom Commit Patterns
Match your team's commit conventions:
await calculateVersion({
commitBumpPatterns: {
major: /BREAKING CHANGE|!:/i,
minor: /^feat:/i,
patch: /^fix:/i
}
});Now commits like feat: add dashboard will bump minor version.
Legacy Scan Limit
If you experience issues (very rare), you can limit commit scanning:
await calculateVersion({
maxCommitScan: 1000 // Only scan last 1000 commits
})Note: This is rarely needed. The default optimized mode handles millions of commits efficiently.
API Reference
calculateVersion(options?)
Calculates the current version based on git history.
Parameters:
options.cwd- Repository path (default:'.')options.mainBranch- Main/trunk branch name(s). Can be a string or array of strings (default:['main', 'master']- both are recognized as trunk branches)options.tagPrefix- Tag prefix (default:'v')options.enableCommitBumps- Enable commit message bumping (default:true)options.maxCommitScan- Optional limit on commits to scan. Only set this if you experience performance issues. When undefined (default), uses optimized git grep scanning with no limit.options.commitBumpPatterns- Custom regex patterns for detecting bumps
Returns: VersionInfo object with:
version- The calculated version stringbranch- Current branch nameisMainBranch- Whether on main branchcommitsSinceTag- Number of commits since last taglastTag- Last version tag info (or null)currentCommit- Current commit hashcommitBumps- Object with{ major, minor, patch, explicitVersion }counts from commit messages
suggestVersionBump(bumpType, options?)
Suggests the next version for a given bump type.
Parameters:
bumpType-'major','minor', or'patch'options- Same ascalculateVersion
Returns: Version string (e.g., '2.0.0')
Performance
Prospector is extremely fast even with millions of commits:
Why It's Fast
- Optimized git operations: Uses
git log --grepto scan only commits with bump markers - Typical case: <1% of commits have version markers, so we only process <1%
- Early termination: Stops when explicit version found
- Smart counting: Uses
git rev-list --count(O(1) operation)
Performance Data
|Repository Size|Commits with Bumps|Time |Memory| |---------------|------------------|------|------| |1K commits |20 |< 0.1s|< 1MB | |10K commits |50 |< 0.2s|< 1MB | |100K commits |100 |< 0.3s|< 2MB | |1M commits |200 |< 0.5s|< 3MB | |10M commits |500 |< 1s |< 5MB |
With --no-commit-bumps: All sizes run in < 0.1s.
Quick Reference
Commit Marker Syntax
# Major version bump (1.0.0 → 2.0.0)
git commit -m "[major] Breaking API changes"
# Minor version bump (1.0.0 → 1.1.0)
git commit -m "[minor] New reporting feature"
# Patch version bump (1.0.0 → 1.0.1)
git commit -m "[patch] Fix bug in login"
# Set exact version
git commit -m "[version:2.5.0] Release version 2.5.0"
git commit -m "[v:1.3.7] Align with upstream"
# No explicit bump (uses commit count for patch)
git commit -m "Update README"See docs/COMMIT_SYNTAX.md for more details on commit message patterns.
Common CLI Commands
# Get current version
prospector
# Show detailed information including commit bumps
prospector --detailed
# Disable commit message bumping
prospector --no-commit-bumps
# Suggest next minor release
prospector --suggest minor
# Use in different directory
prospector --dir /path/to/repoLicense
MIT
