EPISODE 01 — OPERATION NODE_MODULES

dep-upsurgeon

Upgrade npm, pnpm & yarn deps one-by-one — with pre-flight + install + validation, automatic rollback, a peer-range resolver that backtracks through the packument (SAT / AC-3 for big graphs), --security-only with transitive + parent-scoped overrides, --fix-lockfile dedupe, breaking-change radar, policy-as-code, atomic git commits, auto-opened PRs, and undo + doctor subcommands.

$npm install -g dep-up-surgeon

▸ framework-agnostic · peerDeps graph · peer resolver · monorepo-ready · ci-mode · security-first · policy-as-code · auto-PR · undo · doctor · node 20.17+ / 22.9+

Anime surgeon mascot holding an npm syringe
v2.2.8
NO PATIENTS HARMED ✦
ROLLBACK ✓
◉ ONE-BY-ONE UPGRADES✚ INSTALL + VALIDATE⚕ PRE-FLIGHT CHECK⟲ AUTO ROLLBACK◇ PEER-GRAPH BATCHING⛁ WORKSPACE-AWARE⇉ PARALLEL TARGETS⛨ NPM · PNPM · YARN⚠ CONFLICT REPORTING☰ JSON + LAST-RUN↻ --RETRY-FAILED▤ MD/HTML SUMMARY⎇ GIT AUTO-COMMITS◎ CI / PR-BOT MODE★ INTERACTIVE RECOVERY⛯ FRAMEWORK-AGNOSTIC❖ SECURITY-FIRST MODE◩ TRANSITIVE OVERRIDES⚡ BREAKING-CHANGE RADAR⌖ BLAST RADIUS§ POLICY ENGINE✎ CHANGELOG EXCERPTS⇢ AUTO-OPEN PR◉ ONE-BY-ONE UPGRADES✚ INSTALL + VALIDATE⚕ PRE-FLIGHT CHECK⟲ AUTO ROLLBACK◇ PEER-GRAPH BATCHING⛁ WORKSPACE-AWARE⇉ PARALLEL TARGETS⛨ NPM · PNPM · YARN⚠ CONFLICT REPORTING☰ JSON + LAST-RUN↻ --RETRY-FAILED▤ MD/HTML SUMMARY⎇ GIT AUTO-COMMITS◎ CI / PR-BOT MODE★ INTERACTIVE RECOVERY⛯ FRAMEWORK-AGNOSTIC❖ SECURITY-FIRST MODE◩ TRANSITIVE OVERRIDES⚡ BREAKING-CHANGE RADAR⌖ BLAST RADIUS§ POLICY ENGINE✎ CHANGELOG EXCERPTS⇢ AUTO-OPEN PR
// FILE 01 — LIVE DEMO

operation log

A real session: plan → install → validate → rollback on trouble. Hit refresh to replay the surgery.

REC ● LIVE OP
CRT-OS v2.2.8
/dev/tty1
▸ POWER▸ V-HOLD
■ dep-up-surgeon
// FILE 02 — TOOLKIT

Sticker-pack features

Peel, slap onto your CI pipeline, press firmly. Twenty-nine capabilities in one binary — workspace-aware, git-aware, CI-aware, policy-aware, security-aware, PR-aware, and with undo + doctor subcommands for disaster recovery and pre-flight diagnostics. No plugins, no bolt-ons, no framework lock-in.

Surgical one-by-one

Every upgrade is its own operation: bump → install → validate. If a patch fails, package.json is restored from backup. No mass updates, no mystery regressions.

/core/retryEngine.ts

Peer-graph batching

With --link-groups auto, the tool reads each package's published peerDependencies and builds a graph. Connected components become one batch → one write → one install → one validation. @types/* pair with their runtime automatically.

/core/graph.ts

Pre-flight check

Before mutating any dependency, the resolved validator runs once on the unchanged tree. If the project build was already broken, the run aborts with the validator command, exit code, and last ~40 lines — instead of pretending every rollback is a real conflict.

preflight in --json

Generic conflict parser

A regex-based parser classifies peer mismatches, missing peers, engine bumps, and unresolved trees — from real npm / pnpm / yarn output. Root-only mentions get filtered so your own app never looks like a conflict.

