On this page
Start with Renovate and Dependabot
What the README and the knowledge base say about these tools, on one page.
Five-minute start
npx depcurfew doctorworks beforeinit: withoutdepcurfew.jsonit compares the repository with the policyinitwould write and shows, as notes in a block of their own, whatinitandapplywould change, for example a package manager that installs new versions without a release-age delay, with the settingsapplywould write for it. These notes never make it fail.npx depcurfew initwritesdepcurfew.jsonwith the default policy below and lists the tools it detected. When the repository already sets a longer release-age delay for one of them,cooldown.minimumkeeps the longest one, andinitsays where it found it.npx depcurfew explainshows what it detected and what the policy means for each tool.npx depcurfew apply --dry-runprints the changes as a diff, without writing anything.npx depcurfew applywrites them. Run it again wheneverdepcurfew.jsonchanges; a second run with the same policy changes nothing.npx depcurfew doctorreports configuration that silently does not work and drift from the policy, and exits with 1 when it finds an error or, with the"doctor": { "failOn": "warning" }thatinitwrites, a warning.- Add the GitHub Action so that doctor runs on every push and reports to code scanning.
The default policy:
{
"$schema": "https://unpkg.com/depcurfew/schema.json",
"version": 1,
"cooldown": {
"minimum": "3d",
"exclude": [],
"securityUpdates": "bypass"
},
"installScripts": {
"default": "deny",
"allow": [],
"deny": []
},
"sources": {
"git": "deny",
"remoteTarball": "deny",
"file": "allow",
"directory": "allow"
},
"targets": "auto",
"doctor": {
"failOn": "warning"
}
}
Update bots
apply gives Renovate and Dependabot the policy's delay, rounded up to their unit and at least as long as the delay of every package manager after rounding, so that they never propose a version the package managers would refuse. It edits only bot configuration files that exist and adds no entries to them.
- Dependabot gets
cooldownin eachupdatesentry of an ecosystem depcurfew configures (npm,bun,deno,pip,uv,composer,bundler), with the policy's exceptions for that registry underexclude(abundlerentry keeps its own, since the policy names no gems), and in the entries of the ecosystems updated by bots only (below). Anincludelist in such acooldownstays, but it limits the cooldown to the dependencies it names, soapplywarns (bot-rule-shortens-delay, with the entry and the line) unless it is"*"; so it does when an entry keeps its ownexclude(actions, gems, the ecosystems updated by bots only) and that list matches every dependency ("*"), since Dependabot then waits for none of them.doctorreports both as before (bot-cooldown-mismatch,broad-exclusion). - GitHub Actions. When the repository has workflows in
.github/workflowsandtargetsis"auto"or names the bot, the actions they run wait as long as the packages. Thegithub-actionsentries of Dependabot get the samedefault-days(GitHub Actions reads nosemver-*-days), and theirexcludestays as written, because the policy's exceptions name packages, not actions. The delay at the top level of the Renovate configuration covers itsgithub-actionsmanager too.doctor(bot-cooldown-mismatch) compares the bot's delay for the actions withcooldown.minimum. - Cargo, Go modules, Maven, Gradle and NuGet are updated by bots only. Their package managers have no release-age delay that depcurfew configures (the rows "bots only" in Supported tools say what each has), so depcurfew delays their new versions through the bots alone. When
depcurfew.jsonhas acooldownandtargetsis"auto"or names the bot, the Dependabot entriescargo,gomod,maven,gradleandnugetget the samedefault-daysas the packages, lowersemver-*-daysare raised to it, and theirexcludestays as written, because the policy's exceptions name npm, Python and Composer packages. The delay at the top level of the Renovate configuration covers itscargo,gomod,maven,gradleandnugetmanagers;packageRulesentries for them by manager, category (rust,golang,java,dotnet) or datasource (crate,go,maven,nuget) count as for the package managers, and the presetsecurity:minimumReleaseAgeCrategives Cargo dependencies 3 days.doctor(bot-cooldown-mismatch) compares the bot's delay for them withcooldown.minimum, and gives one note per ecosystem when the repository has their files but no update bot, since nothing delays their new versions then. depcurfew looks for these files (Cargo.toml,go.mod,pom.xml,settings.gradle, a.csproj…) in the root, in its direct subdirectories that are not hidden, in workspace packages and in the directories listed inprojects;depcurfew explainlists what it found under "Updated by bots only". Other dependencies that come in with the bot's update of a lockfile (Cargo.lock,go.sum…) are not held back, because the package manager has no delay of its own to apply to them. - What NuGet's
minPublishAgeHourscovers. From .NET SDK 11.0.100 (NuGet 8.0, Visual Studio 18.12) on, the attributeminPublishAgeHoursof a source innuget.configholds back new versions only wheredotnet package addanddotnet package updatechoose the version themselves; the 10.0 SDKs and earlier ignore it, and depcurfew does not write it. The NuGet documentation says that an explicit version bypasses it, that restore does not check it (for transitive dependencies too), and that with an age set, restore fails withNU1020for a floating version such as1.2.*. The Visual Studio Package Manager UI and Package Manager Console,dotnet package listanddotnet package searchare not documented as covered (their NuGet issues are open), nor aredotnet tool,dnxanddotnet new install.check, the Claude Code hook anddepcurfew mcpdo not look NuGet packages up, so depcurfew delays NuGet dependencies only through the bots. - Renovate gets the delay at the top level of its configuration and a
packageRulesentry for the exceptions of each registry, limited to its datasource:matchDatasources: ["npm"]for npm names,["pypi"]forpypi:names and["packagist"]forcomposer:names, so an exception never reaches a crate, a Go module, a gem or an action of the same name. A built-in preset ofextendsthat gives a datasource in use a shorter delay than the policy (config:best-practicesandsecurity:minimumReleaseAgeNpm3 days fornpm,security:minimumReleaseAgePypiforpypi,security:minimumReleaseAgeCrateforcrate) wins over the top-level value, since a matching rule wins over the top level;applythen writes a rule with that datasource,matchUpdateTypes: ["major", "minor", "patch"]and the policy's delay at the front ofpackageRules, which Renovate applies after the rules of the presets and before the repository's own rules and the exception rules, and removes it when the preset goes or no longer waits less. The deprecatedrenovatekey ofpackage.jsonand.renovatercget it in the snippet.doctorreports a rule of the repository that gives npm, Python or Composer packages of some names a shorter delay thancooldown.minimum, or none, while the policy's exceptions do not exempt them (broad-exclusion, at the line of the rule), and a rule an earlierapplywrote withoutmatchDatasources: ["npm"].applyanddoctorread the otherpackageRulesentries the way Renovate matches them, also bymatchManagersandmatchCategories:npmcovers the packages of npm, pnpm and Yarn,bunanddenothose of Bun and Deno,pep621those of uv and PDM,poetry,pip_requirementsandpipenvthose of Poetry, pip and Pipenv,composerthose of Composer,bundlerthose of Bundler, andgithub-actionsthe actions of the workflows; the categories arejs,python,php,rubyandci. Globs,/regex/,!and a single string instead of a list work as in Renovate. A rule that shortens the delay of a package manager in use (or of the actions) givesbot-rule-shortens-delayinapplyandbot-cooldown-mismatchindoctor, and one that turns it off givesbroad-exclusion. For the actions, a rule withmatchFileNamesthat matches every workflow file of the repository (read as Renovate reads it:*within one directory,**across them, any case, or/regex/) and a rule withmatchDepTypesthat matchesaction, the depType Renovate gives an action of a workflow step, count too; one that matches only some workflow files, or only reusable workflows (workflow), leaves the other actions their delay and does not count. A rule with a glob matcher depcurfew cannot read (braces, character classes,?, or extglobs such as@(a|b)and+(…)) does not count, anddoctorgives a note when it may set a shorter delay. depcurfew does not run a/regex/that a crafted file could make take minutes: one with a quantified group, a backreference, a lookaround, more than one*,+or{n,}, or more than 256 ways to match through?,{n,m}and|(16 next to a*,+or{n,}), nor the patterns of a file past a fixed amount of matching work. Such a pattern counts as matching where the rule shortens or turns off the delay, sobot-cooldown-mismatch,broad-exclusionandbot-rule-shortens-delayreport the rule and name the pattern; where the rule would make the delay longer, it does not count; so does a rule with a matcher depcurfew does not evaluate (matchBaseBranches,matchJsonata,matchRepositories,matchCurrentAge, andmatchFileNamesormatchDepTypesfor the packages of a package manager), unless a package matcher already limits it to some packages. When rules give the update types different delays,doctorreports each one that is shorter, not only the shortest. - Numbers in
dependabot.ymlare read as Dependabot's YAML library, Ruby's Psych, reads them, which follows YAML 1.1:default-days: 010is 8 days (octal),1_0and1,0are 10,1:30is 5400, and0o12is text.doctorcompares the number Dependabot reads with the policy and says how it read it ("default-days: 010 in .github/dependabot.yml, which Dependabot reads as 8"), andapplywrites the policy's number in place of one Dependabot reads otherwise. Words are read the same way:yes,no,onandoffin any case are booleans and~andnullin any case are null, soapplywrites an exception such asyes,off,1_0or2024-01-01in double quotes (- "yes"), which Dependabot reads as the name, and treats an unquoted- yesin the file as the boolean it is. - YAML aliases. Dependabot does not accept YAML aliases (
*name) in.github/dependabot.yml(dependabot-core loads the file without them), sodoctordoes not read a delay or an exception through one:bot-cooldown-mismatchgives a note at the first alias instead of a result,applywrites thecooldownof an entry out in place of an alias and warns that Dependabot reads nothing from the file (bot-config-unreadable), andinitnotes it, since it does not keep a longer delay from such a file incooldown.minimum. GitHub Actions workflows may use aliases:doctorand detection read theenvmaps, jobs and steps of a workflow through them, at most 100 aliases per file. - How old an action is comes from git. Renovate takes the commit date of a tag, the tagger date of an annotated tag, or the date of a GitHub release of that version when that is newer, and holds an update without a date; Dependabot takes the date of the GitHub release, then of the tag, then of the commit, and lets an update without a date through. Whoever makes a commit or a tag sets its git date, so the delay protects actions less than packages from a registry, which records when a version was published.
In a repository without package.json
depcurfew is a Node.js program, and a repository without package.json in its root, such as a Rust, .NET, Python, PHP or Ruby project, does not need one to run it.
In GitHub Actions, the GitHub Action needs nothing installed.
Once, by hand, run an exact release with npx:
npx --yes depcurfew@1.5.2 doctor
Name a release that is at least as old as cooldown.minimum of the policy: depcurfew's own Claude Code hook denies a younger one, and so does npm where its min-release-age is set (npx then fails with ETARGET). The example names the newest release that was at least 7 days old when this README was written, usually the one before the newest. Without --yes, npx asks before it downloads a package the project does not have, and without a terminal or in CI it downloads without asking.
Pinned in the repository, keep depcurfew in the tools directory .claude/depcurfew: its own package.json pins depcurfew exactly, its package-lock.json is committed and .claude/depcurfew/node_modules is git-ignored. npm ci installs what that package-lock.json locks, and --prefix runs it in the tools directory, so both commands run from the root of the repository, without cd:
npm ci --ignore-scripts --prefix .claude/depcurfew
node .claude/depcurfew/node_modules/depcurfew/dist/cli.js doctor
doctor reads this copy too: depcurfew-outdated says when the depcurfew that runs is older than it, and the Claude Code hook can run it. To be offered new releases of the pin, you can add a Dependabot npm entry for the directory /.claude/depcurfew; apply gives it the cooldown of the policy like any other npm entry. The tools directory and the Action pin their versions separately, so update both.
Supported tools
| Tool | Release-age delay | Exceptions | Install-script allow-list (Python: packages built from source; Composer: plugins) | Dependency sources | Verified |
|---|---|---|---|---|---|
| Renovate | minimumReleaseAge in renovate.json, renovate.jsonc … (duration string), since 35.46.0 | packageRules: matchPackageNames + minimumReleaseAge: null, since 35.46.0 ❓ | none | n/a | 2026-10-28 – 2026-11-03 |
| Dependabot | cooldown in ., . (days), since 2025-07-01 | cooldown.exclude, since 2025-07-01 ❓ | none | n/a | 2026-10-28 – 2026-11-03 |
| Cargo (bots only) | registry. in ., since Cargo 1.100.0 (depcurfew does not write it) ❓; the delay comes from the bots: Dependabot cargo, Renovate cargo | n/a | n/a | n/a | 2026-11-03 |
| Go modules (bots only) | none ❓; the delay comes from the bots: Dependabot gomod, Renovate gomod | n/a | n/a | n/a | 2026-11-03 |
| Maven (bots only) | none ❓; the delay comes from the bots: Dependabot maven, Renovate maven | n/a | n/a | n/a | 2026-11-03 |
| Gradle (bots only) | none ❓; the delay comes from the bots: Dependabot gradle, Renovate gradle | n/a | n/a | n/a | 2026-11-03 |
| NuGet (bots only) | minPublishAgeHours in nuget.config, since .NET SDK 11.0.100, only for the versions dotnet package add and dotnet package update choose (depcurfew does not write it); the delay comes from the bots: Dependabot nuget, Renovate nuget | n/a | n/a | n/a | 2026-11-03 – 2026-11-11 |
⚠️ official sources disagree (depcurfew takes the safer reading) · ❓ official sources are incomplete. Every value with its source: docs/knowledge.md.
doctor rules for these tools
bot-cooldown-mismatch
error · An update bot waits less than the package manager, or for the actions of workflows and the dependencies of the ecosystems updated by bots only less than the policy, before proposing a new version.
The bot then opens pull requests with versions the package manager would not pick yet: they fail where the manager re-checks the lockfile or bring in younger versions, and security updates that skip the bot delay fail too. A Dependabot cooldown with an include list delays only the dependencies it names; a Renovate packageRules entry can shorten the delay for a registry, manager, category, update type or the files and depType of actions, each is reported, and one with a matcher depcurfew cannot read gets a note. The actions of workflows and the dependencies of Cargo, Go, Maven, Gradle and NuGet must wait cooldown.minimum; without a bot, the latter get a note. An unreadable bot file (JSON5, a YAML alias) gets a note per package manager that waits. With projects, a bot file inside a project gets a note (bots read only the root's), and a project the root's Dependabot configuration leaves out gets a warning. A Dependabot composer entry gets a note: it counts from the release time the author sets.
Fix: Give the bot a delay at least as long as the package manager's, and for the actions of workflows and the ecosystems updated by bots only as long as cooldown.minimum (depcurfew apply does this).
Every rule: doctor rules.
Sources
Every fact behind these tables, with its official source, is in the knowledge base: Renovate, Dependabot.