You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Install "BetterDependabot" in this repo by following the spec/instructions from
https://gist.githubusercontent.com/alexey-max-fedorov/a3108513bbbf7f9f8c43c900e0664767/raw/00500fcedd5ae2dabc09dc9de46cd9078bc721ad/betterdependabot-prompt.md
Paste this prompt into Claude Code to set up BetterDependabot on any project. BetterDependabot is a GitHub Actions workflow that runs daily, calls each package manager's native update command per directory, and commits the result — giving you automatic dependency updates that keep lockfiles in sync (unlike GitHub's built-in Dependabot, which only updates package.json and breaks frozen-lockfile CI).
The Prompt
Set up BetterDependabot for this project.
BetterDependabot is a GitHub Actions workflow that:
- Runs daily on a cron schedule (and on workflow_dispatch)
- Calls the native update command in each package directory (pnpm update / npm update / yarn upgrade / bun update)
- Commits the lockfile changes back to the default branch
This avoids the core problem with GitHub's built-in Dependabot: it updates package.json but not the root lockfile, causing ERR_PNPM_OUTDATED_LOCKFILE in CI.
---## Step 1 — Discover all package directories
Run this to find every package.json (excluding build artifacts and node_modules):
```bash
find . -name "package.json" \
-not -path "*/node_modules/*" \
-not -path "*/.next/*" \
-not -path "*/build/*" \
-not -path "*/dist/*" \
-not -path "*/.plasmo/*" \
-not -path "*/coverage/*" \
-not -path "*/.turbo/*" \
| sort
```
For each package.json found, read it and record:
-**Directory** — relative path from repo root, use `.` for root
-**Package manager** — check `packageManager` field first (e.g. `"pnpm@10.23.0"`), then check for lockfiles:
-`pnpm-lock.yaml` → pnpm
-`yarn.lock` → yarn (check `packageManager` for classic vs berry)
-`bun.lockb` → bun
-`package-lock.json` or nothing → npm
-**Node requirement** — read `engines.node` if present
---## Step 2 — Determine global config-**Node version**: use the highest major version required across all packages. Minimum is `22` (pnpm 11+ requires Node ≥22; GitHub is forcing Node 24 for Actions by June 2026).
-**Uses pnpm**: true if ANY directory uses pnpm
---## Step 3 — Generate `.github/workflows/BetterDependabot.yml`### ⚠️ Critical rules — these mistakes caused 100% failure across 8 real repos:1.**Always add `permissions: contents: write`** at the workflow level. GitHub's default GITHUB_TOKEN is `contents: read` — without this, every push step gets a 403.
2.**Never hardcode `version:` in `pnpm/action-setup`** if any `package.json` has a `packageManager` field. Newer versions of the action auto-read it. Both set = `ERR_PNPM_BAD_PM_VERSION`.
3.**Use plain `git push`** for the commit step, not `ad-m/github-push-action` or similar. `actions/checkout@v4` already configures the GITHUB_TOKEN for git auth — a plain push just works.
4.**Node 22 minimum** — required for pnpm 11+ compat.
5.**Must be on the default branch** — GitHub only triggers scheduled workflows for files on the default branch.
### Template:```yamlname: BetterDependaboton:
schedule:
- cron: '0 4 * * *'workflow_dispatch:
permissions:
contents: writejobs:
update-dependencies:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4with:
node-version: '<NODE_VERSION>'# 22 minimum, higher if engines requires it# Only include if project uses pnpm — OMIT the version: field entirely
- uses: pnpm/action-setup@v4# One step per package directory — for root, omit working-directory
- name: Update <DIR> dependencies# working-directory: <RELATIVE_PATH> # omit for rootrun: <UPDATE_CMD># Repeat the above step for each additional directory...
- name: Commit and pushrun: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add . git diff --staged --quiet || git commit -m "chore: update dependencies" git push origin HEAD:${{ github.ref }}```Update commands by package manager:- pnpm → `pnpm update`
- npm → `npm update`
- yarn (classic) → `yarn upgrade`
- yarn (berry) → `yarn up`
- bun → `bun update`For repos with mixed package managers (e.g. root uses pnpm, a subdirectory uses npm):
- Include the `pnpm/action-setup@v4` step (pnpm global install)
- npm is already available on the runner — just call `npm update` in that directory's step
- No conflicts
---
## Step 4 — Generate `.github/dependabot.yml`Create or update `.github/dependabot.yml` for GitHub's native Dependabot. Keep this for GitHub Actions version updates (checkout, setup-node, etc.) since BetterDependabot doesn't handle those.```yamlversion: 2updates: # One npm entry per package directory - package-ecosystem: "npm" directory: "/" # use "/subdir" for subdirectories schedule: interval: "daily" commit-message: prefix: "[deps]" # customize per dir if desired # Always include this for Actions updates - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" commit-message: prefix: "[actions]"```
---
## Step 5 — Commit both files to the default branch```bashgit add .github/workflows/BetterDependabot.yml .github/dependabot.ymlgit commit -m "chore: add BetterDependabot workflow"git push```
---
## Step 6 — Trigger and verifyGet the GitHub remote:
```bashgit remote get-url origin```Trigger a run:
```bashgh workflow run BetterDependabot.yml --repo <owner/repo>```Poll until done:
```bashwhile true; do STATUS=$(gh run list --workflow=BetterDependabot.yml --repo <owner/repo> --limit 1 --json status --jq '.[0].status') echo "Status: $STATUS" if [ "$STATUS" != "in_progress" ] && [ "$STATUS" != "queued" ]; then break; fi sleep 30done```If it fails, get the logs:
```bashRUN_ID=$(gh run list --workflow=BetterDependabot.yml --repo <owner/repo> --limit 1 --json databaseId --jq '.[0].databaseId')gh run view $RUN_ID --repo <owner/repo> --log```Fix, commit, push, and re-trigger until it passes. Common failures and their fixes:
| Error | Fix ||-------|-----|| `403 Permission denied` on push | Add `permissions: contents: write` to the workflow || `ERR_PNPM_BAD_PM_VERSION` | Remove `version:` from `pnpm/action-setup` step || `ERR_UNKNOWN_BUILTIN_MODULE: node:sqlite` | Bump `node-version` to `22` (or `24`) || `packages field missing or empty` | Add `packages: ['.']` to `pnpm-workspace.yaml` || Workflow doesn't trigger on schedule | Move workflow file to the default branch |
What gets created
.github/workflows/BetterDependabot.yml — the daily update runner
.github/dependabot.yml — native Dependabot for GitHub Actions version updates only
Why not just use GitHub Dependabot for everything?
Dependabot updates package.json but not the root pnpm-lock.yaml. Any CI that runs pnpm install --frozen-lockfile (e.g. Vercel) will fail with ERR_PNPM_OUTDATED_LOCKFILE. BetterDependabot runs the actual update command so lockfiles are always in sync.
BetterDependabot is a GitHub Actions workflow that:
Runs daily on a cron schedule (and on workflow_dispatch)
Calls the native update command in each package directory (pnpm update / npm update / yarn upgrade / bun update)
Commits the lockfile changes back to the default branch
This avoids the core problem with GitHub's built-in Dependabot: it updates package.json but not the root lockfile, causing ERR_PNPM_OUTDATED_LOCKFILE in CI.
Step 1 — Discover all package directories
Run this to find every package.json (excluding build artifacts and node_modules):
Directory — relative path from repo root, use . for root
Package manager — check packageManager field first (e.g. "pnpm@10.23.0"), then check for lockfiles:
pnpm-lock.yaml → pnpm
yarn.lock → yarn (check packageManager for classic vs berry)
bun.lockb → bun
package-lock.json or nothing → npm
Node requirement — read engines.node if present
Step 2 — Determine global config
Node version: use the highest major version required across all packages. Minimum is 22 (pnpm 11+ requires Node ≥22; GitHub is forcing Node 24 for Actions by June 2026).
⚠️ Critical rules — these mistakes caused 100% failure across 8 real repos:
Always add permissions: contents: write at the workflow level. GitHub's default GITHUB_TOKEN is contents: read — without this, every push step gets a 403.
Never hardcode version: in pnpm/action-setup if any package.json has a packageManager field. Newer versions of the action auto-read it. Both set = ERR_PNPM_BAD_PM_VERSION.
Use plain git push for the commit step, not ad-m/github-push-action or similar. actions/checkout@v4 already configures the GITHUB_TOKEN for git auth — a plain push just works.
Node 22 minimum — required for pnpm 11+ compat.
Must be on the default branch — GitHub only triggers scheduled workflows for files on the default branch.
Template:
name: BetterDependaboton:
schedule:
- cron: '0 4 * * *'workflow_dispatch:
permissions:
contents: writejobs:
update-dependencies:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4with:
node-version: '<NODE_VERSION>'# 22 minimum, higher if engines requires it# Only include if project uses pnpm — OMIT the version: field entirely
- uses: pnpm/action-setup@v4# One step per package directory — for root, omit working-directory
- name: Update <DIR> dependencies# working-directory: <RELATIVE_PATH> # omit for rootrun: <UPDATE_CMD># Repeat the above step for each additional directory...
- name: Commit and pushrun: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add . git diff --staged --quiet || git commit -m "chore: update dependencies" git push origin HEAD:${{ github.ref }}
Update commands by package manager:
pnpm → pnpm update
npm → npm update
yarn (classic) → yarn upgrade
yarn (berry) → yarn up
bun → bun update
For repos with mixed package managers (e.g. root uses pnpm, a subdirectory uses npm):
Include the pnpm/action-setup@v4 step (pnpm global install)
npm is already available on the runner — just call npm update in that directory's step
No conflicts
Step 4 — Generate .github/dependabot.yml
Create or update .github/dependabot.yml for GitHub's native Dependabot. Keep this for GitHub Actions version updates (checkout, setup-node, etc.) since BetterDependabot doesn't handle those.
version: 2updates:
# One npm entry per package directory
- package-ecosystem: "npm"directory: "/"# use "/subdir" for subdirectoriesschedule:
interval: "daily"commit-message:
prefix: "[deps]"# customize per dir if desired# Always include this for Actions updates
- package-ecosystem: "github-actions"directory: "/"schedule:
interval: "daily"commit-message:
prefix: "[actions]"