/core/conflictParser.ts

Workspaces & monorepos

--workspaces traverses the root + every member; --workspace <names> picks specific packages. Install + validation run from the workspace root so the lockfile is always coherent. --install-mode filtered uses npm install --workspace, pnpm --filter, or yarn workspaces focus when available.

--workspaces · --install-mode

Parallel target traversal

--concurrency up to 16 overlaps registry scan + plan across workspace targets while a shared mutex keeps install + validation strictly serialized — your shared lockfile is never raced. An in-process manifest cache deduplicates pacote calls across the whole run.

--concurrency <n>

Fallback strategies

@latest first, then walk back: major-lines (default) tries the best stable per major; minor-lines steps by major.minor. ERR_REQUIRE_ESM halts further tries for that package. Set none to lock to @latest only.

--fallback-strategy

Auto package-manager

Detects npm / pnpm / yarn from the packageManager field, then the lockfile, then pnpm-workspace.yaml. The chosen manager drives both install and the default validator (<mgr> test → <mgr> run build). Yarn berry capabilities are auto-probed for filtered installs.

--package-manager auto

Interactive recovery

--interactive splits prompts by phase. Linked-group conflict: skip group / retry / force / freeze-all. Single-package failure: continue / pin / retry. After the run, optionally bulk-add every failed name to the .dep-up-surgeonrc ignore list so the next pass converges.

/cli/interactive.ts

JSON report + last-run

--json emits one structured object: upgraded, skipped, failed, conflicts, groups, project, targets, installMode, concurrency, commits. Persisted to .dep-up-surgeon.last-run.json next to the workspace root for CI dashboards and --retry-failed.

--json · last-run.json

Resume with --retry-failed

Reads the persisted last-run report and only re-attempts non-terminal residue (install / validation / validation-conflicts). Successful upgrades and terminal failures (peer, validation-script) are auto-frozen so the next pass converges instead of looping.

--retry-failed

Summary writer

--summary md|html renders Upgraded / Failed tables, pre-flight status, ignored list, and target counts. On GitHub Actions it's appended to $GITHUB_STEP_SUMMARY automatically — perfect for PR-bot diagnostics without extra workflow plumbing.

--summary <md|html>

Git auto-commits

--git-commit lands every successful upgrade as its own atomic commit (per-success / per-target / all). Only stages package.json + the lockfile — never git add -A — so prepare/postinstall side effects stay uncommitted. Pair --git-branch + --git-sign for review-ready PR-bot runs.

--git-commit · --git-branch

CI / PR-bot mode

--ci disables --interactive, auto-enables --summary md, and remaps the exit code: per-package failures stay green so your bot's PR carries the diagnostic. Pre-flight + fatal errors still exit 1 — those mean a human needs to look.

--ci

Safety-first rollback

Before the first change, package.json is copied to package.json.dep-up-surgeon.bak. Even when the installer exits 0 but the log is full of conflicts, the bump is rolled back — unless you --force it. A failed git commit never rolls back the upgrade.

safety rail

Framework-agnostic

No hardcoded React / Angular / Vue / Expo lists. Grouping and conflict handling come from registry metadata and parsed installer output. Custom batches via .dep-up-surgeonrc linkedGroups when the registry graph is invisible.

zero stack lock-in

Security-first mode

--security-only flips the tool into CVE-driven mode. It runs npm/pnpm/yarn audit, filters by --min-severity, then upgrades only the vulnerable names. Every bump carries its advisory ID + severity into commit subjects ([security:high]) and into a dedicated Security fixes table in --summary.

--security-only · --min-severity

Transitive overrides

--apply-overrides pins vulnerable transitives no direct bump could reach — writes overrides (npm 8.3+), pnpm.overrides (pnpm), or resolutions (yarn). --override accepts manual parent-scoped pins (some-dep>foo@1.2.3 / parent/child@1.2.3) and works standalone. Install + validator run after each pin; failures are rolled back per-slot so one bad pin never strands the rest.

--apply-overrides · --override

Peer-range resolver

When a linked-group bump hits a peer conflict, the resolver reads every member's published peerDependencies and backtracks to the newest tuple that satisfies them all. Graphs of 10+ members switch to a SAT-style AC-3 solver; single-package failures synthesize an ad-hoc group from direct-dep blockers. --no-resolve-peers restores the old fail-fast behavior.

