$npx -y skills add gaia-react/gaia --skill update-depsAutonomous Dependabot, auto-discover outdated packages, audit overrides, apply migrations for major bumps, resolve conflicts, run quality gate. Trigger when the user clicks the statusline Run /update-deps indicator or asks "update dependencies", "bump deps", "run dependabot".
| 1 | Superpowered Dependabot. Auto-discover all outdated packages, preview them grouped by severity so you can snooze any you are not ready for, audit overrides, apply codebase migrations for major bumps, resolve dependency conflicts, and run the quality gate. In CI it runs unattended (no preview); interactively it shows the preview first. On a `main`/`master` run it opens the PR and merges it once checks are green, then cleans up locally; on any other branch it pushes and leaves the PR to you. |
| 2 | |
| 3 | ## Pre-flight: Worktree check |
| 4 | |
| 5 | This wrapper writes a new `pnpm-lock.yaml` and opens a PR, both belong on the main checkout, not a per-SPEC worktree branch. If invoked from a linked worktree, reject hard with a message that surfaces the cached state from main so the user knows whether action is even pending. |
| 6 | |
| 7 | Detection (run this first, before anything else): |
| 8 | |
| 9 | ```bash |
| 10 | common_dir="$(git rev-parse --git-common-dir 2>/dev/null)" |
| 11 | if [ -n "$common_dir" ]; then |
| 12 | case "$common_dir" in |
| 13 | /*) absolute_common_dir="$common_dir" ;; |
| 14 | *) absolute_common_dir="$(pwd)/$common_dir" ;; |
| 15 | esac |
| 16 | main_root="$(cd "$(dirname "$absolute_common_dir")" 2>/dev/null && pwd)" |
| 17 | current_root="$(git rev-parse --show-toplevel 2>/dev/null)" |
| 18 | if [ -n "$main_root" ] && [ -n "$current_root" ] && [ "$main_root" != "$current_root" ]; then |
| 19 | cached_line="Cached state unavailable on main; symlinks may be broken, run \`.gaia/cli/gaia setup link-worktree\` to repair." |
| 20 | cache_file="$main_root/.gaia/local/cache/shared/update-check.json" |
| 21 | if [ -f "$cache_file" ] && command -v jq >/dev/null 2>&1; then |
| 22 | outdated_count="$(jq -r '.outdatedCount // 0' "$cache_file" 2>/dev/null)" |
| 23 | checked_at="$(jq -r '.checkedAt // 0' "$cache_file" 2>/dev/null)" |
| 24 | if [ -n "$outdated_count" ] && [ -n "$checked_at" ] && [ "$checked_at" != "0" ]; then |
| 25 | now=$(date +%s) |
| 26 | age=$((now - checked_at)) |
| 27 | # Format age as <Nm ago> / <Nh ago> / <Nd ago>. |
| 28 | ago_unit="s"; ago_value="$age" |
| 29 | if [ "$age" -ge 86400 ]; then ago_unit="d"; ago_value=$((age / 86400)); |
| 30 | elif [ "$age" -ge 3600 ]; then ago_unit="h"; ago_value=$((age / 3600)); |
| 31 | elif [ "$age" -ge 60 ]; then ago_unit="m"; ago_value=$((age / 60)); |
| 32 | fi |
| 33 | cached_line="Cached on main: $outdated_count packages outdated (last checked ${ago_value}${ago_unit} ago)." |
| 34 | fi |
| 35 | fi |
| 36 | cat <<EOF |
| 37 | /update-deps must run from the main checkout, not a worktree. |
| 38 | |
| 39 | Worktree: $current_root |
| 40 | Main checkout: $main_root |
| 41 | |
| 42 | $cached_line |
| 43 | |
| 44 | Run \`cd $main_root\` then re-invoke /update-deps. |
| 45 | EOF |
| 46 | exit 1 |
| 47 | fi |
| 48 | fi |
| 49 | ``` |
| 50 | |
| 51 | If the detection does not fire, fall through to the existing `## Pre-flight: Branch check` section. |
| 52 | |
| 53 | ## Pre-flight: Branch check |
| 54 | |
| 55 | ```bash |
| 56 | git branch --show-current |
| 57 | ``` |
| 58 | |
| 59 | If the current branch is `main` or `master` **and not running in CI**, set a flag (`SHOULD_CREATE_BRANCH=true`) but **do not create the branch yet**, branch creation is deferred until after Phase 1 confirms there are packages to update. Creating a branch when there is nothing to update pollutes the branch list. |
| 60 | |
| 61 | In CI (`CI=true`, set by GitHub Actions, GitLab CI, CircleCI, and most CI providers), skip branch creation, the workflow owns branch management and pre-creates the appropriate branch before this skill runs. |
| 62 | |
| 63 | Otherwise set `SHOULD_CREATE_BRANCH=false` and proceed on the current branch. |
| 64 | |
| 65 | ## Composition: --scope <group-name> |
| 66 | |
| 67 | When invoked with `--scope <group-name>` (e.g. `/update-deps --scope react-router`): |
| 68 | |
| 69 | - Skip Phase 0 (override audit), out of scope for a single-group run. |
| 70 | - Skip the discovery + preview phase, no preview runs in `--scope`; the |
| 71 | group's members are known from the companion-group table. |
| 72 | - Skip wave classification, the run is implicitly a single group; treat it |
| 73 | as Wave A if all members are minor/patch, else Wave B. |
| 74 | - Wave A / Wave B still apply, scoped to the named group's members |
| 75 | in root `package.json`. |
| 76 | - Quality gate, return value, and final report still run. |
| 77 | |
| 78 | Used by the GAIA CI update-deps workflow's wave-B matrix shards to fan |
| 79 | out one PR per major-bump group. |
| 80 | |
| 81 | ## Companion groups (reference) |
| 82 | |
| 83 | The fixed table mapping each package to its group. `gaia update-deps run` |
| 84 | resolves grouping internally and is the source of |
| 85 | truth at runtime; every emitted entry already carries its resolved `group`. |
| 86 | **When any member of a group is outdated, all members present in `package.json` |
| 87 | update together**, so a group moves as one unit (and snoozes as one unit). |
| 88 | |
| 89 | | Group | Members | |
| 90 | | --------------- |