Fully autonomous release orchestration for Node.js projects. Monitors a git repository, parses conventional commits, generates changelogs, bumps semver versions, creates release branches, and opens pull requests — all without manual intervention.
The release pipeline executes a 12-step process:
┌─────────────────────────────────────────────────────────┐
│ 1. Validate → Clean working tree? On base branch? │
│ 2. Fetch → Pull latest from remote + tags │
│ 3. Analyze → Gather commits since last tag │
│ 4. Determine Bump → feat=minor, fix=patch, BREAKING=major│
│ 5. Compute Version→ 1.2.3 → 1.3.0 (semver increment) │
│ 6. Changelog → Group commits by type → Markdown │
│ 7. Branch → Create release/1.3.0 │
│ 8. Bump Files → Update package.json + lockfile │
│ 9. Write Changelog→ Prepend to CHANGELOG.md │
│ 10. Commit + Tag → chore(release): 1.3.0 + v1.3.0 tag │
│ 11. Push → Push branch + tags to remote │
│ 12. Open PR → Create PR via GitHub CLI (gh) │
└─────────────────────────────────────────────────────────┘
The tool parses commit messages following the Conventional Commits spec:
| Commit Message | Bump Type | Example Version Change |
|---|---|---|
feat: add dark mode |
minor | 1.2.3 → 1.3.0 |
fix: resolve memory leak |
patch | 1.2.3 → 1.2.4 |
feat!: redesign auth API |
major | 1.2.3 → 2.0.0 |
chore: update deps |
patch | 1.2.3 → 1.2.4 |
refactor(core): extract utils |
patch | 1.2.3 → 1.2.4 |
Any commit with ! after the type or BREAKING CHANGE: in the body triggers a major bump.
In watch mode, the tool runs as a background daemon that:
- Polls the remote at a configurable interval (default: 60s)
- Compares the local HEAD hash against the remote
- When new commits are detected, triggers the full release pipeline
- Handles errors gracefully and continues polling
- Shuts down cleanly on SIGINT/SIGTERM (Ctrl+C)
cd ~/Downloads/release-manager
npm install- Node.js >= 20
- git available in PATH
- gh (GitHub CLI) — required only for PR creation. Install via
brew install ghand rungh auth login
Run the pipeline once against a repository:
# Dry run — see what would happen
npx tsx src/cli/index.ts release --path /path/to/repo --dry-run
# Full release on current directory
npx tsx src/cli/index.ts release
# Custom options
npx tsx src/cli/index.ts release \
--path /path/to/repo \
--base main \
--prefix release/ \
--tag-prefix v \
--labels release,automated \
--draftWatch a repo and auto-release when new commits land:
# Default: poll every 60 seconds
npx tsx src/cli/index.ts watch --path /path/to/repo
# Poll every 30 seconds, draft PRs only
npx tsx src/cli/index.ts watch --path /path/to/repo -i 30 --draft
# No PR creation, just branch + tag + push
npx tsx src/cli/index.ts watch --path /path/to/repo --no-prnpx tsx src/cli/index.ts config| Flag | Default | Description |
|---|---|---|
-p, --path <path> |
. (cwd) |
Path to the git repository |
-b, --base <branch> |
main |
Base branch to compare against |
--prefix <prefix> |
release/ |
Release branch prefix |
--tag-prefix <prefix> |
v |
Git tag prefix |
--no-pr |
— | Skip pull request creation |
--no-push |
— | Skip pushing to remote |
--draft |
false |
Create PR as draft |
--no-changelog |
— | Skip CHANGELOG.md update |
--dry-run |
false |
Preview without making changes |
--labels <labels> |
release |
Comma-separated PR labels |
| Flag | Default | Description |
|---|---|---|
-p, --path <path> |
. (cwd) |
Path to the git repository |
-b, --base <branch> |
main |
Base branch to watch |
-i, --interval <sec> |
60 |
Polling interval in seconds |
--prefix <prefix> |
release/ |
Release branch prefix |
--tag-prefix <prefix> |
v |
Git tag prefix |
--no-pr |
— | Skip pull request creation |
--draft |
false |
Create PRs as drafts |
--labels <labels> |
release |
Comma-separated PR labels |
The tool produces grouped, readable changelogs:
# 1.3.0 (2026-03-31)
## Breaking Changes
- **auth:** remove legacy session tokens (`a1b2c3d`)
## Features
- **ui:** add dark mode toggle (`d4e5f6a`)
- add keyboard shortcuts (`b7c8d9e`)
## Bug Fixes
- **api:** resolve memory leak in connection pool (`f0a1b2c`)
## Contributors
- Aman Singh
- Jane Doe
---
*12 commit(s) since v1.2.3*src/
├── cli/index.ts CLI entry point (commander.js)
│ 3 commands: release, watch, config
│
├── git/
│ ├── types.ts Commit, TagInfo, BranchInfo types
│ └── operations.ts 15 git operations via execFile
│ (fetch, tag, branch, commit, push)
│
├── changelog/
│ └── generator.ts Conventional commit parser
│ Full changelog + compact PR body
│
├── version/
│ └── bumper.ts Semver bump determination
│ package.json + lockfile updater
│
├── pr/
│ └── creator.ts GitHub CLI (gh) wrapper
│ PR creation + duplicate detection
│
├── orchestrator/
│ ├── config.ts ReleaseConfig type + defaults
│ └── pipeline.ts 12-step release pipeline
│ Validation → changelog → branch → PR
│
├── daemon/
│ └── watcher.ts Polling loop with graceful shutdown
│ Detects new commits via hash comparison
│
└── utils/
├── exec.ts Safe command execution (no shell=true)
└── logger.ts Structured chalk-based logging
- All shell commands run via
execFile(no shell interpolation, no injection risk) - No
shell: trueanywhere in the codebase - No hardcoded secrets — relies on
gh authfor GitHub access - Validates repository state before any destructive operation
- Atomic file writes with indent-style preservation
Inspired by the Claude Code tool architecture:
- Validation pipeline (FileEditTool) — sequential checks with early bailout before any mutation
- Safe execution (BashTool) —
execFileoverexec, structured stdout/stderr capture - Recurring tasks (CronTool) — polling with graceful shutdown on SIGINT/SIGTERM
- Atomic edits (FileEditTool) — read current state, validate, write with format preservation
cd my-project # on main branch, clean working tree
npx tsx ~/Downloads/release-manager/src/cli/index.ts releaseOutput:
✔ Repository is clean and on base branch
✔ Latest tag: v1.2.3 (2026-03-28)
✔ Found 8 commit(s) → bump type: minor
✔ Version: 1.2.3 → 1.3.0
✔ Changelog generated
✔ Branch created: release/1.3.0
✔ package.json updated to 1.3.0 (+ package-lock.json)
✔ CHANGELOG.md updated
✔ Committed and tagged: v1.3.0
✔ Pushed branch and tags
✔ PR created: https://github.com/user/repo/pull/42
═══ Release Summary ═══
Version: 1.3.0
Tag: v1.3.0
Branch: release/1.3.0
Commits: 8
PR: https://github.com/user/repo/pull/42
# In a tmux/screen session or systemd service
npx tsx ~/Downloads/release-manager/src/cli/index.ts watch \
--path /opt/repos/my-project \
--interval 120 \
--draft \
--labels release,automatedMIT