--resolve-peers · default on

Disaster recovery (undo)

dep-up-surgeon undo replays the last-run report in reverse: writes every recorded from back to package.json, drops (or restores) every override it added, then runs install + validator so you see green/red before you commit. Drift-protected — deps that moved since the run are skipped as 'drifted' instead of being rewritten.

dep-up-surgeon undo

Doctor subcommand

dep-up-surgeon doctor is a read-only green / yellow / red pre-flight: Node engine match, manager resolution, lockfile parse, workspace coherence, policy parse, validator pre-flight, peer-dep scan, audit severity breakdown, and stale-transitive scan. Exit 2 on any red, 1 on yellow under --strict. The CI gate you run before trusting the upgrade loop.

dep-up-surgeon doctor

Lockfile fix + stale scan

--fix-lockfile runs `npm dedupe --no-audit --loglevel error` / `pnpm dedupe` / `yarn dedupe` (berry only) to collapse redundant copies without touching package.json, and flags transitives more than a minor or full major behind latest (top 250 by installed-copy count). Lockfile is snapshotted first — restored on dedupe or post-dedupe validator failure. Yarn classic → skipped:"unsupported"; missing lockfile → skipped:"no-lockfile".

--fix-lockfile

Parallel installs

In an isolated-lockfile monorepo (pnpm shared-workspace-lockfile=false in .npmrc, or per-member lockfiles) installs + validation run in parallel too — the keyed async mutex unlocks different-dir operations while same-dir ones still serialize. Auto-detected and reported as project.isolatedLockfiles + project.isolatedLockfilesSource ('pnpm-npmrc' | 'per-workspace-lockfiles') + top-level parallelInstalls in --json. --no-parallel-installs forces the serialized path.

--no-parallel-installs

Breaking-change radar

Every fetched changelog is scanned for breaking-change markers: Conventional-Commit footers, 💥 / ⚠ BREAKING emoji, Node-version drops, API removals. Matches add a [breaking] tag to the commit subject, a Breaking changes detected section to the body, and a prominent banner above the --summary upgraded table.

auto when --changelog on

Blast radius

Before you hand the PR to a reviewer, --blast-radius scans your source (.ts/.tsx/.js/.jsx/.mjs/.cjs/.mts/.cts/.vue/.svelte/.astro) to list which files actually import each upgraded package. Word-boundary safe. Surfaces as collapsible per-package lists in --summary and upgraded[].blastRadius in --json.

--blast-radius · default on
§

Policy engine

