Dependency bots are useful, but I do not want every package manager to become a surprise inbox. Before a bot opens a branch, I like having a local habit for checking drift, grouping the work, and deciding what deserves a real CI run.
npm-check-updates is good for the JavaScript side of that loop. It looks at package.json, shows
newer versions, and can update the manifest when I am ready to do the real work. The important word
is ready. I do not treat dependency updates as a button that magically makes the repo healthier.
They are code changes. They deserve a branch, a lockfile diff, tests, and a quick read of the risky
packages.
python-check-updates gives the same shape to Python projects: a fast local check against PyPI
before I decide whether to touch the lockfile. That matters in mixed stacks where the frontend, CLI,
worker, and scripts all drift at different speeds. A small local command makes the drift visible
without turning the first signal into a pull request.
The loop I want#
For a Bun or npm-style project, I usually want the first pass to be read-only:
npx npm-check-updatesThen I split the result into boring updates, runtime-sensitive updates, and package-boundary changes. UI libraries, bundlers, database clients, auth packages, generated SDK tooling, and test runners do not get treated like a random patch bump. If the package can change how the app builds, talks to the network, serializes data, or validates user input, I read more before I touch the lockfile.
When the set is small enough to review:
npx npm-check-updates -u
bun install
bun test
bun run typecheckFor Python projects, the same habit applies. Install the checker, run it locally, then let uv own
the environment and lockfile after the update decision is made:
cargo install python-check-updates
python-check-updates
uv lock
uv run pytestThe tool does not replace judgment. It gives the judgment a cleaner starting point.
How this fits with Renovate#
Renovate is still useful. The bot handles schedules, grouping, dashboards, and boring repetition. The local check handles operator awareness. I want both because they solve different parts of the same maintenance problem.
The local pass is especially useful before a maintenance window, before cutting a release, or after a long-running feature branch has been away from main for too long. It lets me answer the practical question before automation creates work for everyone else: is this a small refresh, or did the platform move under us?
What belongs in Lab#
This is the kind of thing I want Lab to capture: small tools that remove operational friction. The same bucket should eventually include zsh setup, Ansible workstation bootstrap, local installs, and Tailscale routes for exposing development services safely. The common thread is not novelty. It is developer leverage: less repeated setup, fewer forgotten steps, and a local path that stays close to how the system is actually built and shipped.