README
¶
bumpit
A terminal UI for keeping your monorepo in shape.
bumpit brings the recurring chores of a healthy codebase — updating dependencies, trimming dead weight, auditing licenses — into a single interactive interface. No browser tabs, no context switching, no scripting one-offs.
Package Updater
15 packages Sort: update type (MAJOR first) [s to cycle]
Package Current Latest Kind Status Dir/Type
▶ [x] react 18.2.0 → 19.0.0 MAJOR ⚠ Breaking (web) dep
[ ] tailwindcss 3.4.1 → 4.0.0 MAJOR ⚠ Breaking (root) dep
[ ] typescript 5.3.3 → 5.8.3 minor ✓ OK (root) dev
[ ] @types/node 20.11.0 → 22.0.0 MAJOR ⏳ 1d left (root) dev
[x] axios 1.6.8 → 1.7.9 minor ✓ OK (api) dep
[ ] lodash 4.17.20 → 4.17.21 patch ✓ OK (root) dep
2 package(s) selected
j/k: navigate space: select a: all enter: detail /: filter u: update s: sort ?: help q: quit
Commands
bumpit update [directory] # interactive outdated-package updater
bumpit unused [directory] # find and remove unused direct dependencies
bumpit license [directory] # audit dependency licenses
bumpit clean [directory] # find and delete generated artifact directories
bumpit css [directory] # two-way CSS audit: unused selectors and missing definitions
bumpit todo [directory] # list all TODO, FIXME, HACK, and XXX comments
bumpit i18n [directory] # two-way translation key audit: unused keys and undefined references
bumpit env [directory] # two-way .env.example audit: unused vars and undefined references
All commands default to the current directory. Run bumpit --help for a full flag listing.
Features
bumpit update
Changelog in the terminal. Opens GitHub releases for the full range between your current and latest version. No browser, no tab switching.
Breaking change detection. Scans release notes for BREAKING CHANGE, BREAKING:, ⚠️, and INCOMPATIBLE. Highlights affected packages in red.
minimumReleaseAge support. Reads your .npmrc for minimum-release-age (supports 3 days, 72h, 3d). Packages that haven't aged enough show a countdown instead of a status, matching pnpm's publish safety model.
Monorepo aware. Recursively finds every package.json and go.mod under the project root. Skips node_modules, dist, build, .git, and similar directories. Each package shows which workspace it belongs to.
Auto-detects package manager. Checks for pnpm-lock.yaml, yarn.lock, and package-lock.json — including walking up to the workspace root.
Security advisories. Runs pnpm audit in the background and surfaces vulnerability counts next to affected packages.
Batch updates. Select any combination of packages and press u. Updates are grouped by directory and run with pnpm update --latest.
Go modules. Parses go list -m -u -json all output alongside npm packages in a unified list.
bumpit unused
Unused dependency detection. Scans your source files, scripts, and tool config files to find direct dependencies that are never referenced. Select and remove them interactively. Understands ecosystem-specific patterns so it won't flag build tools, type definitions, or platform packages that are used without being directly imported.
Ecosystem-aware — will not flag:
@types/*packages when the corresponding package is installed- TypeScript, ESLint plugins/configs, Nx plugins, Capacitor platform packages, Vite/jsdom (as vitest peers), Angular build tooling, commitlint configs
bumpit license
License audit. Reads license metadata from locally installed node_modules for every direct dependency. Default view shows only packages that need attention, with a plain-English explanation of what each license requires. Press a to see all packages.
| Indicator | Commercial use | Open-source obligation |
|---|---|---|
✓ Permissive (MIT, ISC, Apache-2.0, BSD-*) |
✓ Free | None — keep the copyright notice; include license files when distributing |
⚠ Weak copyleft (LGPL-*, MPL-2.0) |
✓ Allowed | Only if you modify the library itself — using it as a dependency is fine |
✗ Strong copyleft (GPL-*, AGPL-3.0) |
✗ Not without open-sourcing | Distributing (GPL) or serving over a network (AGPL) requires open-sourcing your entire app |
? Unknown — no license field |
✗ Illegal by default | All rights reserved — contact the author before using |
Handles SPDX compound expressions: (MIT OR GPL-3.0-or-later) is treated as permissive (consumer picks MIT). Filter with /, toggle sort between risk-first and alphabetical with s.
bumpit clean
Artifact cleanup. Walks the project tree and finds all generated or installed directories — node_modules, dist, .next, .turbo, coverage, and more. Shows each with its disk size, sorted biggest-first so the most impactful targets are at the top. Select with space and press D to delete.
Finds: node_modules, dist, build, out, storybook-static, .next, .nuxt, .output, .angular, .svelte-kit, .vite, .turbo, .cache, coverage, .nyc_output.
bumpit css
Two-way CSS audit. Checks for problems in both directions:
| Indicator | Meaning |
|---|---|
~ (orange) |
Class defined in a CSS file but never referenced in any template |
? (red) |
Class referenced in a template class= attribute but absent from every CSS file |
The ~ direction catches dead CSS you can safely delete. The ? direction catches typos and stale references — class names that exist in markup but have no matching stylesheet rule.
Scans CSS files: .css, .scss, .sass, .less. Scans templates: .html, .jsx, .tsx, .js, .ts, .vue, .svelte.
How references are detected. Explicit class="..." and className="..." attributes drive both directions. String literals (cx('foo'), clsx('bar'), classList.add('baz')) are also checked but only for the ~ direction — they would produce too many false positives for the ? direction since common English words would appear to be missing CSS definitions.
Limitations:
- CSS modules (
.module.css) are skipped — class names are transformed by the bundler and referenced asstyles.className, not as string literals. - SCSS
&parent selectors (e.g.&__child,&:hover) are not resolved — classes composed via&may appear as unused even if they are referenced. - Tailwind utility classes are not tracked. If a Tailwind config is detected, a warning is shown.
Read-only — bumpit css reports findings but does not modify any files.
bumpit todo
Tech-debt overview. Scans every source file in the project and lists all TODO, FIXME, HACK, and XXX comments in one navigable list, sorted by file and line.
| Kind | Color | Typical use |
|---|---|---|
TODO |
blue | Planned work, missing feature |
FIXME |
orange | Known bug or broken code |
HACK |
orange | Workaround that should be cleaned up |
XXX |
red | Dangerous or critical tech debt |
Scans: .go, .js, .ts, .jsx, .tsx, .vue, .svelte, .css, .scss, .html, .yaml, .sh, and more. Filter with / to search by kind, file, or comment text. Read-only.
bumpit i18n
Two-way translation key audit. Checks for drift between your locale files and source code in both directions:
| Indicator | Meaning |
|---|---|
~ (orange) |
Key defined in a locale file but never called in source |
? (red) |
t('key') call in source with no matching key in any locale file |
The ~ direction surfaces dead translations you can safely delete. The ? direction catches typos and stale references — calls that will silently fall back to the raw key at runtime.
Locale file discovery. Scans all JSON files inside directories named locales/, locale/, i18n/, translations/, lang/, or langs/. Nested JSON objects are flattened to dot-notation keys (section.subsection.key). Multiple locale files are merged — a key is considered defined if it exists in any locale file.
Source reference detection. Matches t('key'), $t('key'), i18n.t('key'), and translate('key'). Bare t( calls require a non-identifier preceding character to avoid false positives from similarly-named functions. Works with Vue i18n, react-i18next, and most i18n libraries.
Limitations:
- Namespaced calls like
t('common:key')(react-i18next namespaces) are matched literally — the keycommon:keymust exist in the locale file as-is. - Dynamic keys (
t(\prefix.${var}`)`) cannot be statically resolved and are not detected.
Read-only.
bumpit env
Two-way .env.example audit. Checks for drift between your .env.example files and source code in both directions:
| Indicator | Meaning |
|---|---|
~ (orange) |
Variable defined in a .env.example file but never referenced in any source file |
? (red) |
Variable referenced in source but absent from every .env.example file |
The ~ direction surfaces stale env vars you can safely remove. The ? direction catches variables used in code that have no corresponding .env.example entry — potential configuration gaps.
Env file discovery. Scans .env.example, .env.sample, .env.template, .env.defaults, and .env.schema files across the project. Lines starting with # are treated as comments; export KEY=value syntax is also supported.
Source reference detection. Matches environment variable access patterns across multiple ecosystems:
- Node.js:
process.env.KEY,process.env['KEY'] - Vite / Astro:
import.meta.env.KEY,import.meta.env['KEY'] - Go:
os.Getenv("KEY") - Python:
os.environ["KEY"],os.environ.get("KEY") - YAML / shell:
${KEY}substitution (docker-compose, kubernetes manifests, shell scripts)
Limitations:
- Shell bare
$KEYreferences (without{}) are not detected — too noisy ($HOME,$PATH, etc. would produce false positives) - Dynamic key construction (
process.env[varName]) cannot be statically resolved
Read-only — bumpit env reports findings but does not modify any files.
Installation
Download a pre-built binary from the releases page:
| Platform | File |
|---|---|
| macOS (Apple Silicon) | bumpit_darwin_arm64.tar.gz |
| macOS (Intel) | bumpit_darwin_amd64.tar.gz |
| Linux x86-64 | bumpit_linux_amd64.tar.gz |
| Linux arm64 | bumpit_linux_arm64.tar.gz |
| Windows x86-64 | bumpit_windows_amd64.zip |
tar -xzf bumpit_darwin_arm64.tar.gz
mv bumpit /usr/local/bin/
Or install with Go:
go install github.com/marcelmettler/bumpit@latest
Or build from source:
git clone https://github.com/marcelmettler/bumpit
cd bumpit
go build -o bumpit .
Requires Go 1.22+. For npm packages, pnpm must be available in your PATH.
Usage
bumpit update
bumpit update
bumpit update /path/to/project
bumpit update --show-indirect # include indirect Go module dependencies
bumpit unused
bumpit unused
bumpit unused /path/to/project
bumpit license
bumpit license
bumpit license /path/to/project
Reads license data from local node_modules. Run after pnpm install for accurate results. Packages that are listed in package.json but not yet installed are shown with a ? indicator.
bumpit clean
bumpit clean
bumpit clean /path/to/project
bumpit css
bumpit css
bumpit css /path/to/project
bumpit todo
bumpit todo
bumpit todo /path/to/project
bumpit i18n
bumpit i18n
bumpit i18n /path/to/project
bumpit env
bumpit env
bumpit env /path/to/project
GitHub authentication
Changelogs are fetched from the GitHub API. Unauthenticated requests are limited to 60 per hour. bumpit automatically resolves credentials from your existing machine state — no setup required if you already use the GitHub CLI or have git configured with HTTPS:
GITHUB_TOKENenv varGH_TOKENenv vargh auth token— GitHub CLI credential storegit credential fill— system keychain (macOS Keychain, libsecret, etc.)
If none of the above are available, bumpit falls back to unauthenticated requests. For larger projects or private repos you can always set a token explicitly:
export GITHUB_TOKEN=ghp_...
bumpit
minimumReleaseAge
If your .npmrc contains:
minimum-release-age=3 days
Packages published less than 3 days ago will show ⏳ Nd left instead of a status. This matches pnpm's own behavior and gives the ecosystem time to catch regressions before you adopt a release.
How it works
bumpit update
- Detect — walks the directory tree to find
package.jsonandgo.modfiles - Fetch outdated — runs
pnpm outdated --jsonorgo list -m -u -json allper directory - Enrich — fetches publish date and repository URL from the npm registry for each package
- Changelogs — calls the GitHub releases API, filters to the relevant version range, and renders markdown in the terminal using glamour
- Audit — runs
pnpm audit --jsonin the background and annotates vulnerable packages - Update — runs
pnpm update --latest <pkg...>grouped by directory for monorepo correctness
bumpit unused
- Detect — same file discovery as
update - Scan imports — walks all
.js/.ts/.jsx/.tsx/.mjs/.cjs/.vue/.sveltesource files across the entire workspace root collectingimport/requirereferences - Scan scripts — checks
package.jsonscripts for package name references (catches CLI tools likeprettier) - Scan configs — reads
angular.json,nx.json,project.json,.eslintrc.json,.commitlintrc.jsonfor executor and parser strings - Ecosystem rules — applies per-ecosystem knowledge to skip packages that are used without being imported (build tools, type stubs, platform packages)
- Remove — runs
pnpm remove <pkg...>orgo get mod@none && go mod tidyfor selected packages
bumpit license
- Detect — same file discovery as
update - Read — for each direct dependency in each
package.json, reads the installednode_modules/<pkg>/package.json(checks package-local then workspace-root for hoisted deps) - Categorise — parses SPDX expressions including compound forms (
MIT OR GPL-3.0-or-later→ permissive,MIT AND GPL-3.0→ strong copyleft); maps to one of four risk categories - Deduplicate — packages that appear in multiple
package.jsonfiles across a monorepo are shown once - Display — default view shows only packages needing attention with plain-English action text; press
afor the full list
bumpit clean
- Scan — walks the directory tree; when a directory with a known artifact name is found, records it and skips descending into it (so nested
node_modulesinsidenode_modulesare not double-counted) - Size — computes total disk usage for each artifact directory
- Sort — biggest directories first, so the most impactful targets are immediately visible
- Delete —
Drunsos.RemoveAllon selected directories and reports total space freed
bumpit css
- Pass 1 (define) — walks all
.css/.scss/.sass/.lessfiles, strips comments andurl()references, extracts every.classnameselector. Skips.module.cssfiles and lines containing&. - Pass 2 (reference) — walks all template and source files; builds two sets:
broad(class attrs + string literals, for the~direction) andexplicit(class attrs only with file/line, for the?direction). String literals are excluded fromexplicitto avoid false positives from common English words. - Diff both ways —
~= defined in CSS but absent frombroad;?= present inexplicitbut absent from CSS definitions - Display — combined scrollable list sorted within each direction by file then line;
/to filter by name or file
bumpit todo
- Scan — walks all source files matching a broad extension list (
.go,.js/.ts,.vue,.svelte,.css/.scss,.html,.yaml,.sh, and more); skipsnode_modules,dist,.git, and other artifact directories - Match — per line, applies
\b(TODO|FIXME|HACK|XXX)\bregex; captures the text following the keyword, strips trailing comment closers (*/,-->) andTODO(author):prefixes - Display — read-only list sorted by file then line; color-coded by kind (
TODOblue,FIXME/HACKorange,XXXred);/filters by kind, text, or file
bumpit i18n
- Locale scan — walks all JSON files inside
locales/,i18n/,translations/,lang/directories; parses each withencoding/jsonand recursively flattens nested objects to dot-notation keys; deduplicates across multiple locale files - Source scan — walks
.js/.ts/.jsx/.tsx/.vue/.svelte/.htmlfiles line by line; applies two patterns:\$t|i18n\.t|translate(explicit) and[^a-zA-Z_$\d]t\s*\((baret()) for broad coverage - Diff both ways —
~= defined in locale but not in source refs;?= in source refs but absent from all locale files - Display — combined scrollable list (unused first, then undefined);
/filters by key or file
bumpit env
- Env file scan — walks all
.env.example,.env.sample,.env.template,.env.defaults, and.env.schemafiles; parses each line with^(?:export\s+)?KEY=regex; skips comments and blank lines - Source scan — walks
.js/.ts/.go/.py/.sh/.yamland related files; applies patterns forprocess.env.KEY,import.meta.env.KEY,os.Getenv("KEY"),os.environ["KEY"], and${KEY}YAML substitution - Diff both ways —
~= declared in.env.examplebut no matching access in source;?= accessed in source but absent from all env files - Display — combined scrollable list (unused first, then undefined);
/filters by variable name or file
Status indicators
| Indicator | Meaning |
|---|---|
⚠ Breaking |
Release notes contain breaking change markers |
⏳ Nd left |
Published too recently — below minimumReleaseAge |
✓ OK |
No breaking changes detected, age requirement met |
… |
Changelog is still loading |
Update kinds
| Badge | Meaning |
|---|---|
MAJOR (red) |
Breaking semver bump — review carefully |
minor (yellow) |
Backwards-compatible new features |
patch (green) |
Bug fixes only |
Contributing
Bug reports and pull requests are welcome. For significant changes, open an issue first to discuss the approach.
git clone https://github.com/marcelmettler/bumpit
cd bumpit
go build -o bumpit .
go test ./...
Set BUMPIT_DEBUG=1 to write a trace log to /tmp/bumpit-debug.log:
BUMPIT_DEBUG=1 bumpit update
License
Documentation
¶
There is no documentation for this package.