(/ta:zei/, fresh in Persian)
A modern cli tool that keeps your deps fresh
npx taze
or recursively for monorepos
npx taze -r
or for agents to consume
npx taze -r --json
- Built-in support for monorepos
- No installation required —
npx taze - Safe by default — updates in the version range you are allowed
- Interactive mode to select which packages to update
- Respects
package.json'senginesfield and your package manager's config - Updates GitHub Actions in your workflows, with optional SHA pinning
- Updates the Node.js version pinned in
.node-versionand.nvmrc - Agents compatible JSON output
By default, taze will only bump versions in the ranges you specified in package.json (which is safe and the default behavior of npm install)
To ignore the ranges, explicitly set the maximum allowed version change.
For example taze major will check all changes and bump to the latest stable changes including majors (breaking changes), or taze minor that bump to latest minor changes within the same major version.
taze has the built-in first-class monorepo support. Simply adding -r will scan the subdirectories that contain package.json and update them together. It will handle local private packages automatically.
See taze --help for more details
You can filter out packages you want to check for upgrades by --include or --exclude; they accept string and regex, separated by commas (,).
taze --include lodash,webpack
taze --include /react/ --exclude react-dom # regex is also supported--exclude (and --include) also accepts a name@range selector to exclude only a specific version range of a package, instead of the whole package. This is useful to block a specific major version while still allowing other updates (including in interactive mode):
# skip typescript's major v7 (and later), but still offer v6 minor/patch updates
taze --exclude typescript@7
taze --exclude "typescript@^7||^8" # multiple ranges can be combined with ||Dependencies listed in pnpm's update.ignoreDeps in pnpm-workspace.yaml are automatically excluded, so packages you tell pnpm never to update are also skipped by taze.
Locked (fixed version without ^ or ~) packages are skipped by default, use taze --include-locked or taze -l to show them.
Bumping version in peerDependencies is not enabled by default. Pass --peer option to include them in the update process.
taze --peerBy default the most recent version of a dependency is used. You may choose to filter to versions that have been out longer by passing --maturity-period.
taze --maturity-periodThe filter when using the maturity-period flag is 7 days. You may also want to pass a day value to have a longer or shorter number of days.
taze --maturity-period 14You can exclude packages from the maturity filter. This is also inferred from package manager config when available, such as minimumReleaseAgeExclude in pnpm-workspace.yaml and npmPreapprovedPackages in .yarnrc.yml.
taze --maturity-period-exclude react,webpackIf you want stable releases only while still honoring the maturity period, use stable mode.
taze stable --maturity-period 14Note
This kind of filtering is sometimes called cooldown or minimumReleaseAge by other tools.
Pass --json to output the resolved update info as JSON to stdout instead of the rendered table. This is handy for scripting and CI.
taze --jsonWhen --json is used, --interactive is ignored and no progress bars, tables, or tips are printed. By default only dependencies with an available update are included; combine it with --all to include up-to-date dependencies too. It can still be combined with -w to write the changes back to package.json.
taze also checks the GitHub Actions used in your workflows. When a .github/workflows directory exists, it scans .github/workflows/*.{yml,yaml}, composite actions (.github/actions/**/action.{yml,yaml} and a repo-root action.{yml,yaml}), and reusable workflow calls, then reports newer versions alongside your npm dependencies. It works with every mode (major, minor, ...), --interactive, --json, and -w.
taze major -w # also updates outdated actions, e.g. actions/checkout@v3 -> @v4
taze --no-github-actions # opt outReferences are updated in place while preserving the granularity you wrote (@v4 → @v5, @v4.1.1 → @v4.2.0). By default the existing style of each action is kept: tag references stay tags, while SHA-pinned references stay pinned (with a refreshed # vX.Y.Z comment). Choose a style explicitly with --github-actions-style <auto|tag|sha>:
# style: sha — pin to an immutable commit for supply-chain safety
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# style: tag
- uses: actions/checkout@v5Only v-prefixed version tags are considered; branch refs (@main), non-v tags, docker:// and local (./) actions are left untouched. Filtering (--include/--exclude/packageMode), the maturity-period cool-down, and mode all apply, matched by the action's owner/repo name.
Versions are fetched from the GitHub REST API. Set a GITHUB_TOKEN (or GH_TOKEN) to raise the rate limit from 60 to 5000 requests/hour:
GITHUB_TOKEN=xxxx taze majorIf neither is set, taze falls back to a token from the GitHub CLI (gh auth token) when you're logged in, so an authenticated gh needs no extra configuration.
taze checks JSR dependencies alongside your npm ones. Both ways of declaring a JSR package are supported:
jsr: specifiers are resolved against the JSR registry (yanked versions are skipped) and written back in place preserving the jsr: prefix. All modes, filtering, and -w apply as usual.
taze also keeps the Node.js version pinned in .node-version, .nvmrc, and a package.json devEngines.runtime entry fresh. It checks these files in the current directory, and with -r it discovers nested ones too (honoring ignorePaths); a neighboring package.json is not required for the .node-version / .nvmrc files.
taze # stay on the current Node.js major
taze patch # stay on the current major and minor
taze major -w # allow a newer major and write the file
taze --no-node-version # opt outIn .node-version / .nvmrc only stable numeric references with an optional v prefix are recognized (22, 22.14, v22.14.0); aliases (lts/*, node), ranges, and prereleases are left untouched. The written reference keeps the shape you had — a major-only 22 stays major-only, and the v prefix, surrounding whitespace, and any comments/blank lines are preserved.
A devEngines.runtime pin whose name is node is instead treated as a semver range and rewritten in place, preserving the range operator (>=20 → >=26.7.0, ^20.0.0 → ^20.20.2); runtime may be a single object or an array (only the node entry is touched).
Releases and their dates come from the official Node.js distribution index, so maturityPeriod and version-specific exclusions apply here too. Filtering uses the dependency name node (--include node, --exclude node, packageMode.node), and --no-node-version / nodeVersion: false opts out of all of the above. Writing the files does not install or switch the active Node.js runtime.
With taze.config.js file, you can configure the same options the command has.
import { defineConfig } from 'taze'
export default defineConfig({
// ignore packages from bumping
exclude: [
'webpack'
],
// fetch latest package info from registry without cache
force: true,
// use a custom fast-npm-meta compatible API endpoint
fastNpmMetaApiEndpoint: 'https://npm.example.com/',
// retry behavior when fetching package metadata fails:
// a number for retry count, `false` to disable, or an object for fine-grained
// control, e.g. { retries: 4, factor: 2, minTimeout: 1000, maxTimeout: 30_000, randomize: false }
retry: 4,
// write to package.json
write: true,
// run `npm install` or `yarn install` right after bumping
install: true,
// ignore paths for looking for package.json in monorepo
ignorePaths: [
'**/node_modules/**',
'**/test/**',
],
// ignore package.json that in other workspaces (with their own .git,pnpm-workspace.yaml,etc.)
ignoreOtherWorkspaces: true,
// override with different bumping mode for each package
packageMode: {
'typescript': 'major',
'unocss': 'ignore',
// regex starts and ends with '/'
'/vue/': 'latest'
},
// exclude packages from the maturity period filter
maturityPeriodExclude: [
'react',
'@myorg/*',
],
// disable checking for "overrides" package.json field
depFields: {
overrides: false
},
// GitHub Actions updates: `true` (default) | `false` to opt out | options object
githubActions: {
// 'auto' (preserve existing style) | 'tag' | 'sha'
style: 'auto'
},
// `.node-version` / `.nvmrc` updates are enabled by default; `false` to opt out
nodeVersion: true
})taze discovers, reads and writes each kind of dependency file through a
Manifest (package.json, package.yaml, pnpm/bun/yarn catalogs, GitHub
workflows). You can register your own to support extra file types, via the
manifests option in your config or programmatically. Custom manifests are
merged ahead of the built-ins, so they can also override how an existing file
type is handled.
import type { Manifest } from 'taze'
import { defineConfig } from 'taze'
const myManifest: Manifest = {
name: 'my-manifest',
type: 'my-manifest',
// glob/find the files this manifest owns
discover: async () => ['my-deps.json'],
// claim a discovered file (receives the absolute path)
match: filepath => filepath.endsWith('my-deps.json'),
// parse it into one or more packages of dependencies
async load(relative, options, shouldUpdate) {
return [/* PackageMeta[] */]
},
// write the resolved updates back
async write(pkg, options) {},
}
export default defineConfig({
manifests: [myManifest],
})Only available from a JS/TS config file or programmatically, not from
.tazerc.json.
taze is inspired by the following tools.
They work well but have different focuses and feature sets, try them out as well :)
Great thanks to @sinoon who helped a lot with idea brainstorming and feedback discussion.
The GitHub Actions updating feature is inspired by and credits actions-up by Azat S., which pioneered the interactive SHA-pinning workflow this builds upon.
MIT License © 2020 Anthony Fu






{ "dependencies": { // native jsr: protocol (pnpm / deno) — versions come from jsr.io "@std/cli": "jsr:^1.0.0", // npm-compat form written by `npx/bunx jsr add` — needs `@jsr:registry=https://npm.jsr.io` in .npmrc "@std/encoding": "npm:@jsr/std__encoding@^1.0.0" } }