Drop a .dep-up-surgeon.policy.yaml in the repo and encode upgrade rules that survive runs: freeze patterns (wildcards like @types/* supported), maxVersion semver caps, allowMajorAfter date gates, requireReviewers / autoMerge metadata for your PR bot. Every applied rule appears in --summary and under policy.* in --json.

policy-as-code

Changelog excerpts

Every successful upgrade is annotated with release notes (GitHub Releases API first, then the package's CHANGELOG.md from its tarball). Embedded in commit bodies and rendered as collapsible <details> blocks in --summary. Set GITHUB_TOKEN / GH_TOKEN to lift the API rate limit from 60/h to 5000/h.

--changelog · default on

Auto-open PR

--open-pr closes the loop: after --git-commit --git-branch pushes the branch, it pipes the --summary markdown to gh pr create --body-file -. Reuses existing PRs for the same head. --open-pr-draft for merge-queue safety, --open-pr-reviewers / --open-pr-assignees / --open-pr-base for team wiring. Never fatal — a missing gh never aborts the run.

--open-pr · gh CLI

Live progress

TTY-aware spinner (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏) with (Ns) / (NmNs) elapsed timer on the pre-flight, single-package, and linked-group phases. Status flips through Installing … → Validating <cmd> … → Rolling back … as the engine moves. Non-TTY / CI degrades to plain › … log lines; --json and --ci suppress the spinner entirely so machine-parseable output stays clean. Auto-disabled when --concurrency > 1 in non-JSON mode so per-target lines never interleave.

/utils/logger.ts
Chibi surgeon mascot holding a pkg floppy disk
✦ KAWAII MODE ✦
READY TO OPERATE
// FILE 03 — INSTALL

Scrub in,
let's operate.

Install globally or run locally after cloning. From your project root (where package.json lives), call the CLI — optionally with --dry-run first.

▸ 01 — global install
$npm install -g dep-up-surgeon
▸ 02 — plan only (no writes)
$dep-up-surgeon --dry-run --json
▸ 03 — real surgery
$dep-up-surgeon --link-groups auto --fallback-strategy major-lines
▸ 04 — monorepo, parallel scan, atomic commits
$dep-up-surgeon --workspaces --concurrency 4 --json --git-commit
▸ 05 — CI / PR-bot (stays green, writes step summary)
$npx dep-up-surgeon --workspaces --ci --git-commit
▸ 06 — resume only the residue from the last run
$dep-up-surgeon --retry-failed --json
▸ 07 — CVE-driven: bump only vulnerable packages (+ transitive overrides)
$dep-up-surgeon --security-only --min-severity high --apply-overrides
▸ 08 — weekly security sweep → branch → draft PR with summary
$dep-up-surgeon --workspaces --security-only --apply-overrides --git-commit --git-branch deps/security --open-pr --open-pr-draft
▸ 09 — full PR-bot flow with reviewers (policy-aware)
$npx dep-up-surgeon --workspaces --ci --git-commit --git-branch deps/weekly --summary md --open-pr --open-pr-reviewers alice,bob
▸ 10 — pre-flight diagnostic (read-only, CI-gate friendly)
$npx dep-up-surgeon doctor --strict --json
▸ 11 — manual parent-scoped pin (no --security-only needed)
$dep-up-surgeon --override "some-dep>lodash@4.17.21" --override "axios@1.6.0"
▸ 12 — collapse redundant transitives (no package.json diff)
$dep-up-surgeon --fix-lockfile --summary md
▸ 13 — disaster recovery: replay the last run in reverse
$dep-up-surgeon undo
// .dep-up-surgeonrc
{
  "ignore": ["some-legacy-package"],
  "linkedGroups": [
    {
      "id": "my-batch",
      "packages": ["package-a", "package-b"]
    }
  ],
  "validate": "tsc -p tsconfig.json --noEmit",
  "overrides": [
    {
      "chain": ["some-dep", "foo"],
      "range": "1.2.3",
      "reason": "CVE-2025-1234"
    },
    {
      "selector": "lodash@4.17.21",
      "reason": "awaiting upstream PR #42"
    }
  ]
}
▸ validate accepts a string, { command: "..." }, or { skip: true } · overrides merge with --override CLI flags (CLI wins on chain conflict) · reason flows into --summary + report
# .dep-up-surgeon.policy.yaml
freeze:
  - pattern: react
    reason: "pinned until Q3 refactor"
  - pattern: "@types/*"
maxVersion:
  - pattern: next
    range: "<=14"
allowMajorAfter:
  - pattern: eslint
    date: "2026-06-01"
requireReviewers: 2
autoMerge: false
▸ policy-as-code · freeze wins · maxVersion caps · allowMajorAfter date-gates majors
// FILE 04 — FLAG DOSSIER

Flag reference

The full control panel — 53flags & subcommands across eight sections: core run control, validation, workspaces, reports & CI, git integration, security-first mode, PR automation, and the read-only doctor / undo subcommands. Exit code 1 when any upgrade could not be kept (unless --force) or when the pre-flight validator fails. Under --ci, per-package failures stay green.

// SECTION A

Core run control

8 flags
--dry-run
Resolve latest versions and print the plan. Does not touch package.json or run installs. Pairs beautifully with --json in CI.
--interactive
On failure, prompts for next steps. Single-package: continue / pin / retry. Linked-group: skip / retry / force / freeze. Optionally bulk-adds failed names to .dep-up-surgeonrc.
--forcesharp
Keep a bump even when validation fails, and skip rollback when structured conflicts appear after a successful exit code. Use with care.
--ignore<pkg,pkg,...>
Comma-separated package names to skip. Merged with the ignore list from .dep-up-surgeonrc.
--jsonci-ready
Machine-readable report to stdout. Top-level keys: upgraded, skipped, failed, conflicts, unresolved, groups, ignored, project, targets, installMode, concurrency, parallelInstalls, commits, gitCommitMode, preflight, preflightAborted, policy, overrides, pullRequest, lockfileFix.
--fallback-strategy<major-lines | minor-lines | none>default: major-lines
After @latest fails: major-lines (default) walks back by major (9.x→8.x→…). minor-lines steps one major.minor at a time. ESM/CJS errors (ERR_REQUIRE_ESM) stop further fallbacks for that package. none only tries @latest.
--link-groups<auto | none>default: auto
auto (default) builds linked batches from the registry peer-graph + your linkedGroups config. none upgrades strictly one dependency per step.
--resolve-peers--no-resolve-peers (opt-out)default: on
When a linked-group bump (or a single-package bump, via an ad-hoc group synthesized from direct-dep blockers) fails with a peer conflict, intersect the members' published peerDependencies across the packument and retry with the newest satisfiable tuple. Graphs of 10+ members switch to a SAT-style AC-3 + MRV-DFS solver. Members may land below `latest`; tagged `peer-resolved from <v>` in --summary / --json.
// SECTION B

Validation

2 flags
--validate<cmd>
Override the validator command run after every install. Defaults to <mgr> test if a test script exists, else <mgr> run build (yarn classic uses yarn build), else nothing. Great in monorepos: --validate "tsc -p tsconfig.json --noEmit".
--no-validate
Skip validation entirely. Upgrades are kept regardless of test/build outcome. Different from --force: --force still runs the validator and only keeps a bump when it fails; --no-validate runs no validator at all.
// SECTION C

Workspaces & package managers

8 flags
--package-manager<auto | npm | pnpm | yarn>default: auto
auto (default) reads packageManager, then lockfile (pnpm-lock.yaml → pnpm, yarn.lock → yarn, package-lock.json → npm), then pnpm-workspace.yaml, finally falls back to npm. Drives both <mgr> install and the default validator.
--include-workspace-deps
By default, deps whose name matches a local workspace package are skipped (their version comes from the workspace, not the registry). Pass this when those packages are also published to npm.
--workspaces
Traverse the root package.json AND every workspace member (one engine pass per package.json). Install + validation always run from the workspace root so the lockfile and validator see the whole monorepo.
--workspaces-only
Like --workspaces but skips the root package.json. Only workspace members are traversed.
--workspace<names>
Comma-separated workspace member names (the name field from each child package.json) to traverse. Pass root to also include the root. Unknown names produce a friendly error listing the known members.
--install-mode<root | filtered>default: root
Workspace install strategy. root (default) runs <mgr> install from the workspace root after every mutation. filtered rewrites per-child installs: npm 7+ → npm install --workspace <name>, pnpm → pnpm install --filter <name>, yarn berry + plugin-workspace-tools → yarn workspaces focus <name> (yarn classic falls back to a root install with a one-time warning).
--concurrency<n>default: 1
Maximum number of workspace targets traversed in parallel (1–16; default 1). Overlaps registry scan + plan across targets while a shared mutex keeps install + validation strictly serialized — the lockfile is shared. In an isolated-lockfile monorepo (pnpm shared-workspace-lockfile=false, or per-member lockfiles) installs + validation ALSO run in parallel. Requires --json so per-target log lines don't interleave.
--no-parallel-installsisolated lockfiles
Force installs + validation to stay serialized even when an isolated-lockfile monorepo is detected. Useful when debugging a flaky install step (parallel installs mask the ordering) or when a per-workspace postinstall script touches shared state outside its workspace.
// SECTION D

Reports & CI

5 flags
--retry-failed
Read .dep-up-surgeon.last-run.json from the previous run and only re-attempt entries that failed for non-terminal reasons (install, validation, validation-conflicts). Successful upgrades and terminal failures (peer, validation-script) are added to the ignore list automatically.
--no-persist-report
Do NOT write .dep-up-surgeon.last-run.json after the run. By default the structured report is written next to the workspace root for --retry-failed and CI consumers.
--summary<md | html>default: md
Write a human-friendly summary of the run. Destination is $GITHUB_STEP_SUMMARY if set (appended), otherwise --summary-file <path>, otherwise ./dep-up-surgeon-summary.<ext>. Includes counts, project info, target list, Upgraded/Failed tables, pre-flight status, ignored list.
--summary-file<path>
Override the destination for --summary. Wins over $GITHUB_STEP_SUMMARY.
--ciPR-bot ready
Convenience flag for CI / bot use. Disables --interactive, auto-enables --summary md (great with $GITHUB_STEP_SUMMARY), and exits 0 even when individual upgrades fail (only pre-flight + fatal errors exit 1) so per-package conflicts surface in the PR description instead of failing the job.
// SECTION E

Git integration

6 flags
--git-commit
Commit successful upgrades to git as the run progresses. Refuses to start on a dirty working tree (override with --git-allow-dirty). Only stages package.json + the lockfile — never git add -A. Skipped silently in --dry-run.
--git-commit-mode<per-success | per-target | all>default: per-success
How to group commits. per-success (default) — one commit per upgrade, best for review and git-revert-friendly. per-target — one commit per workspace target with all its successes squashed. all — one commit at the end with everything. Linked-group upgrades always land in a single commit regardless of mode.
--git-commit-prefix<prefix>
String prepended to every commit message (default "deps: "). Use "chore(deps): " for Conventional Commits or set it to your team's preferred convention.
--git-branch<name>
Create + checkout this branch before any commits. If it already exists, switches to it. Pairs nicely with --ci for PR-bot workflows (e.g. --git-branch "deps/auto-$(date +%Y-%m-%d)").
--git-sign
Pass --gpg-sign to every commit. Requires a signing key configured in git (user.signingkey + gpg.format). Failed signatures are recorded as failed commits in the JSON report rather than aborting the run.
--git-allow-dirtyuse with care
Allow --git-commit to run on a dirty working tree. We still only git add files we touched — but if you also git add your own files manually, they'll land in dep-up-surgeon's commits.
// SECTION F

Security-first mode

6 flags
--security-onlyCVE-driven
Flip the tool from 'bump everything' to 'bump only packages with known CVEs'. Runs npm/pnpm/yarn audit first, filters by --min-severity, then restricts the upgrade plan to vulnerable names. Every bump carries its advisory ID + severity into commit subjects (`[security:high]`) and into the --summary Security fixes table.
--min-severity<low | moderate | high | critical>default: low
Minimum advisory severity to consider under --security-only. Lower-severity advisories are filtered out before the upgrade plan is built.
--apply-overridestransitive CVEs
After the main upgrade loop, fix transitive CVEs no direct bump could reach by writing a package-manager override: overrides (npm 8.3+), pnpm.overrides (pnpm), resolutions (yarn). Install + validator run after each pin; on failure the override is rolled back automatically. Requires --security-only.
--override<spec...>parent-scoped
Apply manual override pins — parent-scoped or flat — independent of the audit. Repeatable / comma-separated. Syntax: `<chain>@<range>`, where `<chain>` is a bare name (`lodash`), a pnpm-style chain (`some-dep>foo`, any depth), or a yarn-style chain (`parent/child`). Written to the manager's native nested form and run through the same install + validator + rollback loop as --apply-overrides. Works standalone — no --security-only required.
--override-force
Used with --apply-overrides. Overwrite an existing override whose value conflicts with the audit-recommended version. Default refuses to clobber user-managed pins and records `conflict` in the report.
--fix-lockfilelockfile hygiene
After the main upgrade loop, run the manager's native dedupe (`npm dedupe --no-audit --loglevel error` / `pnpm dedupe` / `yarn dedupe` — berry only) to collapse redundant transitive copies WITHOUT touching package.json, and flag transitives more than a minor or a full major behind registry `latest` (top 250 by installed-copy count). Lockfile is snapshotted first; dedupe or post-dedupe validator failure restores it. Yarn classic → `skipped: "unsupported"`; missing lockfile → `skipped: "no-lockfile"`.
// SECTION G

PR automation · changelog · blast radius

8 flags
--changelog--no-changelog (opt-out)default: on
Fetch release notes (GitHub Releases API first, then the package's CHANGELOG.md from its published tarball) and embed them in commit bodies + --summary. Breaking-change markers in the notes are scanned automatically and tagged as [breaking] on the commit subject. Default ON when --git-commit or --summary is active. GITHUB_TOKEN / GH_TOKEN lifts the API rate limit to 5000/h.
--blast-radius--no-blast-radius (opt-out)default: on
Scan your project source (.ts/.tsx/.js/.jsx/.mjs/.cjs/.mts/.cts/.vue/.svelte/.astro) to list which files actually import/require each upgraded package. Word-boundary safe so `react` doesn't match `react-dom`. Output appears in --json (upgraded[].blastRadius) and as collapsible per-package lists in --summary. Default ON when --summary is active.
--open-prgh CLI required
After --git-commit --git-branch pushes the branch, open a GitHub pull request via the gh CLI. Body is the --summary markdown (falls back to a minimal deterministic body). Never fatal — a missing gh binary, auth failure, or push rejection is recorded under pullRequest.error in the JSON report. Existing PRs for the same head branch are reused.
--open-pr-title<title>
Override the PR title. Default is derived from the upgrade counts (e.g. `deps: [breaking+security] bump 3 packages`).
--open-pr-draft
Open the PR as a draft. Recommended with --force or when the breaking-change scanner fires so merge-queue bots don't auto-land it.
--open-pr-base<branch>
Target base branch. Default: the repo's default branch as reported by `gh repo view`.
--open-pr-reviewers<users>
Comma-separated usernames passed straight to `gh pr create --reviewer`.
--open-pr-assignees<users>
Comma-separated usernames passed straight to `gh pr create --assignee`.
// SECTION H

Subcommands · undo · doctor

10 flags
dep-up-surgeon undodisaster recovery
Replay the last-run report in reverse: write every recorded `from` back to package.json, drop (or restore) every override the run added, run install once per edited target, then run the validator so you see green/red before committing the revert. Deps that moved since the run are skipped as `drifted`. Exit 2 when the run report is missing / invalid.
undo --file <path>
Replay a specific run-report file (e.g. from a CI artifact) instead of the newest `.dep-up-surgeon.last-run.json` in the current directory.
undo --json / --dry-run
`--json` emits the full structured `UndoResult` to stdout (perfect for CI pipelines). `--dry-run` computes the reverse plan without touching `package.json` or running install — use it for review / CI audit.
undo --skip-install
Write the reverted `from` values back to `package.json` and drop/restore overrides, but DON'T run `<mgr> install` afterwards. Useful when you only want the source edits and plan to install yourself.
undo --no-validate / --validate <cmd>
`--no-validate` skips the validator after the revert install — handy when the project has no test script but you still want the dep ranges rolled back. `--validate "<cmd>"` overrides the validator command for the reverse pass (e.g. `tsc -p tsconfig.json --noEmit`).
undo --package-manager <mgr> / --cwd <path>
Force a specific package manager (`auto` / `npm` / `pnpm` / `yarn`) instead of auto-detecting from the run report, or run the undo against a different working directory.
dep-up-surgeon doctorpre-flight gate
Read-only green / yellow / red diagnostic — never mutates anything. Checks node-version (vs engines.node), manager resolution, lockfile parse, workspace coherence, policy parse, pre-flight validator, peer-dep scan, audit severity breakdown, and stale-transitive scan. Exit 0 on all-green (or yellow-only without --strict), 1 on yellow under --strict, 2 on any red.
doctor --strict
Treat yellow checks as failures (exit 1 instead of 0). Use for CI gates that should block on anything non-green.
doctor --json
Emit the full structured `DoctorReport` to stdout instead of the human format. Each check carries a stable ID (`node-version`, `manager`, `lockfile`, `workspace-coherence`, `policy`, `preflight-validator`, `peer-deps`, `audit`, `stale-transitives`) so dashboards and bots can parse consistently.
doctor --skip-audit / --skip-peer-scan / --skip-stale-scan
Opt out of the slower checks individually. Useful for air-gapped CI (skip-audit), huge trees (skip-peer-scan), or offline dev (skip-stale-scan). The diagnostic also accepts --no-validate, --validate <cmd>, --package-manager <mgr>, and --cwd <path>.

▸ note — non-registry ranges (workspace:, link:, file:, git:, git+, http:, https:) are skipped for upgrades · pre-flight runs once at the workspace root before any mutation