--- name: deps description: Checks for outdated dependencies in a project using its configured package manager (bun, npm, nub, cargo, go, pip, bundler), plus GitHub Actions refs, Terraform provider pins, and container images in Kubernetes manifests; fetches upstream release notes to flag breaking changes. Use when the user asks to check for updates, look for outdated packages, audit dependencies, or review upgrade impact. license: MIT metadata: author: frytg agent: pi category: engineering --- # Check Dependencies Detect the project's package manager, list outdated dependencies, and surface breaking changes from upstream release notes. Infra-style repos with no lockfile still have dependencies: GitHub Actions refs, Terraform provider pins, and container images pinned in Kubernetes manifests — all covered below. ## 1. Detect the package manager Walk the project root for the first matching lockfile or manifest. Stop at the first hit. | File | Manager | Outdated command | | -------------------------------------- | ---------- | --------------------- | | `bun.lock` / `bun.lockb` | bun | `bun outdated` | | `package-lock.json` | npm | `npm outdated` | | `lock.yaml` | nub | `nub outdated` | | `Cargo.lock` | cargo | `cargo outdated` | | `go.sum` | go modules | `go list -u -m all` | | `pyproject.toml` / `requirements*.txt` | pip | `pip list --outdated` | | `Gemfile.lock` | bundler | `bundle outdated` | When multiple lockfiles are present, prefer (in order): `lock.yaml` (explicit nub declaration) > `bun.lock*` > `package-lock.json`. Only ask the user when the signal is truly ambiguous. `cargo outdated` requires `cargo install cargo-outdated` once. ## 2. List outdated dependencies Run the matched command from the project root. Capture full output, then parse for: package name, current version, wanted version, latest version. ### bun ```bash bun outdated ``` ### npm ```bash npm outdated ``` ### nub ```bash nub outdated # table of outdated deps nub outdated --json # machine-readable nub outdated --long # also show specifier and dep type nub outdated -r # across all workspace packages nub outdated '' # e.g. '@babel/*' ``` ### cargo ```bash cargo install cargo-outdated # one-time cargo outdated ``` ### go ```bash go list -u -m all ``` ### pip ```bash pip list --outdated ``` ### bundler ```bash bundle outdated ``` ### Terraform providers (no lockfile manager — pin comparison) If the repo has `*.tf` files with `required_providers` version pins (common in infra/homelab repos with no package manager at all), compare each pin against the registry: ```bash curl -s "https://registry.terraform.io/v1/providers/{namespace}/{name}/versions" \ | tr '{' '\n' | grep -oE '"version":"[0-9]+\.[0-9]+\.[0-9]+"' | cut -d'"' -f4 | sort -V | tail -1 ``` Pins are usually exact (`version = "2.81.0"`), so any newer release is an update. Same-major newer → patch/minor bucket; different major (or a 0.x provider minor flagged as breaking in its changelog — 0.x providers don't guarantee semver) → major bucket with a changelog link. The `.terraform.lock.hcl` mirrors the pins; report against the pin, not the lockfile. ## 3. Find breaking changes Group outdated packages into two buckets: **patch/minor** and **major**. Only majors need release-note research. ### GitHub Actions For every `uses: owner/repo@ref` in `.github/workflows/*.yml` (or `.yaml`): 1. Resolve `ref`. If it's a major-version tag (e.g. `@v4`), the next breaking change is the next major (e.g. `@v5`). If it's a SHA, resolve to the matching tag first: ```bash gh api "repos/{owner}/{repo}/git/refs/tags" ``` 2. Fetch the next major's release notes: ```bash gh release view v5 --repo actions/checkout # or list recent releases gh api "repos/actions/checkout/releases?per_page=10" ``` 3. For public repos, the raw API works without auth, but is rate-limited to 60 requests/hour/IP. Use `gh` with auth (`gh auth status`) for higher limits: ```bash curl -s https://api.github.com/repos/{owner}/{repo}/releases/latest ``` 4. Read the body for `BREAKING`, `Breaking`, `⚠️`, or migration notes. Note API/signature changes, default-behavior changes, and required Node/runtime bumps. ### Other dependencies For each package with a major version bump, locate the source repo. Sources in order of reliability: 1. The package's GitHub repo (check `package.json` → `repository`, or `cargo`/`go`/`pip` metadata). 2. The registry page itself (e.g. `https://www.npmjs.com/package/` links to the repo). 3. The changelog file in the repo (`CHANGELOG.md`, `CHANGES.md`, `Releases`). Fetch the release notes: ```bash # Recent releases for a GitHub repo gh release list --repo {owner}/{repo} --limit 20 # A specific tag gh release view v2.0.0 --repo {owner}/{repo} # Atom feed (no auth, works for public repos) curl -sL https://github.com/{owner}/{repo}/releases.atom | head -200 # Changelog file curl -sL https://raw.githubusercontent.com/{owner}/{repo}/main/CHANGELOG.md ``` Scan for `BREAKING`, `Breaking`, `⚠️`, `Migration`, `Removed`, renamed exports, default flips, and minimum runtime/peer bumps. Skip the raw changelog if it's mostly patch entries — only the majors are interesting. ## 4. Check container images (Kubernetes manifests) If the repo contains Kubernetes workload manifests (files with `kind: Deployment`, `StatefulSet`, `DaemonSet`, `Job`, `CronJob`, or `Pod`), every pinned `image:` tag is a dependency. Find them: ```bash rg -l --type yaml -e '^kind: (Deployment|StatefulSet|DaemonSet|Job|CronJob|Pod)\b' . ``` **If the `k8s-images` skill is available, delegate to it** — it owns the full flow: extracting images (multi-doc safe, `yq`), classifying floating/templated/digest-pinned tags, `crane ls` lookups bounded by the pinned major, the one-at-a-time confirmation, and the YAML edits. Never duplicate that logic inline. Without the skill, do the read-only minimum yourself: 1. Extract images per manifest (containers + initContainers, CronJob via `.spec.jobTemplate...`), dedupe. 2. Skip templated (`{{`, `${`), digest-pinned (`@sha256:`), and floating tags (`latest`, `main`, `stable`, dated). 3. `crane ls ` per image, pick the highest tag matching the pinned shape within the same major; different-major latest goes in the **major** bucket with a release-notes link. 4. Report — don't edit. Same rule as lockfiles: the user approves every bump. Registry notes: - Bare names default to Docker Hub (`nginx` → `docker.io/library/nginx`). - Private registries need ambient credentials; a failed lookup is a registry error in the report, not a bug. - `crane ls` is slow; call it once per repo, not per file. Don't wrap it in `timeout` on macOS — the binary doesn't exist there and every call silently fails. ## 5. Check tool config drift (biome) If the project uses biome, the version pinned in `biome.json#.$schema` can lag behind the installed `biome` binary. Drift means new rules/options aren't available and deprecated keys may be ignored or warned. Biome ships a built-in `migrate` command for exactly this: ```bash # Dry-run — prints a diff if the config needs an update, no-op if not biome migrate # Apply the migration biome migrate --write ``` The check is safe to run unconditionally: if `$schema` already matches the installed version, `biome migrate` exits silently. To compare versions explicitly without running the command: ```bash # Installed version biome --version # Schema version (matches the URL in $schema: .../schemas/X.Y.Z/schema.json) grep -oE '/schemas/[0-9]+\.[0-9]+\.[0-9]+' biome.json | head -1 ``` If a migration was applied, re-run the linter to confirm the new schema parses cleanly: ```bash biome check . ``` Skip this step if the project has no `biome.json` / `biome.jsonc`. For other tooling config (`.eslintrc`, `prettier.config.*`, etc.) there's no equivalent `migrate` command — compare the pinned version against the installed binary and consult the tool's changelog manually. ## 6. Report Produce a tight summary, not a raw dump: - **Patch & minor** — one bullet per package, no commentary. - **Major & breaking** — one bullet per package with: current → next, a one-line breaking-change summary, and a link to the release notes. Includes container images whose upstream major differs from the pinned one. - **Container images** — out-of-date pinned tags (file, container name, current → latest), plus separate buckets for floating tags that should be pinned and registry errors. Already-latest images get one line, not a list. - **Action items** — anything needing user decision: Node/runtime bump, peer-dep conflict, deprecated transitive, security advisory, rolling tags to pin. Keep the report scannable. Don't paste the full `outdated` output. ## Safety - Never run `update` / `upgrade` / `install` as part of this skill. The user decides what to bump. - Never edit lockfiles or `package.json` versions. Reporting is the only job. - Never deploy or mutate live state: no `terraform apply`/`init -upgrade`, no `kubectl apply`, no cluster or host changes. Infra deps (providers, images) are reported like any other dependency. - For private registries, `npm outdated` may still work, but `gh` release lookups need an authenticated user.