The syntax, every option, more examples, and the output formats and exit codes of depup. How depup chooses versions is explained in the Usage Guide.
depup [OPTIONS] [PATH]PATH is the directory to process (defaults to the current directory). With --cd, depup changes to that directory first and resolves PATH from there.
| Option | Short | Description |
|---|---|---|
--cd <DIR> |
-C |
Change to directory before running |
--dry-run |
-n |
Show what would be updated without making changes |
--verbose |
Enable verbose output | |
--quiet |
-q |
Minimal output |
--node |
Update only Node.js dependencies | |
--python |
Update only Python dependencies | |
--rust |
Update only Rust dependencies | |
--go |
Update only Go dependencies | |
--ruby |
Update only Ruby dependencies | |
--php |
Update only PHP dependencies | |
--java |
Update only Java dependencies | |
--swift |
Update only Swift dependencies | |
--mise |
Update only mise tool versions (mise.toml / .tool-versions) | |
--exclude <PKG> |
Exclude specific packages (repeatable) | |
--only <PKG> |
Update only specific packages (repeatable) | |
--include-pinned |
Include pinned versions in update | |
--age <DURATION> |
Minimum release age (e.g., 2w, 10d, 1m). Overrides global config | |
--no-age |
Disable age filter for this run (overrides global config and default, but not a project minimumReleaseAge) |
|
--osv |
Check OSV.dev and prefer versions without known vulnerabilities; allow updates that fix existing vulnerabilities under severity and count limits by default | |
--no-osv |
Disable OSV vulnerability check for this run (overrides global config and default) | |
--no-osv-risk-tradeoff |
Reject every candidate with known vulnerabilities for this run, even if it fixes existing vulnerabilities | |
--max-change <LEVEL> |
Limit allowed bumps: patch (patch only), minor (patch + minor), major (default — all) |
|
--json |
Output results in JSON format | |
--diff |
Show changes in diff format | |
--install |
Run package manager install after update | |
--refresh-lock |
Re-resolve pnpm/Cargo lockfiles, including transitive dependencies; requires --install; incompatible with --only, --exclude, and --max-change (including global defaults) |
|
--version |
-V |
Show version |
--help |
-h |
Show help |
When --only is present, it takes precedence over --exclude. This lets an explicit allow-list entry remain updatable even if the same package also appears in a broader exclude list.
# Preview all updates
depup -n
# Update only lodash and typescript
depup --only lodash --only typescript
# Exclude react from updates
depup --exclude react
# --only takes precedence if the same package is also excluded
depup --only lodash --exclude lodash
# Only update to versions at least 2 weeks old
depup --age 2w
# Update Python and Rust only
depup --python --rust
# Update Java (Gradle) dependencies
depup --java
# Update Swift (Package.swift) dependencies
depup --swift
# Update mise tool versions (mise.toml / .tool-versions)
depup --mise
# JSON output for CI/CD
depup --json
# Update, then run the package manager install (npm install, etc.)
depup --node --install
# Run in a different directory
depup --cd ./projects/myapp -n🔧indicates development dependencies (such as devDependencies)- Known release dates are shown in
(yyyy/mm/dd HH:MM)format; unavailable dates appear as(release date unknown) - Change type:
[major],[minor],[patch] ✓ OSVmarks versions with no known OSV advisories. Updates allowed with remaining vulnerabilities carry no such mark. Normal text shows the fixed, introduced, and retained issue counts and warns that known vulnerabilities remain;--verboseadds all advisory IDs and severities. Canceled candidates saycandidate not appliedonly when recovery completed; otherwise their installed state is reported as unverified. JSON retains the fullosv_risk_tradeoffobject withbaseline_versions,candidate_versions,fixed,introduced, andretainedarrays, each issue group having deduplicatedidsand a normalizedseverity. The short↳ OSV:line counts excluded candidates;--verboseshows their versions and advisory IDs under↳ OSV skipped:.- When OSV excludes every eligible update, the reason is
no eligible update without known vulnerabilities. Normal output includes the manifest baseline's vulnerability status and, when confirmed, a safe newer version with its age eligibility time. JSON includes this skip with reasonknown_vulnerabilitiesand structuredosvdetails even without--verbose. Cargo age rollback notices also flag vulnerable destinations remaining in the final lockfile; these notices do not change the exit code - Skipped dependencies are counted in each manifest heading (
— N updates, M skips) and in the summary; a manifest with no updates also shows the count per reason - Failed updates are not counted as updates: the heading becomes
— N updates, K failed, M skips, and the summary addsK package(s) failed to update. In normal text output, updates in the same manifest with identical failure reasons share a numberedFailure #N (K packages)explanation above the update rows. The full reason, including advisory IDs, wraps at whitespace to fit 100 characters where possible. Each affected row refers to that explanation with✗ failed: #N([failed: #N]without color). Only the first three rows per reason are shown, followed by the omitted count and a--verbosehint; rows with individual OSV or age-exemption diagnostics remain visible. Single failures keep their reason inline, with multiline whitespace collapsed. --verboselists every failed update with its full reason inline. JSON always retains every failed update and its original reason, regardless of text grouping.- Updates canceled together after an install or lock verification failure are counted as
canceledin text, separately from individual write failures. The recovery report on stderr shows the cause, scope, restored or kept files, recovery outcome, and next action. Normal output refers to that report instead of repeating the cause and every canceled package;--verboselists every canceled update and its full reason. Installed artifacts are retained, and incomplete recovery requires manual review before running the package manager. For compatibility, JSON and diff output continue to include cancellations infailed; exit codes are unchanged. - With
--verbose, every skipped dependency is listed under its reason, and the summary is broken down by reason and language - The
latestandnewer than --ageskip groups show the current version's own publication date when confirmed. Unknown dates and floating wildcard/prefix specifications have no date.newer than --agemeans the current release is too young for the effective age policy and is not publisher-exempt; it does not downgrade the dependency Errors:lists errors that affect the exit code. OSV lookup failures and final-lock trade-offs appear underWarnings:; rejected vulnerable candidates appear underNotices:. Normal output summarizes candidate rejections, while--verboseincludes every version and advisory ID. Progress-time OSV details are deferred to the final report in normal text mode; quiet, diff, JSON, and verbose modes retain stderr diagnostics. JSON keeps all OSV diagnostics in its existingerrorsarray.
With --refresh-lock, lock_refreshes reports each lock scope's directory, language, status (completed, failed, or unsupported), changed, and error. changed means an accepted refresh changed the lock; a failed refresh has changed: false, including when an external edit prevents recovery. If no eligible scope exists, language is null. A pnpm scope stopped by the preflight (for example, an existing lockfile that violates the age policy) is not refreshed; it is reported as failed with the preflight reason in error. Direct dependency counts retain their existing meaning. A Cargo refresh can be completed while the command exits with code 2 when only pre-run versions remain outside the age policy. See Refreshing Lockfiles for verification and recovery.
With --json --install, output is deferred until install recovery and age audits finish, then one JSON value is flushed even if install fails. Updates canceled by a failed project, including recovery conflicts and lock-only Git updates, move from updates to failed with a reason. Successful independent projects remain in updates. Recovery details and copy locations go to stderr.
depup --json{
"dry_run": false,
"summary": {
"updates": 1,
"failed": 1,
"skips": 1
},
"manifests": [
{
"path": "./package.json",
"language": "Node.js",
"updates": [
{
"name": "lodash",
"kind": "registry",
"from": "4.17.20",
"to": "4.17.21",
"dev": false
}
],
"failed": [
{
"name": "react",
"kind": "registry",
"from": "18.0.0",
"to": "19.2.0",
"dev": false,
"error": "Refusing to update ambiguous dependency 'react' because it has multiple declarations or a shared version target"
}
]
}
],
"errors": [
"Failed to write ./package.json: Refusing to update ambiguous dependency 'react' because it has multiple declarations or a shared version target"
]
}summary.updates and each manifest's updates cover only the updates that were written (with --dry-run, the updates that would be written). Updates that could not be written are counted in summary.failed and listed in the manifest's failed array, with the reason in error. Git dependencies use "kind": "git" and add source (the repository URL with any credentials masked) and reference. With --verbose, each manifest also lists its skips, and the summary adds by_language.
Verbose skip entries use reason: "current_version_too_recent" when the confirmed current release is younger than the effective age policy and no update is selected. Other filters and errors keep their own reasons. This replaces already_latest for those age cases and also applies to the default and configured age values. Skip released_at belongs to the current release, rather than the latest eligible candidate; it is omitted when unknown or when the specification does not identify one release. For example:
{
"name": "library",
"version": "2.0.0",
"reason": "current_version_too_recent",
"released_at": "2024-05-30T12:00:00+00:00"
}The reporting rules and other skip reasons are described in When a Dependency Is Not Updated.
depup --diff--- a/./package.json
+++ b/./package.json
@@ lodash @@
- "lodash": "^4.17.20"
+ "lodash": "^4.17.21"
# 1 package(s) would be updated, 1 failedUpdates that could not be written get no hunk. The last line counts updates the same way as the text and JSON output, and adds , K failed only when some updates could not be written.
| Code | Meaning |
|---|---|
0 |
No failures. This includes runs with no updates, dry runs, and runs whose only diagnostics are candidate OSV notices or warnings (fallbacks, permitted trade-offs, or failed lookups). Final lock verification of retained vulnerabilities is an exception described below. |
1 |
A package manager install failed or could not be prepared (whether or not its recovery completed), --cd could not change the directory, or depup itself could not continue (for example, the HTTP client failed to initialize, or the results or the recovery report could not be written). |
2 |
Part of the run failed: a manifest could not be read, parsed, or written (including a refused ambiguous write), a registry lookup failed, or a Rust or Node lockfile age audit left violations or unverified entries (including an unreadable lock or an exhausted time budget). This includes --install runs that restored a unit because a version they added failed the audit, even when some files were kept for manual recovery. Invalid command-line arguments also exit with 2. |
A code-2 failure does not stop the run. A failed lookup skips that dependency, and a manifest that cannot be read or parsed is left out; everything else is still written and installed. If a file cannot be saved, it keeps its original content. If only some updates in a manifest cannot be written (for example, one refused as ambiguous), the rest are still saved. Either way, the updates that could not be written are reported as failed instead of updated, and they do not make --install run. With --install, when a version this run added to a lockfile fails the age audit, the manifests and lockfiles of that install unit are restored to their state before the run and its updates are reported as failed (see When the Final Lockfile Fails the Age Audit). When both 1 and 2 apply, 1 wins.
Final OSV lock verification exits with code 2 when a changed package retains vulnerable pre-run versions alongside new advisory-free versions. Updates remain applied; the warning identifies only the affected pre-run versions and suggests --install --refresh-lock for pnpm/Cargo. This differs from permitted severity trade-offs and candidate lookup warnings, which do not change the exit code. The JSON errors array retains the warning text.
These lookup problems leave the exit code unchanged:
- A failed
git ls-remotefor a Cargo git dependency (the dependency is skipped) - A registry that returns no usable versions (
fetch failed: no versions available) - A missing
misecommand (mise config files are ignored with a warning)
There is no dedicated code for "updates available"; use --json to inspect the result in CI.
Errors are listed in the Errors: section of the text output and in the errors array of the JSON output. With --diff, or with --quiet in text output, the list is not printed unless --verbose is also given (it then goes to stderr), so check the exit code to detect failures.
