depcurfew v1.5.1
On this page

Package manager knowledge base

The facts depcurfew relies on, each linked to the official documentation or changelog it was verified against.

Legend: ↗ source · ❓ uncertain (official sources are incomplete) · ⚠️ disputed (official sources disagree; every variant is shown) · 1.2.3+ means "from version 1.2.3".

14 tools · 912 facts · 126 uncertain · 14 disputed · verified 2026-10-28 to 2026-11-03.

Release-age cooldown

How each tool delays freshly published versions.

ToolSettingConfig filesCLI flagUnitSinceDefaultExclusionsExclusions sinceExclusion patternsSecurity updates
npmmin-release-age ↗.npmrc ↗--min-release-age=<days> ↗days ↗11.10.0 ↗11.10.0+: off ↗min-release-age-exclude ↗11.17.0 ↗Package names or minimatch globs matched against the name, e.g. @myorg/*; only the named package is exempt, not its dependencies; also exempts from before ↗applies ↗
pnpmminimumReleaseAge ↗pnpm-workspace.yaml ↗none ❓ ↗minutes ↗10.16.0 ↗10.16.0+: 0
11.0.0+: 1440 ↗
minimumReleaseAgeExclude ↗10.16.0 ↗Package names (all versions); globs such as @myorg/* since 10.17.0; exact versions name@1.2.3 or name@1.2.3 || 1.2.4 since 10.19.0; ranges are not documented ↗applies ↗
Yarn (Berry)npmMinimalAgeGate ↗.yarnrc.yml ↗none ❓ ↗minutes ↗4.10.2 ↗⚠️ 4.10.0+: 0
4.15.0+: 1d ↗ / 4.10.0+: 0
4.11.0+: 3d
4.15.0+: 1d ↗
npmPreapprovedPackages ↗4.10.0 ↗Package descriptors or name globs, optionally with a semver range: @scope/*, package, package*, package@^1.0.0; global only, not per npmScopes ↗applies ❓ ↗
Buninstall.minimumReleaseAge ↗bunfig.toml ↗--minimum-release-age ↗seconds ↗1.3.0 ↗⚠️ 1.3.0+: off ↗ / 1.3.0+: 259200 ↗install.minimumReleaseAgeExcludes ↗1.3.0 ↗Exact package names (all versions); since 1.4.4 also name@exactVersion. No wildcards; ranges and tags are ignored with a warning ↗applies ❓ ↗
DenominimumDependencyAge ↗deno.json, .npmrc ↗--minimum-dependency-age ↗minutes ↗⚠️ 2.5.5 ↗ / 2.6.0 ↗earlier: off
2.9.0+: 1440 ↗
minimumDependencyAge.exclude ↗2.5.5 ↗Specifiers prefixed npm: or jsr:; a trailing * matches by prefix (npm:@scope/*) since 2.9.2 ↗applies ❓ ↗
uvexclude-newer ↗uv.toml, pyproject.toml ↗--exclude-newer ↗duration-string ↗0.9.17 ↗0.9.17+: off ↗exclude-newer-package ↗0.9.25 ↗Exact package names as table keys; no wildcards ↗applies ❓ ↗
pipuploaded-prior-to ↗none (no project file) ↗--uploaded-prior-to ↗days ↗26.1.0 ↗26.1.0+: off ↗none ❓ ↗--applies ❓ ↗
Poetrysolver.min-release-age ↗poetry.toml ↗none ❓ ↗days ↗2.4.0 ↗2.4.0+: off ↗solver.min-release-age-exclude ↗2.4.0 ↗Exact package names; no wildcards ↗applies ❓ ↗
PDMexclude-newer ↗pyproject.toml ↗--exclude-newer ↗duration-string ↗2.26.9 ↗2.26.9+: off ↗exclude-newer-override ↗2.29.1 ↗Package names, normalized before matching; no wildcards ↗applies ❓ ↗
Pipenvcool-down-period ↗Pipfile ↗none ❓ ↗duration-string ↗2026.6.2 ↗2026.6.2+: off ↗none ❓ ↗--applies ❓ ↗
Composerconfig.policy.cooldown.period ↗composer.json ↗none ❓ ↗duration-string ↗2.11.0 ↗2.11.0+: off ↗config.policy.cooldown.ignore ↗2.11.0 ↗Package names with * wildcards, e.g. vendor/* ↗applies ❓ ↗
Bundlercooldown ↗Gemfile, gems.rb ↗--cooldown ↗days ↗4.0.13 ↗4.0.13+: off ↗none ❓ ↗--applies ↗
RenovateminimumReleaseAge ↗renovate.json, renovate.jsonc, renovate.json5, .github/renovate.json, .github/renovate.jsonc, .github/renovate.json5, .gitlab/renovate.json, .gitlab/renovate.jsonc, .gitlab/renovate.json5, .renovaterc, .renovaterc.json, .renovaterc.jsonc, .renovaterc.json5 ↗--minimum-release-age ↗duration-string ↗35.46.0 ↗all versions: off ↗packageRules: matchPackageNames + minimumReleaseAge: null ↗35.46.0 ❓ ↗matchPackageNames: exact names, globs such as @org/** (with ! negation) or /regex/; case-insensitive ↗bypass ↗
Dependabotcooldown ↗.github/dependabot.yml, .github/dependabot.yaml ↗none ❓ ↗days ↗2025-07-01 ↗2025-07-01+: off
2026-07-14+: 3 ↗
cooldown.exclude ↗2025-07-01 ❓ ↗Dependency names with * wildcards, up to 150 entries; exclude always wins over include ↗bypass ↗

Install scripts

Whether dependency lifecycle scripts run, and how to allow specific packages.

ToolDefault policyAllow-list settingAllow-list fileAllow-list sinceAllow-list formatDisable all
npmearlier: run
11.16.0+: run-with-warning
12.0.0+: deny-except-allowlist ↗
allowScripts ↗package.json ↗11.16.0 ↗Object keyed by name, name@version or name@v1 || v2 with true (allow) or false (deny); npm install-scripts approve writes pinned name@version entries ❓ ↗ignore-scripts ↗
pnpmearlier: run
10.0.0+: deny-except-allowlist ↗
allowBuilds ↗pnpm-workspace.yaml ↗10.26.0 ↗Map of package matcher to true (allow) or false (deny), e.g. esbuild: true or "nx@21.6.4 || 21.6.5": true; a bare name never approves git or tarball dependencies (pnpm 11+) ↗ignoreScripts ↗
Yarn (Berry)2.0.0+: run
4.14.0+: deny-except-allowlist ↗
dependenciesMeta.<package>.built ↗package.json ↗2.0.0 ❓ ↗Object keyed by package name or name@version: { built: true } allows a package when enableScripts is false; { built: false } denies it when enableScripts is true ↗enableScripts: false ↗
Bunall versions: deny-except-allowlist ↗trustedDependencies ↗package.json ↗1.0.5 ❓ ↗Array of package names, e.g. ["node-sass"] ↗install.ignoreScripts ↗
Denoall versions: deny-except-allowlist ↗allowScripts ↗deno.json ↗2.6.0 ↗true, an array of npm: constraints (semver ranges allowed, tags rejected) or { "allow": ..., "deny": [...] } ↗allowScripts: false ❓ ↗
uvall versions: run ↗no-binary-package ↗pyproject.toml ↗0.2.12 ↗A list of package names ↗no-build ↗
pipall versions: run ↗--no-binary ↗requirements.txt ↗7.0.0 ❓ ↗One option line per package or a comma-separated list, e.g. --no-binary=docopt ↗--only-binary=:all: ↗
Poetryall versions: run ↗installer.no-binary ↗poetry.toml ↗2.2.0 ↗A list of package names, or :all: or :none: ↗installer.only-binary ↗
PDMall versions: run ↗no-binary ↗pyproject.toml ↗2.15.0 ↗A comma-separated string or a list of package names, or :all: ↗only-binary ↗
Pipenvall versions: run ↗none ❓ ↗---none ❓ ↗
Composerearlier: run
2.2.0+: deny-except-allowlist ↗
config.allow-plugins ↗composer.json ↗2.2.0 ↗An object of package name patterns (vendor/*) to true (allow) or false (disallow without asking); true allows every plugin and false none ↗config.allow-plugins: false ↗
Bundlerall versions: run ↗none ❓ ↗---none ❓ ↗
Renovateall versions: deny ↗none ❓ ↗---ignoreScripts: true ↗
Dependabotall versions: deny ❓ ↗none ↗---none ❓ ↗

Project files

How depcurfew recognizes each package manager in a repository.

ToolLockfilesManifestsWorkspacesObject form key
npmearlier: npm-shrinkwrap.json, package-lock.json
12.0.0+: package-lock.json ↗
package.json ↗{"files":["package.json"],"key":"workspaces"} ↗packages ❓ ↗
pnpmall versions: pnpm-lock.yaml ↗package.json, package.json5, package.yaml ↗{"files":["pnpm-workspace.yaml"],"key":"packages"} ↗none ❓ ↗
Yarn (Berry)all versions: yarn.lock ↗package.json ↗{"files":["package.json"],"key":"workspaces"} ↗packages ❓ ↗
Bunearlier: bun.lockb
1.2.0+: bun.lock, bun.lockb ❓ ↗
package.json ↗{"files":["package.json"],"key":"workspaces"} ↗packages ↗
Denoall versions: deno.lock ↗deno.json, deno.jsonc ↗{"files":["deno.json","deno.jsonc"],"key":"workspace"} ↗members ↗
uvall versions: uv.lock ↗pyproject.toml ↗{"files":["pyproject.toml"],"key":"tool.uv.workspace","excludeKey":"exclude"} ↗members ↗
pip25.1.0+: pylock.toml ↗requirements.txt ↗none ❓ ↗none ❓ ↗
Poetryall versions: poetry.lock ↗pyproject.toml ↗none ❓ ↗none ❓ ↗
PDMall versions: pdm.lock ↗pyproject.toml ↗none ❓ ↗none ❓ ↗
Pipenvall versions: Pipfile.lock ↗Pipfile ↗none ❓ ↗none ❓ ↗
Composerall versions: composer.lock ↗composer.json ↗none ❓ ↗none ❓ ↗
Bundlerall versions: Gemfile.lock, gems.locked ↗Gemfile, gems.rb ↗none ❓ ↗none ❓ ↗

Dependency sources

Settings that allow or forbid dependencies from git, remote tarballs and local paths.

ToolSettingValuesSinceDefault
npm · gitallow-git ↗all, none, root ↗⚠️ 11.9.0 ↗ / 11.10.0 ↗11.9.0+: all
12.0.0+: none ↗
npm · remote tarballallow-remote ↗all, none, root ↗⚠️ 11.14.0 ↗ / 11.15.0 ↗11.14.0+: all
12.0.0+: none ↗
npm · local tarballallow-file ↗all, none, root ↗⚠️ 11.14.0 ↗ / 11.15.0 ↗11.14.0+: all ↗
npm · local directoryallow-directory ↗all, none, root ↗⚠️ 11.14.0 ↗ / 11.15.0 ↗11.14.0+: all ↗
pnpm · gitblockExoticSubdeps ↗true, false ↗10.26.0 ↗10.26.0+: false
11.0.0+: true ↗
pnpm · remote tarballblockExoticSubdeps ↗true, false ↗10.26.0 ↗10.26.0+: false
11.0.0+: true ↗
pnpm · local tarballnone ❓ ↗---
pnpm · local directorynone ❓ ↗---
Yarn (Berry) · gitapprovedGitRepositories ↗repository URL glob patterns, e.g. https://github.com/org/* ↗4.14.0 ↗4.14.0+: [] (every git dependency is blocked) ↗
Yarn (Berry) · remote tarballnone ❓ ↗---
Yarn (Berry) · local tarballnone ❓ ↗---
Yarn (Berry) · local directorynone ❓ ↗---
Bun · gitnone ❓ ↗---
Bun · remote tarballnone ❓ ↗---
Bun · local tarballnone ❓ ↗---
Bun · local directorynone ❓ ↗---
Deno · gitnone ↗---
Deno · remote tarballnone ↗---
Deno · local tarballnone ↗---
Deno · local directorynone ↗---
uv · gitnone ❓ ↗---
uv · remote tarballnone ❓ ↗---
uv · local tarballnone ❓ ↗---
uv · local directorynone ❓ ↗---
pip · gitnone ❓ ↗---
pip · remote tarballnone ❓ ↗---
pip · local tarballnone ❓ ↗---
pip · local directorynone ❓ ↗---
Poetry · gitnone ❓ ↗---
Poetry · remote tarballnone ❓ ↗---
Poetry · local tarballnone ❓ ↗---
Poetry · local directorynone ❓ ↗---
PDM · gitnone ❓ ↗---
PDM · remote tarballnone ❓ ↗---
PDM · local tarballnone ❓ ↗---
PDM · local directorynone ❓ ↗---
Pipenv · gitnone ❓ ↗---
Pipenv · remote tarballnone ❓ ↗---
Pipenv · local tarballnone ❓ ↗---
Pipenv · local directorynone ❓ ↗---
Composer · gitnone ❓ ↗---
Composer · remote tarballnone ❓ ↗---
Composer · local tarballnone ❓ ↗---
Composer · local directorynone ❓ ↗---
Bundler · gitnone ❓ ↗---
Bundler · remote tarballnone ❓ ↗---
Bundler · local tarballnone ❓ ↗---
Bundler · local directorynone ❓ ↗---

Additional facts

Further facts used by generators and doctor.

npm

  • environmentNames (✅ verified): {"prefix":"npm_config_","match":"any-case"} ↗
  • localPrefix (✅ verified): {"markers":{"file":"package.json","directory":"node_modules"},"workspaceRoot":true,"workspacesField":"workspaces","workspacesObjectKey":"packages","prefixOption":"--prefix","workspacesOption":"--workspaces","projectFile":".npmrc"} ↗
  • childEnvironment (✅ verified): {"marker":"npm_execpath","prefix":"npm_config_"} ↗
  • denyList (✅ verified): {"file":"package.json","setting":"allowScripts","value":false,"since":"11.16.0"} ↗
  • trustedPublishing (✅ verified): {"minimumNpm":"11.5.1","minimumNode":"22.14.0","githubPermission":"id-token: write","automaticProvenance":true,"firstPublishWithinDays":2} ↗
  • stagedPublishing (✅ verified): {"minimumNpm":"11.15.0","minimumNode":"22.14.0","stage":"npm stage publish","approve":"npm stage approve","reject":"npm stage reject","newPackagePlaceholder":"0.0.0-stage"} ↗
  • trustCommand (✅ verified): {"command":"npm trust github","minimumNpm":"11.15.0","packageMustExist":true,"permissions":["--allow-publish","--allow-stage-publish"]} ↗
  • tarballIdentity (✅ verified): {"separator":"/-/","extension":".tgz","scopeSeparator":"/|%2f","version":"semver"} ↗
  • lockfileFormat (✅ verified): {"installScripts":"hasInstallScript","gitPrefixes":["git+","git:"],"filePrefix":"file:","linkFlag":"link","registryTarball":"^https?://[^/]+/.+/-/[^/]+-\\d","specWithoutResolved":"version","dependencyFields":["dependencies","optionalDependencies","peerDependencies","devDependencies"]} ↗
  • overrides (✅ verified): {"field":"overrides","selfKey":"."} ↗
  • npmrcScope (✅ verified): {"read":"project root","workspacePackages":"ignored","globalMode":"ignored"} ↗
  • npmrcFormat (✅ verified): {"commentLines":["#",";"],"inlineComments":["#",";"],"escape":"\\","sectionHeader":"^\\[([^\\]]*)\\]\\s*$","keyWithoutValue":"true","settingsFrom":"top level"} ↗
  • npmrcListSyntax (✅ verified): [] ↗
  • allowAllScripts (✅ verified): {"setting":"dangerously-allow-all-scripts","since":"11.16.0","value":true} ↗
  • excludeWildcards (✅ verified): {"since":"11.17.0","trailingOnly":false} ↗
  • latestVersion (✅ verified): 12.2.1 ↗
  • lineReleases (✅ verified): 6.14.18, 7.24.2, 8.19.4, 9.0.1, 9.1.3, 9.2.0, 9.3.1, 9.4.2, 9.5.1, 9.6.7, 9.7.2, 9.8.1, 9.9.4, 10.0.0, 10.1.0, 10.2.5, 10.3.0, 10.4.0, 10.5.2, 10.6.0, 10.7.0, 10.8.3, 10.9.9, 11.0.0, 11.1.0, 11.2.0, 11.3.0, 11.4.2, 11.5.2, 11.6.4, 11.7.0, 11.8.0, 11.9.0, 11.10.1, 11.11.1, 11.12.1, 11.13.0, 11.14.1, 11.15.0, 11.16.0, 11.17.0, 11.18.0, 11.19.1, 11.20.0, 11.21.1, 12.0.2, 12.1.0, 12.2.1 ↗
  • rangeInstall (✅ verified): {"picks":"highest","prefersTag":"latest","enginesFirst":true} ↗
  • beforeInteraction (✅ verified): {"setting":"before","exclusive":{"since":"11.10.0","until":"11.15.0"},"beforeWinsSince":"11.15.0"} ↗
  • strictAllowScripts (✅ verified): {"setting":"strict-allow-scripts","value":true,"since":"11.16.0"} ↗
  • strictAllowScriptsEffect (✅ verified): 11.16.0+: the install fails instead of running the script with a notice
    12.0.0+: the install fails instead of blocking the script with a warning ↗
  • unknownNpmrcKeys (✅ verified): unknown keys in .npmrc files only warn unless strict-npmrc is set; unknown command-line flags throw since npm 12 ↗
  • commandLine (✅ verified): {"add":[["npm","install"],["npm","add"],["npm","i"],["npm","in"],["npm","ins"],["npm","inst"],["npm","insta"],["npm","instal"],["npm","isnt"],["npm","isnta"],["npm","isntal"],["npm","isntall"],["npm","install-test"],["npm","it"]],"run":[{"command":["npx"],"packageOptions":["--package","-p"],"lineOptions":["--call","-c"]},{"command":["npm","exec"],"packageOptions":["--package"],"lineOptions":["--call","-c"]},{"command":["npm","x"],"packageOptions":["--package"],"lineOptions":["--call","-c"]}],"create":[{"command":["npm","init"],"packageOptions":[]},{"command":["npm","create"],"packageOptions":[]},{"command":["npm","innit"],"packageOptions":[]}],"createNames":"prefix","valueOptions":[]} ↗
  • runnerOptions (✅ verified): {"beforeCommand":[{"command":["npm","exec"],"values":"separate"},{"command":["npm","x"],"values":"separate"}],"amongArguments":[["npm","exec"],["npm","x"]]} ↗
  • valueOptions (✅ verified): --access, --allow-directory, --allow-file, --allow-git, --allow-remote, --allow-scripts, --also, --audit-level, --auth-type, --before, --ca, --cache, --cache-max, --cache-min, --cafile, --call, --cert, --cidr, --cpu, --depth, --diff, --diff-dst-prefix, --diff-src-prefix, --diff-unified, --edit-dir, --editor, --expect-result-count, --expires, --extension-file, --fetch-retries, --fetch-retry-factor, --fetch-retry-maxtimeout, --fetch-retry-mintimeout, --fetch-timeout, --git, --global-ignore-file, --globalconfig, --heading, --https-proxy, --include, --init-author-email, --init-author-name, --init-author-url, --init-license, --init-module, --init-type, --init-version, --install-strategy, --key, --libc, --local-address, --location, --lockfile-version, --loglevel, --logs-dir, --logs-max, --maxsockets, --message, --min-release-age, --min-release-age-exclude, --name, --node-gyp, --node-options, --noproxy, --omit, --only, --orgs, --orgs-permission, --os, --otp, --pack-destination, --package, --packages, --packages-and-scopes-permission, --password, --patches-dir, --prefix, --preid, --provenance-file, --proxy, --registry, --replace-registry-host, --save-prefix, --sbom-format, --sbom-type, --scope, --scopes, --script-shell, --searchexclude, --searchlimit, --searchopts, --searchstaleness, --shell, --tag, --tag-version-prefix, --to, --token-description, --umask, --user-agent, --userconfig, --viewer, --which, --workspace, -C, -L, -c, -m, -w ↗
  • flagOptions (✅ verified): --all, --allow-same-version, --allow-scripts-pending, --allow-scripts-pin, --allow-unused-patches, --audit, --bin-links, --browser, --bypass-2fa, --color, --commit-hooks, --dangerously-allow-all-scripts, --description, --dev, --diff-ignore-all-space, --diff-name-only, --diff-no-prefix, --diff-text, --dry-run, --engine-strict, --expect-results, --force, --foreground-scripts, --format-package-lock, --fund, --git-tag-version, --global, --global-style, --if-present, --ignore-existing, --ignore-extension, --ignore-patch-failures, --ignore-scripts, --include-attestations, --include-staged, --include-workspace-root, --init-private, --install-links, --json, --keep-edit-dir, --legacy-bundling, --legacy-peer-deps, --link, --long, --offline, --omit-lockfile-registry-resolved, --optional, --package-lock, --package-lock-only, --packages-all, --parseable, --prefer-dedupe, --prefer-offline, --prefer-online, --production, --progress, --provenance, --read-only, --rebuild-bundle, --save, --save-bundle, --save-dev, --save-exact, --save-optional, --save-peer, --save-prod, --shrinkwrap, --sign-git-commit, --sign-git-tag, --strict-allow-scripts, --strict-npmrc, --strict-peer-deps, --strict-ssl, --timing, --unicode, --update-notifier, --usage, --version, --versions, --workspaces, --workspaces-update, --yes ↗
  • parsing (✅ verified): {"abbreviations":true,"anyDashes":true,"negation":"--no-","shorthands":{"enjoy-by":["--before"],"d":["--loglevel","info"],"dd":["--loglevel","verbose"],"ddd":["--loglevel","silly"],"quiet":["--loglevel","warn"],"q":["--loglevel","warn"],"s":["--loglevel","silent"],"silent":["--loglevel","silent"],"verbose":["--loglevel","verbose"],"desc":["--description"],"help":["--usage"],"local":["--no-global"],"n":["--no-yes"],"no":["--no-yes"],"porcelain":["--parseable"],"readonly":["--read-only"],"reg":["--registry"],"iwr":["--include-workspace-root"],"ws":["--workspaces"],"a":["--all"],"c":["--call"],"f":["--force"],"g":["--global"],"L":["--location"],"l":["--long"],"m":["--message"],"p":["--parseable"],"C":["--prefix"],"S":["--save"],"B":["--save-bundle"],"D":["--save-dev"],"E":["--save-exact"],"O":["--save-optional"],"P":["--save-prod"],"?":["--usage"],"H":["--usage"],"h":["--usage"],"v":["--version"],"w":["--workspace"],"y":["--yes"]}} ↗
  • versionSelection (✅ verified): {"tagOption":"--tag","tagVariable":"npm_config_tag","tagKey":"tag","bareRange":"*"} ↗
  • packageSpecs (✅ verified): {"git":["git://","git+ssh://","git+http://","git+https://","git+file://","github:","gist:","bitbucket:","gitlab:"],"local":["file:"],"workspace":[],"alias":"npm:","remoteTarball":["http://","https://"],"tarballExtensions":[".tar",".tar.gz",".tgz"],"shorthand":"github:"} ↗
  • registryConfig (✅ verified): {"file":".npmrc","userFile":"~/.npmrc","key":"registry","scopeKeySuffix":":registry"} ↗
  • globalConfig (✅ verified): {"userKey":"userconfig","globalKey":"globalconfig","prefixKey":"prefix","file":"etc/npmrc","prefixVariable":"PREFIX","destDirVariable":"DESTDIR","execPathLevels":{"win32":1,"other":2},"order":["cli","env","project","user","global","builtin"]} ↗
  • registryHostTarballs (✅ verified): {"dependencies":"registry specs","match":"origin and path"} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--registry","--@<scope>:registry"],"registryVariables":["npm_config_registry"],"configOptions":["--userconfig","--globalconfig"],"configVariables":["npm_config_userconfig","npm_config_globalconfig"]} ↗
  • configCommands (✅ verified): {"command":["npm","config"],"writes":["set","delete","rm","del","edit","fix"]}, {"command":["npm","set"],"operands":1}, {"command":["npm","pkg"],"writes":["set","delete","fix"],"manifest":true} ↗
  • linkCommands (✅ verified): npm, link ↗
  • commandNames (✅ verified): {"commands":["access","approve-scripts","audit","bugs","cache","ci","completion","config","dedupe","deny-scripts","deprecate","diff","dist-tag","docs","doctor","edit","exec","explain","explore","find-dupes","fund","get","help","help-search","init","install","install-ci-test","install-scripts","install-test","link","ll","login","logout","ls","org","outdated","owner","pack","patch","ping","pkg","prefix","profile","prune","publish","query","rebuild","repo","restart","root","run","sbom","search","set","stage","start","stop","team","test","token","trust","undeprecate","uninstall","unpublish","update","version","view","whoami"],"aliases":{"author":"owner","home":"docs","issues":"bugs","info":"view","show":"view","find":"search","add":"install","unlink":"uninstall","remove":"uninstall","rm":"uninstall","r":"uninstall","un":"uninstall","rb":"rebuild","list":"ls","ln":"link","create":"init","i":"install","it":"install-test","cit":"install-ci-test","u":"update","up":"update","c":"config","s":"search","se":"search","tst":"test","t":"test","ddp":"dedupe","v":"view","run-script":"run","clean-install":"ci","clean-install-test":"install-ci-test","x":"exec","why":"explain","la":"ll","verison":"version","ic":"ci","innit":"init","in":"install","ins":"install","inst":"install","insta":"install","instal":"install","isnt":"install","isnta":"install","isntal":"install","isntall":"install","install-clean":"ci","isntall-clean":"ci","hlep":"help","dist-tags":"dist-tag","upgrade":"update","udpate":"update","rum":"run","sit":"install-ci-test","urn":"run","ogr":"org"}} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--min-release-age","weakens":"delay","values":"delay"},{"name":"--before","weakens":"delay","values":"any"},{"name":"--min-release-age-exclude","weakens":"delay","values":"any"},{"name":"--ignore-scripts","weakens":"scripts","values":{"except":["true"]}},{"name":"--dangerously-allow-all-scripts","weakens":"scripts","values":{"except":["false","null","undefined"]}},{"name":"--allow-scripts","weakens":"scripts","values":"any"}],"variables":[{"name":"npm_config_min_release_age","weakens":"delay","values":"delay"},{"name":"npm_config_before","weakens":"delay","values":"any"},{"name":"npm_config_min_release_age_exclude","weakens":"delay","values":"any"},{"name":"npm_config_ignore_scripts","weakens":"scripts","values":{"except":["true",""]}},{"name":"npm_config_dangerously_allow_all_scripts","weakens":"scripts","values":{"except":["false","null","undefined"]}},{"name":"npm_config_allow_scripts","weakens":"scripts","values":"any"}]} ↗
  • settingOverrides (✅ verified): {"optionPrefix":"--","negation":"--no-","variablePrefix":"npm_config_","settings":[{"setting":"strict-allow-scripts","weakens":"scripts","values":["false","null","undefined"],"when":"written"},{"setting":"allow-git","weakens":"sources","source":"git","values":{"except":["none"]}},{"setting":"allow-remote","weakens":"sources","source":"remoteTarball","values":{"except":["none"]}},{"setting":"allow-file","weakens":"sources","source":"file","values":{"except":["none"]}},{"setting":"allow-directory","weakens":"sources","source":"directory","values":{"except":["none"]}}]} ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--prefix","moves":"directory","localPrefix":true}],"variables":[]} ↗
  • booleanWords (✅ verified): true ↗
  • installCommands (✅ verified): {"install":["install","add","i","in","ins","inst","insta","instal","isnt","isnta","isntal","isntall","install-test","it"],"clean":["ci","clean-install","ic","install-clean","isntall-clean","install-ci-test","cit","clean-install-test","sit"],"update":["update","up","upgrade","udpate"]} ↗
  • globalOption (✅ verified): --global, -g, --location=global ↗
  • unknownConfigKeys (✅ verified): earlier: ignored
    11.2.0+: warning ↗
  • lockfileInstalls (❓ uncertain): npm ci installs versions pinned in package-lock.json without applying min-release-age ❓ ↗
  • cleanInstall (✅ verified): {"commands":"clean","installsLockedVersions":true,"failsWhenOutOfSync":true,"writesLockfile":false} ↗
  • scriptsOff (✅ verified): {"option":"--ignore-scripts","variable":"npm_config_ignore_scripts","anyCase":true,"value":"true"} ↗
  • nodeEngines (✅ verified): {"since":"11.0.0","node":"^20.17.0 || >=22.9.0"}, {"since":"12.0.0","node":"^22.22.2 || ^24.15.0 || >=26.0.0"} ↗
  • rootLifecycleScripts (✅ verified): {"events":["preinstall","install","postinstall","prepublish","preprepare","prepare","postprepare"],"skippedBy":"ignore-scripts","allowListApplies":false} ↗
  • omitOptional (✅ verified): {"omit":{"setting":"omit","value":"optional"},"alias":{"setting":"optional","off":false},"include":{"setting":"include"},"variablePrefix":"npm_config_","listSeparator":"\n\n"} ↗

pnpm

  • environmentNames (✅ verified): {"prefix":"pnpm_config_","match":"lower-or-upper"}, {"prefix":"npm_config_","match":"any-case"} ↗
  • denyList (✅ verified): {"file":"pnpm-workspace.yaml","setting":"allowBuilds","value":false,"since":"10.26.0"} ↗
  • projectInstall (✅ verified): {"commands":["install","i"],"bare":false} ↗
  • commandLine (✅ verified): {"add":[["pnpm","add"]],"run":[{"command":["pnx"],"packageOptions":["--package"],"shellOptions":["--shell-mode","-c"]},{"command":["pnpx"],"packageOptions":["--package"],"shellOptions":["--shell-mode","-c"]},{"command":["pnpm","dlx"],"packageOptions":["--package"],"shellOptions":["--shell-mode","-c"]}],"create":[{"command":["pnpm","create"],"packageOptions":[]}],"createNames":"prefix-unless-prefixed","valueOptions":["--save-prefix","--save-catalog-name","--lockfile-dir","--filter","-F","--registry","--allow-build","--cpu","--os","--libc","-C","--dir","--workspace-packages","--env-file","--reporter","--loglevel"]} ↗
  • runnerOptions (✅ verified): {"beforeCommand":[{"command":["pnpm","dlx"],"values":"separate"}]} ↗
  • packageSpecs (✅ verified): {"git":["github:","bitbucket:","gitlab:","gist:","git+ssh://"],"local":["link:","file:"],"workspace":["workspace:"],"remoteTarball":["http://","https://"],"tarballExtensions":[".tar",".tar.gz",".tgz"],"shorthand":"github:"} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--registry","--@<scope>:registry"],"registryVariables":["pnpm_config_registry"],"configOptions":["--userconfig","--npmrc-auth-file"],"configVariables":["pnpm_config_npmrc_auth_file","pnpm_config_userconfig"]} ↗
  • parsing (✅ verified): {"abbreviations":true,"anyDashes":true,"negation":"--no-","settingPrefix":"--config.","shorthands":{"s":["--reporter=silent"],"d":["--loglevel=info"],"dd":["--loglevel=verbose"],"ddd":["--loglevel=silly"],"L":["--latest"],"r":["--recursive"],"silent":["--reporter=silent"],"verbose":["--loglevel=verbose"],"quiet":["--loglevel=warn"],"q":["--loglevel=warn"],"h":["--help"],"H":["--help"],"?":["--help"],"usage":["--help"],"v":["--version"],"f":["--force"],"local":["--no-global"],"l":["--long"],"p":["--parseable"],"porcelain":["--parseable"],"prod":["--production"],"development":["--dev"],"g":["--global"],"S":["--save"],"D":["--save-dev"],"P":["--save-prod"],"E":["--save-exact"],"O":["--save-optional"],"C":["--dir"],"w":["--workspace-root"],"i":["--interactive"],"F":["--filter"],"y":["--yes"]}} ↗
  • booleanWords (✅ verified): true ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--dir","moves":"directory"}],"variables":[]} ↗
  • configCommands (✅ verified): {"command":["pnpm","config"],"writes":["set","delete"]}, {"command":["pnpm","c"],"writes":["set","delete"]}, {"command":["pnpm","pkg"],"writes":["set","delete","fix"],"manifest":true} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--ignore-scripts","weakens":"scripts","values":{"except":["true"]}},{"name":"--ignoreScripts","weakens":"scripts","values":{"except":["true"]}},{"name":"--allow-build","weakens":"scripts","values":"any"},{"name":"--dangerouslyAllowAllBuilds","weakens":"scripts","values":{"except":["false"]}},{"name":"--dangerously-allow-all-builds","weakens":"scripts","values":{"except":["false"]}},{"name":"--minimumReleaseAge","weakens":"delay","values":"delay"},{"name":"--minimum-release-age","weakens":"delay","values":"delay"},{"name":"--minimumReleaseAgeExclude","weakens":"delay","values":"any"},{"name":"--minimum-release-age-exclude","weakens":"delay","values":"any"},{"name":"--minimumReleaseAgeStrict","weakens":"delay","values":{"except":["true"]}},{"name":"--minimum-release-age-strict","weakens":"delay","values":{"except":["true"]}}],"variables":[{"name":"pnpm_config_minimum_release_age","weakens":"delay","values":"delay"},{"name":"pnpm_config_minimum_release_age_exclude","weakens":"delay","values":"any"},{"name":"pnpm_config_minimum_release_age_strict","weakens":"delay","values":{"except":["true"]}},{"name":"pnpm_config_ignore_scripts","weakens":"scripts","values":{"except":["true"]}},{"name":"pnpm_config_dangerously_allow_all_builds","weakens":"scripts","values":["true"]},{"name":"npm_config_minimum_release_age","weakens":"delay","values":"delay"},{"name":"npm_config_dangerously_allow_all_builds","weakens":"scripts","values":{"except":["false","null","undefined"]}}]} ↗
  • minimumReleaseAgeStrict (✅ verified): {"setting":"minimumReleaseAgeStrict","value":true,"since":"11.0.0"} ↗
  • cooldownExactVersions (✅ verified): 10.17.0 ↗
  • lockfileDocuments (✅ verified): {"bootMarker":"---","graph":"last"} ↗
  • lockfileFormat (✅ verified): {"installScripts":null,"gitKeyPrefix":"git+","gitHostedFlag":"gitHosted","gitHostedTarballHosts":["codeload.github.com","bitbucket.org","gitlab.com"],"gitType":"git","directoryType":"directory"} ↗
  • npmrcPrecedence (✅ verified): {"winner":"pnpm-workspace.yaml","over":[".npmrc","npm_config_*"]} ↗
  • npmrcCooldownKey (✅ verified): {"key":"minimum-release-age","until":"11.0.0"} ↗
  • sharedWorkspaceLockfile (✅ verified): {"setting":"sharedWorkspaceLockfile","npmrcKey":"shared-workspace-lockfile","default":true} ↗
  • perProjectNpmrc (❓ uncertain): {"sharedWorkspaceLockfile":false,"until":"11.0.0"} ❓ ↗
  • ignoredSince (✅ verified): {"since":"11.0.0","npmrc":"auth and registry settings","packageJsonField":"pnpm"} ↗
  • lockfileRecheck (❓ uncertain): 10.16.0+: false
    11.1.3+: true ❓ ↗
  • allowAllBuilds (✅ verified): {"setting":"dangerouslyAllowAllBuilds","since":"10.9.0","value":true,"off":[false,0,null,""]} ↗
  • excludeWildcards (✅ verified): {"since":"10.17.0","trailingOnly":false} ↗
  • onlyBuiltDependencies (✅ verified): {"since":"6.32.1","workspaceFileSince":"10.5.0","removedIn":"11.0.0"} ↗
  • ignoredBuiltDependencies (✅ verified): {"since":"10.1.0","workspaceFileSince":"10.5.0"} ↗
  • npmrcBuildSettings (✅ verified): {"allowAll":{"key":"dangerously-allow-all-builds","off":["false","null","undefined"],"since":"10.9.0"},"until":"11.0.0","projectKeys":[{"since":"10.13.0","value":["dangerouslyAllowAllBuilds","onlyBuiltDependencies","onlyBuiltDependenciesFile","neverBuiltDependencies"]},{"since":"10.26.0","value":["dangerouslyAllowAllBuilds","onlyBuiltDependencies","onlyBuiltDependenciesFile","neverBuiltDependencies","allowBuilds"]}]} ↗
  • yamlMergeKeys (✅ verified): true ↗
  • latestVersion (✅ verified): 12.16.1 ↗
  • npmrcIgnored (✅ verified): pnpm 11+ reads only auth and registry settings from .npmrc, ignores the package.json "pnpm" field and no longer reads npm_config_* variables ↗
  • buildPermissions (✅ verified): {"setting":"permissions","capability":"build","since":"12.11.0","allow":true,"deny":false} ↗
  • legacyAllowList (✅ verified): 10.0.0+: onlyBuiltDependencies (package.json pnpm field; pnpm-workspace.yaml since 10.5.0)
    10.26.0+: allowBuilds; onlyBuiltDependencies and ignoredBuiltDependencies deprecated
    11.0.0+: allowBuilds only; onlyBuiltDependencies, neverBuiltDependencies and ignoredBuiltDependencies removed ↗
  • strictDepBuilds (✅ verified): 10.3.0+: false
    11.0.0+: true ↗
  • strictMode (✅ verified): 11.0.0+: minimumReleaseAgeStrict defaults to false
    11.0.4+: strict whenever minimumReleaseAge is set explicitly
    12.0.0+: explicit values treated as non-strict (regression)
    12.3.0+: strict whenever minimumReleaseAge is set explicitly ↗
  • ignoreMissingTime (✅ verified): minimumReleaseAgeIgnoreMissingTime defaults to true: packages whose registry metadata has no publish time skip the age check ↗
  • lockfileVerification (❓ uncertain): 10.16.0+: frozen-lockfile installs do not re-check versions already in the lockfile
    11.1.3+: lockfile entries are re-checked; trustLockfile: true (11.3.0) turns this off ❓ ↗
  • unknownWorkspaceKeys (✅ verified): pnpm 11 and earlier silently ignore misspelled pnpm-workspace.yaml settings; pnpm 12 warns ↗
  • tarballResolution (✅ verified): {"field":"tarball"} ↗
  • rootLifecycleScripts (✅ verified): {"events":["preinstall","install","postinstall","preprepare","prepare","postprepare"],"skippedBy":"ignoreScripts","allowListApplies":false} ↗
  • managesOwnVersion (✅ verified): {"since":"10.0.0","field":"packageManager"} ↗
  • configIncludes (✅ verified): {"since":"12.15.0","file":"pnpm-workspace.yaml","key":"include","unrestricted":"*","localPrefixes":["./","../"],"localExtensions":[".yaml",".yml"],"globCharacters":"*?[]{}","spellings":{"enableGlobalVirtualStore":"virtualStoreType","nodeExperimentalPackageMap":"nodePackageMap","nodePackageMapType":"nodePackageMap","noproxy":"noProxy","proxy":"httpsProxy","permissions":"allowBuilds","auditConfig":"audit","auditLevel":"audit","cleanupUnusedCatalogs":"catalogPrune","maxsockets":"maxSockets","namedRegistries":"registries","updateConfig":"update"},"notForDependencies":["bootConfig","cacheDir","configDependencies","globalBinDir","globalDir","globalPnpmfile","globalVirtualStoreDir","lockfileDir","modulesDir","npmrcAuthFile","onlyBuiltDependenciesFile","packages","patchedDependencies","patchesDir","pnpmfile","scriptShell","stateDir","storeDir","virtualStoreDir"],"dependencies":"configDependencies"} ↗
  • bootConfig (✅ verified): {"since":"12.15.0","setting":"bootConfig","settings":["minimumReleaseAge","minimumReleaseAgeExclude","minimumReleaseAgeStrict","minimumReleaseAgeIgnoreMissingTime","trustPolicy","trustPolicyExclude","trustPolicyIgnoreAfter"]} ↗
  • pnpmfiles (✅ verified): {"updateConfigSince":"10.8.0","defaults":[{"since":"6.0.0","value":[".pnpmfile.cjs"]},{"since":"11.0.0","value":[".pnpmfile.mjs",".pnpmfile.cjs"]}],"setting":"pnpmfile","ignore":"ignorePnpmfile","global":"globalPnpmfile"} ↗
  • configPlugins (✅ verified): {"setting":"configDependencies","patterns":[{"since":"10.13.0","value":["pnpm-plugin-*","@pnpm/plugin-*"]},{"since":"10.15.0","value":["pnpm-plugin-*","@pnpm/plugin-*","@*/pnpm-plugin-*"]}]} ↗
  • knownPlugins (✅ verified): {"name":"@pnpm/plugin-better-defaults","since":"0.3.0","settings":{"minimumReleaseAge":1440,"blockExoticSubdeps":true}} ↗

Yarn (Berry)

  • environmentNames (✅ verified): {"prefix":"YARN_","match":"any-case"} ↗
  • registrySettings (✅ verified): {"file":".yarnrc.yml","path":["npmRegistryServer"],"applies":"all","effect":"replaces"}, {"file":".yarnrc.yml","path":["npmScopes","*","npmRegistryServer"],"applies":"scope","effect":"replaces"} ↗
  • yamlMergeKeys (✅ verified): false ↗
  • classicUserFile (✅ verified): {"until":"2.0.0","file":".yarnrc"} ↗
  • yarnPath (❓ uncertain): {"key":"yarnPath","releaseFile":"yarn-<version>.cjs","variables":["YARN_YARN_PATH","YARN_IGNORE_PATH"]} ❓ ↗
  • yarnPathRuns (✅ verified): {"file":".yarnrc.yml","key":"yarnPath","classicSince":"1.18.0"} ↗
  • setVersion (✅ verified): {"command":"yarn set version","releases":".yarn/releases","sets":["yarnPath","packageManager"]} ↗
  • classicLockfile (✅ verified): {"lockfileVersion":1,"versionComment":"^yarn lockfile v(\\d+)$","version":"version","resolved":"resolved","hash":"#","alias":"npm:","gitResolved":"^git(\\+[a-z0-9]+)?://","local":["file:","link:","./","../","/"]} ↗
  • denyList (✅ verified): {"file":"package.json","setting":"dependenciesMeta.<package>.built","value":false,"since":"2.0.0"} ↗
  • projectInstall (✅ verified): {"commands":["install"],"bare":true} ↗
  • commandLine (✅ verified): {"add":[["yarn","add"]],"run":[{"command":["yarn","dlx"],"packageOptions":["-p","--package"]}],"create":[{"command":["yarn","create"],"packageOptions":["-p","--package"]}],"createNames":"prefix-unless-prefixed","workspaceCommands":[{"command":["yarn","workspace"],"operands":1}],"valueOptions":["--mode"]} ↗
  • runnerOptions (✅ verified): {"beforeCommand":[{"command":["yarn","dlx"],"values":"separate"},{"command":["yarn","create"],"values":"separate"}]} ↗
  • packageSpecs (✅ verified): {"git":[],"local":["link:","portal:","file:"],"workspace":["workspace:"]} ↗
  • registryOverrides (✅ verified): {"registryOptions":[],"registryVariables":["YARN_NPM_REGISTRY_SERVER"],"configOptions":[],"configVariables":["YARN_RC_FILENAME"]} ↗
  • registryFetch (✅ verified): {"protocol":"npm:","patch":"patch:","patchEnd":"#","params":"?"} ↗
  • lockfileFormat (✅ verified): {"installScripts":null,"registry":"npm:","workspace":"workspace:","patch":"patch:","file":"file:","directory":["portal:","link:"],"gitCommit":"#commit=","tarball":"\\.(?:tar\\.gz|tgz)$"} ↗
  • durationStrings (✅ verified): {"since":"4.11.0","syntax":"compact","before":"no effect"} ↗
  • scriptsSwitch (✅ verified): {"setting":"enableScripts","allow":true,"deny":false,"off":[false,0,"false","0"]} ↗
  • excludeWildcards (✅ verified): {"since":"4.10.0","trailingOnly":false} ↗
  • berryLockfileMarker (❓ uncertain): __metadata ❓ ↗
  • classicLockfileHeader (✅ verified): # yarn lockfile v1 ↗
  • latestVersion (✅ verified): 4.18.1 ↗
  • bypassFlag (✅ verified): --no-time-gate on yarn add and yarn up (4.15.0+) ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--cwd","moves":"directory","position":"first"},{"name":"--cwd","moves":"directory","position":"last","command":["yarn","add"]}],"variables":[]} ↗
  • configCommands (✅ verified): {"command":["yarn","config"],"writes":["set","unset"]} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--no-time-gate","weakens":"delay","values":"any"}],"variables":[{"name":"YARN_NPM_MINIMAL_AGE_GATE","weakens":"delay","values":"delay"},{"name":"YARN_NPM_PREAPPROVED_PACKAGES","weakens":"delay","values":"any"},{"name":"YARN_ENABLE_SCRIPTS","weakens":"scripts","values":{"except":["false","0"]}}]} ↗
  • perScopeGate (✅ verified): {"scopes":"npmScopes","setting":"npmMinimalAgeGate","since":"4.17.0","unset":"1d"} ↗
  • upgradeMigration (✅ verified): When the lockfile predates the new defaults and the key is unset, yarn install writes enableScripts: true, approvedGitRepositories: ["**"] and npmMinimalAgeGate: 0 into .yarnrc.yml ↗
  • missingPublishTime (✅ verified): Versions without a publish time are quarantined while the gate is on ↗
  • unknownSettings (❓ uncertain): Unknown keys in the project .yarnrc.yml throw (unless enableStrictSettings is false), so settings newer than the pinned Yarn break installs ❓ ↗

Bun

  • environmentNames (✅ verified): {"prefix":"","match":"exact"} ↗
  • registrySettings (✅ verified): {"file":"bunfig.toml","path":["install","registry"],"applies":"all","effect":"replaces","urlKey":"url"}, {"file":"bunfig.toml","path":["install","scopes","*"],"applies":"scope","effect":"replaces","urlKey":"url"} ↗
  • projectInstall (✅ verified): {"commands":["install"],"bare":false} ↗
  • commandLine (✅ verified): {"add":[["bun","add"]],"run":[{"command":["bunx"],"packageOptions":["-p","--package"]},{"command":["bun","x"],"packageOptions":["-p","--package"]}],"create":[{"command":["bun","create"],"packageOptions":[]}],"createNames":"prefix","valueOptions":["--omit","--filter","--ca","--cafile","--registry","--network-concurrency","--backend","--concurrent-scripts","--cache-dir","--config","--cwd","--env-file","--minimum-release-age"]} ↗
  • runnerOptions (✅ verified): {"beforeCommand":[{"command":["bun","x"],"values":"attached"}]} ↗
  • commandNames (✅ verified): {"commands":["add","audit","auth","build","check","ci","cloud","completions","config","create","dedupe","deploy","discord","exec","fmt","getcompletes","help","info","init","install","link","lint","list","login","logout","outdated","patch","patch-commit","pm","prune","publish","remove","repl","run","test","unlink","update","upgrade","use","whoami","why","x"],"aliases":{"a":"add","c":"create","i":"install","up":"update","r":"remove","rm":"remove","uninstall":"remove","bun":"build"},"matching":"exact"} ↗
  • packageSpecs (✅ verified): {"git":["github:","git+ssh://","git+https://"],"local":[],"workspace":[],"scp":true} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--registry"],"registryVariables":["BUN_CONFIG_REGISTRY"],"configOptions":["--config","-c"],"configVariables":[]} ↗
  • lockfileFormat (✅ verified): {"installScripts":"hasInstallScript","installScriptsSince":"1.4.4","git":["git+","github:"],"directory":["file:","link:"],"workspace":"workspace:","tarball":"\\.(?:tar\\.gz|tgz)$"} ↗
  • durationStrings (✅ verified): {"since":"1.4.4","syntax":"compact-or-words"} ↗
  • excludeWildcards (✅ verified): {"since":null,"trailingOnly":false} ↗
  • latestVersion (✅ verified): 1.4.4 ↗
  • trustedDependenciesReplacesDefaults (✅ verified): Adding trustedDependencies replaces the built-in trusted list, so default-trusted packages that are not listed stop running scripts ↗
  • lockedVersionsNotRechecked (✅ verified): minimumReleaseAge only affects new resolutions; versions already in bun.lock are kept ↗
  • bunxCooldown (✅ verified): bunx applies --minimum-release-age only since 1.4.4 ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--cwd","moves":"directory"}],"variables":[]} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--minimum-release-age","weakens":"delay","values":"delay"},{"name":"--trust","weakens":"scripts","values":"any"}],"variables":[]} ↗

Deno

  • denyList (✅ verified): {"file":"deno.json","setting":"allowScripts.deny","value":"npm:<package>","since":"2.6.0"} ↗
  • commandLine (✅ verified): {"add":[["deno","add"],["deno","install"]],"run":[{"command":["deno","x"],"packageOptions":["--package","-p"],"binaryPath":true},{"command":["dx"],"packageOptions":["--package","-p"],"binaryPath":true},{"command":["denox"],"packageOptions":["--package","-p"],"binaryPath":true},{"command":["dnx"],"packageOptions":["--package","-p"],"binaryPath":true}],"create":[],"createNames":"prefix","fileOptions":["--entrypoint","-e"],"valueOptions":["--name","-n","--root","--os","--arch","-L","--log-level"],"commandOptions":[{"command":["deno","x"],"valueOptions":["--package","-p","--config","-c","--import-map","--cert","--min-dep-age","--location","--seed","--preload","--require","--conditions","--inspect-publish-uid"]},{"command":["dx"],"valueOptions":["--package","-p","--config","-c","--import-map","--cert","--min-dep-age","--location","--seed","--preload","--require","--conditions","--inspect-publish-uid"]},{"command":["denox"],"valueOptions":["--package","-p","--config","-c","--import-map","--cert","--min-dep-age","--location","--seed","--preload","--require","--conditions","--inspect-publish-uid"]},{"command":["dnx"],"valueOptions":["--package","-p","--config","-c","--import-map","--cert","--min-dep-age","--location","--seed","--preload","--require","--conditions","--inspect-publish-uid"]}]} ↗
  • lockfileFormat (✅ verified): {"installScripts":"scripts","installScriptsSinceLockfile":"5","sources":null,"peerSeparator":"_"} ↗
  • durationStrings (✅ verified): {"since":null,"syntax":"iso8601"} ↗
  • cutoffDates (✅ verified): {"timestamps":true,"offsetRequired":true,"dates":"start-utc"} ↗
  • ageObjectKey (✅ verified): age ↗
  • excludeWildcards (✅ verified): {"since":"2.9.2","trailingOnly":true} ↗
  • npmSpecifierPrefix (✅ verified): npm: ↗
  • allowAllScripts (✅ verified): {"setting":"allowScripts","since":"2.6.0","value":true} ↗
  • latestVersion (✅ verified): 2.9.8 ↗
  • npmrcFormat (⚠️ disputed): ⚠️ whole days only, e.g. min-release-age=3 ↗ / a duration with a unit, e.g. min-release-age=72h ↗
  • fileLinkSkipped (⚠️ disputed): ⚠️ file: and link: dependencies in the project package.json are silently skipped ↗ / file: and link: specifiers in registry metadata of npm packages are skipped ↗
  • denoXCooldown (✅ verified): deno x honors minimumDependencyAge only since 2.9.4 ↗
  • installOverrides (✅ verified): {"options":[{"name":"--minimum-dependency-age","weakens":"delay","values":"delay"},{"name":"--min-dep-age","weakens":"delay","values":"delay"},{"name":"--allow-scripts","weakens":"scripts","values":"any"}],"variables":[]} ↗
  • dxRunsScripts (✅ verified): dx defaults to --allow-all and runs lifecycle scripts once the download prompt is accepted ↗

uv

  • machineSettings (✅ verified): {"variables":[{"name":"UV_DEFAULT_INDEX","effect":"replaces"},{"name":"UV_INDEX_URL","effect":"replaces"},{"name":"UV_INDEX","effect":"adds","list":"spaces"},{"name":"UV_EXTRA_INDEX_URL","effect":"adds","list":"spaces"},{"name":"UV_FIND_LINKS","effect":"adds","list":"commas"}],"configFile":{"variable":"UV_CONFIG_FILE","format":"toml","whenMissing":"nothing"}} ↗
  • dockerImage (✅ verified): {"image":"ghcr.io/astral-sh/uv","versionTag":"^(\\d+\\.\\d+(?:\\.\\d+)?)(?:-.+)?$"} ↗
  • installedPackage (✅ verified): {"name":"uv","commands":[["pipx","install"],["pip","install"]]} ↗
  • environmentNames (✅ verified): {"prefix":"","match":"exact"} ↗
  • registrySettings (✅ verified): {"file":"pyproject.toml","path":["tool","uv","index"],"applies":"all","effect":"adds","urlKey":"url","entries":{"nameKey":"name","rules":[{"key":"explicit","value":true,"effect":"pinned"},{"key":"default","value":true,"effect":"replaces"}],"first":"adds","others":"adds","pins":{"file":"pyproject.toml","tables":[["tool","uv","sources"]],"key":"index"}}}, {"file":"pyproject.toml","path":["tool","uv","index-url"],"applies":"all","effect":"replaces"}, {"file":"pyproject.toml","path":["tool","uv","extra-index-url"],"applies":"all","effect":"adds"}, {"file":"pyproject.toml","path":["tool","uv","find-links"],"applies":"all","effect":"adds"}, {"file":"pyproject.toml","path":["tool","uv","pip","index-url"],"applies":"all","effect":"replaces"}, {"file":"pyproject.toml","path":["tool","uv","pip","extra-index-url"],"applies":"all","effect":"adds"}, {"file":"pyproject.toml","path":["tool","uv","pip","find-links"],"applies":"all","effect":"adds"}, {"file":"uv.toml","path":["index"],"applies":"all","effect":"adds","urlKey":"url","entries":{"nameKey":"name","rules":[{"key":"explicit","value":true,"effect":"pinned"},{"key":"default","value":true,"effect":"replaces"}],"first":"adds","others":"adds","pins":{"file":"pyproject.toml","tables":[["tool","uv","sources"]],"key":"index"}}}, {"file":"uv.toml","path":["index-url"],"applies":"all","effect":"replaces"}, {"file":"uv.toml","path":["extra-index-url"],"applies":"all","effect":"adds"}, {"file":"uv.toml","path":["find-links"],"applies":"all","effect":"adds"}, {"file":"uv.toml","path":["pip","index-url"],"applies":"all","effect":"replaces"}, {"file":"uv.toml","path":["pip","extra-index-url"],"applies":"all","effect":"adds"}, {"file":"uv.toml","path":["pip","find-links"],"applies":"all","effect":"adds"} ↗
  • pylockCreatedBy (✅ verified): uv ↗
  • configTables (✅ verified): {"pyproject.toml":"tool.uv","uv.toml":""} ↗
  • pyprojectTable (✅ verified): tool.uv ↗
  • configPrecedence (✅ verified): uv.toml wins over [tool.uv] in the same directory; only the nearest directory with either is read, and in a workspace only the root ↗
  • configFileOrder (✅ verified): uv.toml, pyproject.toml ↗
  • workspaceRootOnly (✅ verified): true ↗
  • buildSwitch (✅ verified): {"setting":"no-build","value":true,"since":"0.2.12","covers":["registry","git","remoteTarball","file","directory"]} ↗
  • durationStrings (✅ verified): {"since":"0.9.17","syntax":"words-or-iso8601"} ↗
  • durationUnits (✅ verified): hours, days, weeks ↗
  • cutoffDates (✅ verified): {"timestamps":true,"offsetRequired":true,"dates":"next-day-system-time-zone"} ↗
  • excludeWildcards (✅ verified): {"since":null,"trailingOnly":false} ↗
  • excludeValue (✅ verified): false ↗
  • missingUploadTime (✅ verified): A file from an index that gives no upload time is treated as unavailable while a delay is set ↗
  • registryOnly (✅ verified): The delay applies only to packages read from a registry, not to git, URL or path dependencies ↗
  • requiredVersion (✅ verified): {"table":"tool.uv","key":"required-version","since":"0.5.14"} ↗
  • lockfileFormat (❓ uncertain): {"sources":{"registry":"registry","git":"git","remoteTarball":"url","file":"path","directory":"directory","editable":"editable","virtual":"virtual"},"sdist":"sdist","wheels":"wheels","packages":"package"} ❓ ↗
  • ignoredByToolCommands (✅ verified): uv tool install, uv tool run and uvx ignore pyproject.toml and uv.toml in the project and read only user and system configuration ↗
  • lockedSettings (✅ verified): {"settings":["exclude-newer","exclude-newer-package"],"lock":"uv lock","failing":["uv sync --locked","uv lock --check"]} ↗
  • lockOptions (✅ verified): {"table":"options","timestamp":"exclude-newer","span":"exclude-newer-span","packages":"exclude-newer-package","packageTimestamp":"timestamp","packageSpan":"span","placeholder":"0001-01-01T00:00:00Z"} ↗
  • lockComparison (✅ verified): {"spans":"fieldwise","absolute":"earlier","packages":"locked-or-recorded","dateOnly":"next-day-system-time-zone"} ↗
  • spanSyntax (✅ verified): {"friendlyUnits":{"years":["years","year","yrs","yr","y"],"months":["months","month","mos","mo"],"weeks":["weeks","week","wks","wk","w"],"days":["days","day","d"],"hours":["hours","hour","hrs","hr","h"],"minutes":["minutes","minute","mins","min","m"],"seconds":["seconds","second","secs","sec","s"],"milliseconds":["milliseconds","millisecond","millis","milli","msecs","msec","ms"],"microseconds":["microseconds","microsecond","micros","micro","usecs","usec","us"],"nanoseconds":["nanoseconds","nanosecond","nanos","nano","nsecs","nsec","ns"]},"rejectedUnits":["years","months"]} ↗
  • commandLine (✅ verified): {"add":[["uv","add"],["uv","pip","install"],["uv","tool","install"]],"run":[{"command":["uvx"],"packageOptions":["--from"],"extraPackageOptions":["-w","--with","--with-editable"]},{"command":["uv","tool","run"],"packageOptions":["--from"],"extraPackageOptions":["-w","--with","--with-editable"]},{"command":["uv","run"],"packageOptions":[],"extraPackageOptions":["-w","--with","--with-editable"],"packageArgument":false,"scriptUrls":true}],"create":[],"valueOptions":["--cache-dir","--config-file","--color","--allow-insecure-host","--trusted-host","--directory","--project","--python-preference","--python-fetch","--preview-features","--preview-feature","--index","--default-index","-i","--index-url","--extra-index-url","-f","--find-links","-P","--upgrade-package","--upgrade-group","--reinstall-package","--index-strategy","--keyring-provider","--resolution","--prerelease","--prerelease-package","--fork-strategy","-C","--config-setting","--config-settings","--config-settings-package","--no-build-isolation-package","--exclude-newer","--exclude-newer-package","--link-mode","--no-sources-package","--refresh-package","--no-build-package","--no-binary-package","-c","--constraints","--constraint","--overrides","--override","--excludes","--exclude","-b","--build-constraints","--build-constraint","-r","--requirements","--requirement","--group","--extra","--no-editable-package","-p","--python","-t","--target","--prefix","--python-version","--python-platform","--output-format","--torch-backend","--optional","--bounds","--rev","--tag","--branch","--package","--script","--no-install-package","--only-install-package","-w","--with","--with-editable","--with-requirements","--no-extra","--no-group","--only-group","--env-file","--max-recursion-depth","--from","--with-executables-from"],"parsing":{"groupedShortOptions":true},"addPackageOptions":["-w","--with","--with-editable","--with-executables-from"],"editableOptions":["--with-editable"],"commaSeparatedOptions":["-w","--with","--with-editable","--with-executables-from"],"interpreterNames":["python","pythonw","cpython","pypy","graalpy","pyodide"],"commandOptions":[{"command":["uv","pip","install"],"valueOptions":["-e","--editable","--no-binary","--only-binary"],"editableOptions":["-e","--editable"]},{"command":["uv","add"],"valueOptions":["-m","--marker"]}]} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--index","--default-index","-i","--index-url","--extra-index-url","-f","--find-links"],"registryVariables":["UV_INDEX","UV_DEFAULT_INDEX","UV_INDEX_URL","UV_EXTRA_INDEX_URL","UV_FIND_LINKS"],"configOptions":["--config-file"],"configVariables":["UV_CONFIG_FILE"]} ↗
  • selection (✅ verified): {"prereleases":{"onFlags":["--pre"],"modeOptions":["--prerelease"],"packageModeOptions":["--prerelease-package"],"onModes":["allow"],"offModes":["disallow"],"modeVariables":["UV_PRERELEASE"]},"buildFromSource":{"onFlags":["--no-binary"],"offFlags":["--binary"],"onPackages":["--no-binary-package"],"flagVariables":["UV_NO_BINARY"],"onPackageVariables":["UV_NO_BINARY_PACKAGE"]},"commands":[{"command":["uv","pip","install"],"buildFromSource":{"onLists":["--no-binary"],"offLists":["--only-binary"]}}]} ↗
  • latestVersion (✅ verified): 0.13.6 ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--directory","moves":"directory"},{"name":"--project","moves":"project","ignoredBy":[["uv","pip"]]}],"variables":[{"name":"UV_WORKING_DIR","moves":"directory"},{"name":"UV_WORKING_DIRECTORY","moves":"directory"},{"name":"UV_PROJECT","moves":"project","ignoredBy":[["uv","pip"]]}]} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--exclude-newer","weakens":"delay","values":"delay"},{"name":"--exclude-newer-package","weakens":"delay","values":"any"}],"variables":[{"name":"UV_EXCLUDE_NEWER","weakens":"delay","values":"delay"}]} ↗
  • pipTable (✅ verified): {"table":"pip","keys":{"exclude-newer":"exclude-newer","exclude-newer-package":"exclude-newer-package","no-binary-package":"no-binary"}} ↗

pip

  • machineSettings (✅ verified): {"variables":[{"name":"PIP_INDEX_URL","effect":"replaces"},{"name":"PIP_PYPI_URL","effect":"replaces"},{"name":"PIP_EXTRA_INDEX_URL","effect":"adds","list":"spaces"},{"name":"PIP_FIND_LINKS","effect":"adds","list":"spaces"}],"configFile":{"variable":"PIP_CONFIG_FILE","format":"ini","whenMissing":"user-file"},"sections":["global","install"],"keys":[{"key":"index-url","effect":"replaces"},{"key":"pypi-url","effect":"replaces"},{"key":"extra-index-url","effect":"adds"},{"key":"find-links","effect":"adds"}],"legacyUserFiles":{"posix":".pip/pip.conf","win32":"pip/pip.ini"}} ↗
  • environmentNames (✅ verified): {"prefix":"PIP_","match":"prefix-then-any-case"} ↗
  • configCommand (✅ verified): {"command":"config","writes":["set","unset","edit"]} ↗
  • configSectionNames (✅ verified): {"exact":true} ↗
  • configSections (✅ verified): {"global":"global","commandsOverride":true} ↗
  • pylockCreatedBy (✅ verified): pip ↗
  • requirementsOptions (✅ verified): -i, --index-url, --pypi-url, --extra-index-url, --no-index, -c, --constraint, -r, --requirement, -e, --editable, -f, --find-links, --no-binary, --only-binary, --prefer-binary, --require-hashes, --no-require-hashes, --pre, --all-releases, --only-final, --trusted-host, --use-feature ↗
  • requirementsParser (✅ verified): {"longOptions":["--index-url","--pypi-url","--extra-index-url","--no-index","--constraint","--requirement","--editable","--find-links","--no-binary","--only-binary","--prefer-binary","--require-hashes","--no-require-hashes","--pre","--all-releases","--only-final","--trusted-host","--use-feature","--hash","--config-settings"],"shortOptions":["-i","-c","-r","-e","-f","-C"],"abbreviations":true} ↗
  • buildSwitch (❓ uncertain): {"setting":"--only-binary","value":":all:","since":"7.0.0","covers":["registry"]} ❓ ↗
  • formatControl (✅ verified): {"noBinary":"--no-binary","onlyBinary":"--only-binary","all":":all:","none":":none:","separator":",","requirementLines":true} ↗
  • configFileNames (✅ verified): pip.conf, pip.ini ↗
  • configFileVariable (✅ verified): PIP_CONFIG_FILE ↗
  • environmentVariable (✅ verified): PIP_UPLOADED_PRIOR_TO ↗
  • durationStrings (✅ verified): {"since":"26.1.0","syntax":"iso8601"} ↗
  • missingUploadTime (✅ verified): Installation fails when an index gives no upload time while --uploaded-prior-to is set ↗
  • lockfileFormat (✅ verified): {"packages":"packages","vcs":"vcs","directory":"directory","archive":"archive","sdist":"sdist","wheels":"wheels","index":"index","createdBy":"created-by","sources":{"git":"vcs","remoteTarball":"archive","directory":"directory"}} ↗
  • requirementsForms (✅ verified): name==version with --hash options, name @ URL for an archive, a local archive or project path, and VCS URLs (name @ git+https://… or -e git+…) ↗
  • requirementsFormat (✅ verified): {"vcs":{"git":["git+"],"other":["hg+","svn+","bzr+"]},"direct":" @ ","editable":["-e","--editable"],"egg":"#egg=","comment":"#","continuation":"\\"} ↗
  • requirementsIncludes (✅ verified): {"requirements":["-r","--requirement"],"constraints":["-c","--constraint"]} ↗
  • requirementsPaths (✅ verified): {"separators":["/","\\"],"currentDirectory":".","archiveExtensions":[".zip",".whl",".tar.bz2",".tbz",".tar.gz",".tgz",".tar",".tar.xz",".txz",".tlz",".tar.lz",".tar.lzma"],"urlSchemes":["http","https","ftp"],"fileScheme":"file:"} ↗
  • lockfilePattern (✅ verified): ^pylock\.([^.]+)\.toml$ ↗
  • commandLine (✅ verified): {"add":[["pip","install"],["pip3","install"]],"run":[],"create":[],"valueOptions":["-r","--requirement","-c","--constraint","--build-constraint","--requirements-from-script","-e","--editable","--group","-t","--target","--platform","--python-version","--implementation","--abi","--root","--prefix","--src","--source","--source-dir","--source-directory","--upgrade-strategy","-C","--config-settings","--progress-bar","--root-user-action","--report","-i","--index-url","--pypi-url","--extra-index-url","-f","--find-links","--refresh-package","--uploaded-prior-to","--no-binary","--only-binary","--all-releases","--only-final","--python","--log","--log-file","--local-log","--keyring-provider","--proxy","--retries","--resume-retries","--timeout","--default-timeout","--exists-action","--trusted-host","--cert","--client-cert","--cache-dir","--use-feature","--use-deprecated"],"flagOptions":["--no-deps","--no-dependencies","--only-deps","--only-dependencies","--dry-run","--user","--no-user","-U","--upgrade","--force-reinstall","-I","--ignore-installed","--ignore-requires-python","--no-build-isolation","--use-pep517","--check-build-dependencies","--break-system-packages","--compile","--no-compile","--no-warn-script-location","--no-warn-conflicts","--require-hashes","--no-require-hashes","--no-clean","--no-index","--pre","--prefer-binary","-h","--help","--debug","--isolated","--require-virtualenv","--require-venv","-v","--verbose","-V","--version","-q","--quiet","--no-input","--no-proxy-env","--no-cache-dir","--disable-pip-version-check","--no-color","--no-python-version-warning"],"parsing":{"abbreviations":true,"groupedShortOptions":true},"editableOptions":["-e","--editable"]} ↗
  • registryOverrides (✅ verified): {"registryOptions":["-i","--index-url","--pypi-url","--extra-index-url","-f","--find-links"],"registryVariables":["PIP_INDEX_URL","PIP_PYPI_URL","PIP_EXTRA_INDEX_URL","PIP_FIND_LINKS"],"configOptions":[],"configVariables":["PIP_CONFIG_FILE"]} ↗
  • selection (✅ verified): {"prereleases":{"onFlags":["--pre"],"onLists":["--all-releases"],"offLists":["--only-final"],"flagVariables":["PIP_PRE"],"onListVariables":["PIP_ALL_RELEASES"],"offListVariables":["PIP_ONLY_FINAL"]},"buildFromSource":{"onLists":["--no-binary"],"offLists":["--only-binary"],"onListVariables":["PIP_NO_BINARY"],"offListVariables":["PIP_ONLY_BINARY"]}} ↗
  • pipxSelection (✅ verified): {"prereleases":{"flagVariables":["PIP_PRE"],"onListVariables":["PIP_ALL_RELEASES"],"offListVariables":["PIP_ONLY_FINAL"]},"buildFromSource":{"onListVariables":["PIP_NO_BINARY"],"offListVariables":["PIP_ONLY_BINARY"]}} ↗
  • pipxCommandLine (✅ verified): {"add":[["pipx","install"],["pipx","inject"]],"run":[{"command":["pipx","run"],"packageOptions":["--spec"],"extraPackageOptions":["--with"],"scriptSuffixes":[".py"]}],"create":[],"valueOptions":["-i","--index-url","--pip-args","--preinstall","--lock","--include-resources-from","--upgrade-strategy","--suffix","--python","--fetch-python","--app","--cooldown","--backend","--output","--python-args"],"flagOptions":["-q","--quiet","-v","--verbose","--skip-maintenance","--global","-f","--force","-U","--upgrade","--include-deps","--system-site-packages","--fetch-missing-python","-e","--editable","--no-cache","--refresh","--no-path-check","--path","--pypackages","--version","--include-apps","--with-suffix"],"parsing":{"abbreviations":true,"groupedShortOptions":true},"addPackageOptions":["--preinstall"],"commandOptions":[{"command":["pipx","inject"],"valueOptions":["-r","--requirement"],"packageFileOptions":["-r","--requirement"]}],"addOperands":[{"command":["pipx","inject"],"operands":1}],"passOn":[{"command":["pipx","runpip"],"operands":1,"runs":"pip","splitsOneWord":true}],"fileCommands":[["pipx","install-all"],["pipx","manifest","sync"]]} ↗
  • pipxRegistryOverrides (✅ verified): {"registryOptions":["-i","--index-url"],"registryVariables":[],"configOptions":["--pip-args"],"configVariables":[]} ↗
  • latestVersion (✅ verified): 26.2.2 ↗
  • configCommands (✅ verified): {"command":["pip","config"],"writes":["set","unset","edit"]}, {"command":["pip3","config"],"writes":["set","unset","edit"]} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--uploaded-prior-to","weakens":"delay","values":"delay"}],"variables":[{"name":"PIP_UPLOADED_PRIOR_TO","weakens":"delay","values":"delay"}]} ↗

Poetry

  • environmentNames (✅ verified): {"prefix":"","match":"exact"} ↗
  • installedPackage (✅ verified): {"name":"poetry","commands":[["pipx","install"],["pip","install"]]} ↗
  • pylockCreatedBy (✅ verified): poetry-plugin-export ↗
  • configTable (✅ verified): {"solver":"solver","installer":"installer"} ↗
  • pyprojectTable (✅ verified): tool.poetry ↗
  • configLocation (✅ verified): poetry.toml is read only from the directory of the pyproject.toml Poetry found (the current directory or the nearest parent with one) ↗
  • buildSwitch (✅ verified): {"setting":"installer.only-binary","value":[":all:"],"since":"2.0.0","covers":["registry"]} ↗
  • excludeFormat (⚠️ disputed): ⚠️ comma-separated string ↗ / TOML array ↗
  • excludeWildcards (✅ verified): {"since":null,"trailingOnly":false} ↗
  • missingUploadTime (✅ verified): A release whose source gives no upload times is not filtered by solver.min-release-age ↗
  • lockedVersionsKept (❓ uncertain): poetry lock and poetry add keep versions already in poetry.lock even when they are newer than the delay allows; poetry update and poetry lock --regenerate resolve them again ❓ ↗
  • requiredVersion (✅ verified): {"table":"tool.poetry","key":"requires-poetry","since":"2.0.0"} ↗
  • lockfileFormat (❓ uncertain): {"sources":{"git":"git","remoteTarball":"url","file":"file","directory":"directory","registry":"legacy"},"packages":"package","source":"source","files":"files"} ❓ ↗
  • commandLine (✅ verified): {"add":[["poetry","add"]],"run":[],"create":[],"valueOptions":["-C","--directory","-P","--project","-G","--group","-E","--extras","--optional","--python","--platform","--markers","--source"],"parsing":{"groupedShortOptions":true}} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--source"],"registryVariables":[],"configOptions":[],"configVariables":[]} ↗
  • versionConstraints (✅ verified): {"separator":"@","latest":"latest","caret":"^","tilde":"~","any":"*"} ↗
  • selection (✅ verified): {"prereleases":{"onFlags":["--allow-prereleases"]},"buildFromSource":{"onListVariables":["POETRY_INSTALLER_NO_BINARY"],"offListVariables":["POETRY_INSTALLER_ONLY_BINARY"],"listBooleans":true}} ↗
  • latestVersion (✅ verified): 2.5.1 ↗
  • directoryOptions (✅ verified): {"options":[{"name":"-C","moves":"directory"},{"name":"--directory","moves":"directory"},{"name":"-P","moves":"project"},{"name":"--project","moves":"project"}],"variables":[]} ↗
  • registrySettings (✅ verified): {"file":"pyproject.toml","path":["tool","poetry","source"],"applies":"all","effect":"replaces","urlKey":"url","entries":{"nameKey":"name","rules":[{"key":"priority","value":"supplemental","effect":"adds"},{"key":"priority","value":"explicit","effect":"pinned"}],"first":"replaces","others":"replaces","pypiName":"pypi","pins":{"file":"pyproject.toml","tables":[["tool","poetry","dependencies"],["tool","poetry","group","*","dependencies"]],"key":"source"}}} ↗
  • configCommands (✅ verified): {"command":["poetry","config"],"operands":2,"options":["--unset","--migrate"]}, {"command":["poetry","source"],"writes":["add","remove"]} ↗
  • installOverrides (✅ verified): {"options":[],"variables":[{"name":"POETRY_SOLVER_MIN_RELEASE_AGE","weakens":"delay","values":"delay"},{"name":"POETRY_SOLVER_MIN_RELEASE_AGE_EXCLUDE","weakens":"delay","values":"any"},{"name":"POETRY_SOLVER_MIN_RELEASE_AGE_EXCLUDE_SOURCE","weakens":"delay","values":"any"}]} ↗

PDM

  • installedPackage (✅ verified): {"name":"pdm","commands":[["uv","tool","install"],["pipx","install"],["pip","install"]]} ↗
  • environmentNames (✅ verified): {"prefix":"","match":"exact"} ↗
  • pylockCreatedBy (✅ verified): pdm ↗
  • configTables (✅ verified): {"pyproject.toml":"tool.pdm.resolution"} ↗
  • pyprojectTable (✅ verified): tool.pdm ↗
  • buildSwitch (✅ verified): {"setting":"only-binary","value":":all:","since":"2.15.0","covers":["registry"]} ↗
  • durationStrings (✅ verified): {"since":"2.26.8","syntax":"compact"} ↗
  • durationUnits (✅ verified): hours, days, weeks ↗
  • cutoffDates (✅ verified): {"timestamps":true,"offsetRequired":false,"dates":"start-utc"} ↗
  • excludeWildcards (✅ verified): {"since":null,"trailingOnly":false} ↗
  • excludeValue (✅ verified): false ↗
  • missingUploadTime (✅ verified): A distribution without an upload time is treated as unavailable while a cutoff applies to its package ↗
  • lockfileFormat (❓ uncertain): {"packages":"package","files":"files","file":"file","vcs":["git","hg","svn","bzr"],"url":"url","path":"path","editable":"editable"} ❓ ↗
  • lockedSettings (✅ verified): {"settings":"table","lock":"pdm lock","failing":["pdm lock --check","pdm install --check"]} ↗
  • lockHash (✅ verified): {"key":["metadata","content_hash"],"separator":":","inputs":["metadata","lock_inputs"],"inputsSetting":["tool","pdm","resolution","lock_inputs"],"workspace":["tool","pdm","workspace"],"project":["project"],"fields":[{"name":"sources","path":["tool","pdm","source"],"missing":[]},{"name":"dependencies","path":["project","dependencies"],"missing":[]},{"name":"optional-dependencies","path":["project","optional-dependencies"],"missing":{}},{"name":"requires-python","path":["project","requires-python"],"missing":""},{"name":"resolution","path":["tool","pdm","resolution"],"missing":{}}],"groups":{"name":"dev-dependencies","tables":[["dependency-groups"],["tool","pdm","dev-dependencies"]],"separators":"[^A-Za-z0-9]+"}} ↗
  • uvMode (❓ uncertain): {"file":"pdm.toml","key":"use_uv"} ❓ ↗
  • directoryOptions (✅ verified): {"options":[{"name":"-p","moves":"project"},{"name":"--project","moves":"project"}],"variables":[{"name":"PDM_PROJECT","moves":"project"}]} ↗
  • commandLine (✅ verified): {"add":[["pdm","add"]],"run":[],"create":[],"valueOptions":["-c","--config","--pep582","-L","--lockfile","-G","--group","-k","--skip","-e","--editable","-p","--project","--venv","--override"],"flagOptions":["-V","--version","-h","--help","-v","--verbose","-q","--quiet","--no-cache","-I","--ignore-python","-n","--non-interactive","-g","--global","-d","--dev","--no-sync","--frozen-lockfile","--no-lock","--save-compatible","--save-safe-compatible","--save-wildcard","--save-exact","--save-minimum","--update-reuse","--update-eager","--update-all","--update-reuse-installed","--pre","--prerelease","--stable","-u","--unconstrained","--no-editable","--no-self","-x","--fail-fast","--no-isolation","--dry-run"],"parsing":{"abbreviations":true,"groupedShortOptions":true},"editableOptions":["-e","--editable"]} ↗
  • registrySettings (✅ verified): {"file":"pyproject.toml","path":["tool","pdm","source"],"applies":"all","effect":"adds","urlKey":"url","entries":{"nameKey":"name","rules":[{"key":"type","value":"find_links","effect":"adds"},{"key":"name","value":"pypi","effect":"replaces"}],"first":"adds","others":"adds","pypiName":"pypi"}} ↗
  • registryOverrides (✅ verified): {"registryOptions":[],"registryVariables":["PDM_PYPI_URL"],"configOptions":["-c","--config"],"configVariables":["PDM_CONFIG_FILE"]} ↗
  • configCommands (✅ verified): {"command":["pdm","config"],"operands":2,"options":["-d","--delete","-e","--edit"]} ↗
  • selection (✅ verified): {"prereleases":{"onFlags":["--pre","--prerelease"],"offFlags":["--stable"]},"buildFromSource":{"onListVariables":["PDM_NO_BINARY"],"offListVariables":["PDM_ONLY_BINARY"]}} ↗
  • latestVersion (✅ verified): 2.29.5 ↗

Pipenv

  • installedPackage (✅ verified): {"name":"pipenv","commands":[["pipx","install"],["pip","install"]]} ↗
  • environmentNames (✅ verified): {"prefix":"PIPENV_","match":"exact"}, {"prefix":"PIP_","match":"prefix-then-any-case"} ↗
  • pylockCreatedBy (✅ verified): pipenv ↗
  • configTables (✅ verified): {"Pipfile":"pipenv"} ↗
  • durationStrings (✅ verified): {"since":"2026.6.2","syntax":"compact"} ↗
  • durationUnits (✅ verified): days ↗
  • missingUploadTime (✅ verified): An index without upload times makes the setting accepted but without effect ↗
  • resolverBypass (❓ uncertain): {"table":"pipenv","keys":["resolver_backend","resolver"],"value":"pure-python"} ❓ ↗
  • lockfileFormat (✅ verified): {"meta":"_meta","git":"git","file":"file","path":"path","editable":"editable","hashes":"hashes","version":"version"} ↗
  • commandLine (✅ verified): {"add":[["pipenv","install"]],"run":[],"create":[],"valueOptions":["--pypi-mirror","--python","--extra-pip-args","--resolver","--categories","--extras","--config-settings","-i","--index","-r","--requirements","-e","--editable"],"flagOptions":["-h","--help","--version","--where","--venv","--py","--envs","--rm","--bare","--man","--support","-v","--verbose","-q","--quiet","--clear","--site-packages","--no-site-packages","--pre","-d","--dev","--all","--ignore-pipfile","--skip-lock","--system","--deploy"],"parsing":{"abbreviations":true,"groupedShortOptions":true},"editableOptions":["-e","--editable"]} ↗
  • registryOverrides (✅ verified): {"registryOptions":["-i","--index","--pypi-mirror"],"registryVariables":["PIPENV_PYPI_MIRROR"],"configOptions":["--extra-pip-args"],"configVariables":["PIPENV_DOTENV_LOCATION"]} ↗
  • directoryOptions (✅ verified): {"options":[],"variables":[{"name":"PIPENV_PIPFILE","moves":"project","file":"Pipfile"}]} ↗
  • registrySettings (✅ verified): {"file":"Pipfile","path":["source"],"applies":"all","effect":"replaces","urlKey":"url","entries":{"nameKey":"name","rules":[],"first":"replaces","others":"pinned","pins":{"file":"Pipfile","tables":[["*"]],"key":"index"},"searchAll":["pipenv","install_search_all_sources"]}} ↗
  • selection (✅ verified): {"prereleases":{"onFlags":["--pre"]},"buildFromSource":{"onListVariables":["PIP_NO_BINARY"],"offListVariables":["PIP_ONLY_BINARY"]}} ↗
  • latestVersion (✅ verified): 2026.10.4 ↗

Composer

  • environmentNames (✅ verified): {"prefix":"","match":"exact"} ↗
  • latestVersion (✅ verified): 2.11.1 ↗
  • durationStrings (✅ verified): {"since":"2.11.0","syntax":"unit-word","numbers":"seconds","trim":false} ↗
  • durationUnits (✅ verified): days ↗
  • excludeWildcards (✅ verified): {"since":"2.11.0","trailingOnly":false} ↗
  • denyList (✅ verified): {"file":"composer.json","setting":"config.allow-plugins","value":false,"since":"2.2.0"} ↗
  • cooldownTime (✅ verified): {"published":"published-time","author":"time","requireSetting":"require-published-time","authorTimeRepositories":["vcs","path","artifact"]} ↗
  • lockedVersions (✅ verified): composer install installs the locked versions without the cooldown; a partial update keeps every other locked version, a full composer update re-evaluates them all ↗
  • olderVersions (❓ uncertain): Composer 2.10 reads policy.cooldown as a custom dependency policy without sources, which blocks nothing; older versions ignore config.policy as an unknown config key ❓ ↗
  • contentHash (✅ verified): {"file":"composer.lock","key":"content-hash","settings":["config.policy"],"since":"2.11.0","command":"composer update --lock"} ↗
  • pluginApiVersion (✅ verified): {"key":"plugin-api-version","cooldownApi":"2.11.0"} ↗
  • lockfileFormat (✅ verified): {"sections":["packages","packages-dev"],"name":"name","version":"version","installScripts":"type","pluginType":"composer-plugin","pluginTypes":["composer-plugin","composer-installer"],"optionalPlugin":["extra","plugin-optional"],"source":"source","dist":"dist","pathType":"path","archiveTypes":["zip","tar","gzip","xz","phar","rar"]} ↗
  • legacyLockPlugins (✅ verified): {"below":"2.2.0","missing":"1.1.0","allowsAllUntil":"2.10.0"} ↗
  • manifestSyntax (✅ verified): {"comments":false,"trailingCommas":false} ↗
  • sourceInstall (✅ verified): {"source":"source","dist":"dist"} ↗
  • registryDistHosts (✅ verified): api.github.com, gitlab.com, bitbucket.org, codeberg.org ↗
  • repositoryArchiveHosts (✅ verified): {"wpackagist.org":["downloads.wordpress.org"]} ↗
  • branchVersions (✅ verified): {"prefix":"dev-","suffix":"-dev"} ↗
  • repositoryTypes (✅ verified): {"vcs":["vcs","git","github","gitlab","bitbucket","git-bitbucket","svn","hg","fossil","perforce"],"directory":["path"],"file":["artifact"],"inline":["package"],"registry":["composer"],"disable":"packagist.org"} ↗
  • weakeningSettings (✅ verified): {"path":["config","policy"],"when":"false","effect":"turns off every dependency policy, the cooldown and malware blocking included"}, {"path":["config","policy","cooldown"],"when":"false","effect":"turns off the cooldown"}, {"path":["config","policy","cooldown","block"],"when":"php-false","effect":"stops the cooldown from withholding new versions"}, {"path":["config","policy","malware"],"when":"false","effect":"turns off blocking of versions flagged as malware"}, {"path":["config","policy","malware","block"],"when":"php-false","effect":"stops blocking versions flagged as malware"}, {"path":["config","policy","malware","block-scope"],"when":"update","effect":"blocks versions flagged as malware only on update, so composer install still installs them from composer.lock"} ↗
  • transportSettings (✅ verified): {"path":["config","secure-http"],"weakensWhen":false,"effect":"allows downloads over plain HTTP"}, {"path":["config","disable-tls"],"weakensWhen":true,"effect":"downloads without TLS and turns off secure-http"} ↗
  • allowAllPlugins (✅ verified): {"setting":"config.allow-plugins","value":true,"patterns":["*","*/*"]} ↗
  • repositoryWeakening (✅ verified): {"key":"require-published-time","when":"false","effect":"lets the cooldown count from the time the package author wrote into composer.json"}, {"key":"filter","when":"false","list":"malware","effect":"skips the malware list that the repository advertises"} ↗
  • environmentOverrides (✅ verified): {"name":"COMPOSER_POLICY","values":["0","false","off"],"effect":"turns off every dependency policy, the cooldown included"}, {"name":"COMPOSER_NO_BLOCKING","values":["1","true","on","false","off"],"effect":"turns off all policy blocking, the cooldown and malware blocking included"}, {"name":"COMPOSER_NO_SECURITY_BLOCKING","values":["1","true","on","false","off"],"effect":"turns off all policy blocking, the cooldown and malware blocking included"}, {"name":"COMPOSER_POLICY_COOLDOWN_PERIOD","values":"delay","effect":"replaces the cooldown period"}, {"name":"COMPOSER_POLICY_COOLDOWN_BLOCK","values":["0","false","off"],"effect":"stops the cooldown from withholding new versions"}, {"name":"COMPOSER_POLICY_MALWARE_BLOCK","values":["0","false","off"],"effect":"stops blocking versions flagged as malware"} ↗
  • packagistApi (✅ verified): {"url":"https://repo.packagist.org","metadataPath":"/p2/{name}.json","devSuffix":"~dev","notFoundStatus":404,"packagesField":"packages","minifiedField":"minified","minifiedValue":"composer/2.0","unsetValue":"__unset","versionField":"version","normalizedField":"version_normalized","timeField":"time","publishedField":"published-time","typeField":"type","abandonedField":"abandoned","packagePage":"https://packagist.org/packages/{name}"} ↗
  • metadataMinifier (✅ verified): {"firstEntry":"whole","emptyIsFirst":true,"unsetValue":"__unset"} ↗
  • versionConstraints (✅ verified): {"and":[","," "],"or":["||","|"],"hyphen":" - ","wildcards":["*","x","X"],"tilde":"~","caret":"^","operators":[">=","<=","<>","!=","==",">","<","="],"stabilityFlag":"@","branchPrefix":"dev-","branchSuffix":"-dev","alias":" as ","reference":"#"} ↗
  • stabilities (✅ verified): {"order":["stable","RC","beta","alpha","dev"],"priorities":{"stable":0,"RC":5,"beta":10,"alpha":15,"dev":20},"minimumStability":"stable","modifiers":{"a":"alpha","alpha":"alpha","b":"beta","beta":"beta","rc":"RC","p":"patch","pl":"patch","patch":"patch","stable":"stable"}} ↗
  • versionComparison (✅ verified): {"separators":["-","_","+"],"specialForms":[["dev",0],["alpha",1],["a",1],["beta",2],["b",2],["RC",3],["rc",3],["#",4],["pl",5],["p",5]],"numberOrder":4} ↗
  • commandLine (✅ verified): {"add":[["composer","require"],["composer","r"],["composer","global","require"],["composer","global","r"]],"run":[],"create":[{"command":["composer","create-project"],"packageOptions":[]}],"valueOptions":["-d","--working-dir","--prefer-install","--audit-format","--ignore-platform-req","--apcu-autoloader-prefix","--with","--bump-after-update","-s","--stability","--repository","--repository-url","--require","-f","--file","--before","--after"],"parsing":{"groupedShortOptions":true}} ↗
  • commandNames (✅ verified): {"commands":["about","archive","audit","browse","bump","check-platform-reqs","clear-cache","completion","config","create-project","depends","diagnose","dump-autoload","exec","fund","global","help","init","install","licenses","list","outdated","policy","prohibits","reinstall","remove","repository","require","run-script","search","self-update","show","status","suggests","update","validate","_complete"],"aliases":{"home":"browse","clearcache":"clear-cache","cc":"clear-cache","why":"depends","dumpautoload":"dump-autoload","i":"install","why-not":"prohibits","rm":"remove","uninstall":"remove","repo":"repository","r":"require","run":"run-script","selfupdate":"self-update","info":"show","u":"update","upgrade":"update"},"matching":"symfony-console","hidden":["_complete"]} ↗
  • commandArguments (✅ verified): {"require":"require","update":"update","createProject":"create-project","global":"global","pairSeparators":[":","="," "],"platformPackages":"^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9]+(?:[_.-][a-z0-9]+)*|composer(?:-(?:plugin|runtime)-api)?)$","namePattern":"^[a-z0-9]+(?:[_.-][a-z0-9]+)*/[a-z0-9]+(?:(?:[_.]|-{1,2})[a-z0-9]+)*$","updateLockWords":["lock","nothing","mirrors"],"withOption":"--with","requireOption":"--require","stabilityOptions":["--stability","-s"]} ↗
  • registryOverrides (✅ verified): {"registryOptions":["--repository","--repository-url"],"registryVariables":[],"configOptions":[],"configVariables":["COMPOSER","COMPOSER_HOME"]} ↗
  • installOverrides (✅ verified): {"options":[{"name":"--no-blocking","weakens":"protection","values":"any","effect":"turns off all of Composer's policy blocking for the command, the cooldown and the blocking of versions flagged as malware included"},{"name":"--no-security-blocking","weakens":"protection","values":"any","effect":"turns off all of Composer's policy blocking for the command, the cooldown and the blocking of versions flagged as malware included"},{"name":"--no-cooldown","weakens":"delay","values":"any"},{"name":"--no-secure-http","weakens":"protection","values":"any","effect":"turns off secure-http while Composer installs the project package","protects":"secure-http lets Composer download only over HTTPS, which keeps that download from being read or changed on the way"}],"variables":[{"name":"COMPOSER_NO_BLOCKING","weakens":"protection","values":{"except":["","0"]},"effect":"turns off all of Composer's policy blocking for the command, the cooldown and the blocking of versions flagged as malware included"},{"name":"COMPOSER_NO_SECURITY_BLOCKING","weakens":"protection","values":{"except":["","0"]},"effect":"turns off all of Composer's policy blocking for the command, the cooldown and the blocking of versions flagged as malware included"},{"name":"COMPOSER_POLICY","weakens":"protection","values":["0","false","off"],"effect":"turns off every dependency policy of Composer for the command, the cooldown and the blocking of versions flagged as malware included"},{"name":"COMPOSER_POLICY_COOLDOWN_PERIOD","weakens":"delay","values":"delay"},{"name":"COMPOSER_POLICY_COOLDOWN_BLOCK","weakens":"delay","values":["0","false","off"]},{"name":"COMPOSER_POLICY_MALWARE_BLOCK","weakens":"protection","values":["0","false","off"],"effect":"turns off the blocking of versions flagged as malware"}]} ↗
  • configCommands (✅ verified): {"command":["composer","config"],"operands":2,"options":["--unset","--editor","-e"],"unread":{"file":"COMPOSER_HOME/config.json, or the file --file names","options":["--global","-g","--file","-f"]}}, {"command":["composer","repository"],"writes":["add","remove","rm","delete","set-url","seturl","enable","disable"],"unread":{"file":"COMPOSER_HOME/config.json, or the file --file names","options":["--global","-g","--file","-f"]}}, {"command":["composer","policy"],"writes":["add-source"],"unread":{"file":"COMPOSER_HOME/config.json, or the file --file names","options":["--global","-g","--file","-f"]}}, {"command":["composer","global","config"],"operands":2,"options":["--unset","--editor","-e"],"unread":{"file":"a file of COMPOSER_HOME"}}, {"command":["composer","global","repository"],"writes":["add","remove","rm","delete","set-url","seturl","enable","disable"],"unread":{"file":"a file of COMPOSER_HOME"}}, {"command":["composer","global","policy"],"writes":["add-source"],"unread":{"file":"a file of COMPOSER_HOME"}} ↗
  • configCommandValues (✅ verified): {"command":["composer","config"],"section":"config","booleans":["policy","secure-http","disable-tls","allow-plugins"],"accepted":["true","false","1","0"],"falseValues":["false","0"],"period":"policy.cooldown.period","otherFile":["--global","-g","--file","-f"]} ↗
  • applicationOptions (✅ verified): {"name":"help","shortcuts":["h"],"value":"none"}, {"name":"quiet","shortcuts":["q"],"value":"none"}, {"name":"verbose","shortcuts":["v","vv","vvv"],"value":"none"}, {"name":"version","shortcuts":["V"],"value":"none"}, {"name":"ansi","shortcuts":[],"value":"negatable"}, {"name":"no-interaction","shortcuts":["n"],"value":"none"}, {"name":"profile","shortcuts":[],"value":"none"}, {"name":"no-plugins","shortcuts":[],"value":"none"}, {"name":"no-scripts","shortcuts":[],"value":"none"}, {"name":"working-dir","shortcuts":["d"],"value":"required"}, {"name":"no-cache","shortcuts":[],"value":"none"} ↗
  • scriptCommands (✅ verified): {"scripts":"scripts","aliases":"scripts-aliases","events":["pre-install-cmd","post-install-cmd","pre-update-cmd","post-update-cmd","pre-status-cmd","post-status-cmd","pre-autoload-dump","post-autoload-dump","post-root-package-install","post-create-project-cmd","pre-archive-cmd","post-archive-cmd"],"validName":"^[^:]+(?::[^:]+)*$"} ↗
  • scriptAliases (✅ verified): {"key":"scripts-aliases","since":"2.7.0"} ↗
  • rootStability (✅ verified): {"minimumStability":"minimum-stability","preferStable":"prefer-stable","values":["stable","rc","beta","alpha","dev"]} ↗
  • installPreference (✅ verified): {"setting":"preferred-install","default":"dist","dist":"dist","source":"source","auto":"auto","everything":"*"} ↗
  • sourceFallback (✅ verified): {"since":"2.10.0","setting":"source-fallback","removedIn":"2.11.0"} ↗
  • registrySourceHosts (✅ verified): {"api.github.com":"github.com","gitlab.com":"gitlab.com","bitbucket.org":"bitbucket.org","codeberg.org":"codeberg.org"} ↗
  • sourceHostAliases (✅ verified): {"www.github.com":"github.com"} ↗
  • directoryOptions (✅ verified): {"options":[{"name":"--working-dir","moves":"directory"},{"name":"-d","moves":"directory"}],"variables":[],"lookup":"first-token"} ↗

Bundler

  • latestVersion (✅ verified): 4.0.23 ↗
  • gemfileNames (✅ verified): gems.rb, Gemfile ↗
  • lockfileExists (✅ verified): {"test":"File.exist?"} ↗
  • gemfileEvaluation (✅ verified): instance_eval ↗
  • rubySyntax (✅ verified): {"endOfScript":{"marker":"__END__","characters":["\u0000","\u0004","\u001a"]},"embeddedDocument":["=begin","=end"],"percentLiterals":{"expanding":["Q","W","I","x","r"],"plain":["q","w","i","s"]},"pairedDelimiters":{"(":")","[":"]","{":"}","<":">"},"heredocIndent":["-","~"],"globalPunctuation":"~*$?!@/\\;,.=:<>\"&`'+","integerPrefixes":{"0":8,"0x":16,"0b":2,"0o":8,"0d":10},"numberSuffixes":["r","i"],"lineEnding":"\r\n","keywords":{"end":["__ENCODING__","__LINE__","__FILE__","BEGIN","END","end","false","nil","redo","retry","self","true"],"statement":["begin","do","else","ensure","then"],"value":["and","case","elsif","for","if","in","module","or","unless","until","when","while"],"mid":["break","next","rescue","return"],"argument":["defined?","not","super","yield"],"methodName":["def"],"className":["class"],"names":["alias","undef"],"modifiers":["if","rescue","unless","until","while"],"opening":["begin","case","class","def","do","for","if","module","unless","until","while"],"loops":["for","until","while"],"closing":["end"]}} ↗
  • rubyParsers (✅ verified): {"defaults":[{"since":"0.0.0","value":"parse.y"},{"since":"3.4.0","value":"prism"}],"option":"--parser","differences":{"characterBeyondAscii":true,"embeddedDocumentAfter":["\u0004","\u001a"],"globalZeroWithName":true}} ↗
  • lineContinuation (✅ verified): {"calls":[".","&."],"logical":{"since":"4.0.0","operators":["&&","||"],"words":["and","or"]}} ↗
  • stringToInteger (✅ verified): {"whitespace":[" ","\t","\n","\u000b","\f","\r"],"signs":["+","-"],"prefix":"0d","separator":"_"} ↗
  • configFormat (✅ verified): {"comment":"#","quotes":["\"","'"],"indentPerLevel":2,"duplicates":"last"} ↗
  • cliCommands (✅ verified): {"commands":["add","binstubs","cache","check","clean","config","console","doctor","env","exec","fund","gem","help","info","init","install","issue","licenses","list","lock","open","outdated","platform","plugin","pristine","remove","show","update","version"],"aliases":{"c":"check","i":"install","ls":"list","e":"exec","ex":"exec","exe":"exec","package":"cache","pack":"cache","-v":"version","--version":"version","-h":"help","-?":"help","--help":"help","-D":"help"},"prefixes":true,"defaultCommand":"install","hidden":{"cli_help":"cli_help","install_or_cli_help":"install","inject":"inject","viz":"viz"},"dashesAsUnderscores":true} ↗
  • versionSelector (✅ verified): {"form":"_VERSION_","variable":"BUNDLER_VERSION"} ↗
  • rubygemsSource (✅ verified): {"url":"https://rubygems.org","method":"source"} ↗
  • cooldownWithLockfile (✅ verified): {"since":"4.0.14","scope":"once Gemfile.lock exists"} ↗
  • cooldownSetting (✅ verified): {"key":"cooldown","variable":"BUNDLE_COOLDOWN","localFile":".bundle/config","localDirectoryVariable":"BUNDLE_APP_CONFIG","order":["--cooldown","local","environment","global","source"]} ↗
  • cooldownSettingValues (✅ verified): {"conversion":"to_i","falseValue":"unset"} ↗
  • lockedVersions (✅ verified): exempt ↗
  • missingTimestamp (✅ verified): Versions without a created_at date are not held back (fail open) ↗
  • allTooNew (✅ verified): excluded by the cooldown setting; pass `--cooldown 0` to bypass ↗
  • olderVersions (✅ verified): ignored ↗
  • lockfileVersion (✅ verified): {"section":"BUNDLED WITH","variable":"BUNDLER_VERSION","setting":"version","update":"bundle update --bundler"} ↗
  • resolveCommands (✅ verified): {"executables":["bundle","bundler"],"commands":["install","update","lock","add","cache"],"option":"--cooldown"} ↗
  • gemInstall (✅ verified): {"command":["gem","install"],"name":"bundler","versionOptions":["-v","--version"],"separator":":"} ↗
  • configLocal (✅ verified): {"file":".bundle/config","ignoredBy":"bundle gem"} ↗
  • configCommand (✅ verified): {"command":["bundle","config"],"set":"set","scopes":["--local","--global"],"legacyArguments":2,"keyAnyCase":true} ↗
  • updateCommand (✅ verified): bundle update GEM --cooldown 0 --conservative ↗
  • dependencySources (✅ verified): git, directory ↗

Renovate

  • configLocation (✅ verified): {"from":"repository-root","branch":"default"} ↗
  • durationStrings (✅ verified): {"since":null,"syntax":"words"} ↗
  • minimumReleaseAgePresets (✅ verified): {"presets":["config:best-practices","security:minimumReleaseAgeNpm"],"value":"3 days","since":"42.0.0","datasource":"npm"} ↗
  • excludeRule (✅ verified): {"list":"packageRules","match":"matchPackageNames","value":null} ↗
  • securityUpdatesSetting (✅ verified): vulnerabilityAlerts, minimumReleaseAge ↗
  • excludeWildcards (✅ verified): {"since":"38.0.0","trailingOnly":false} ↗
  • ruleDescription (✅ verified): description ↗
  • packageJsonConfig (✅ verified): {"file":"package.json","key":"renovate"} ↗
  • durationUnits (✅ verified): hours, days ↗
  • presets (✅ verified): config:best-practices extends security:minimumReleaseAgeNpm (since 42.0.0): "3 days" and internalChecksFilter "strict" for the npm datasource, except pin, replacement, lockFileMaintenance, bump, lockfileUpdate and rollback ↗
  • datasources (✅ verified): {"npm":"npm","pypi":"pypi","packagist":"packagist","rubygems":"rubygems"} ↗
  • packagistReleaseTime (✅ verified): {"field":"published-time","fallback":"time"} ↗
  • negativeMatch (✅ verified): ! ↗
  • packageRuleMatching (✅ verified): {"negation":"!","allPatterns":"*","packageMatchers":["matchPackageNames","matchDepNames"],"datasourceMatcher":"matchDatasources","updateTypeMatcher":"matchUpdateTypes"} ↗
  • packageRulesOrder (✅ verified): {"presetsFirst":true,"overridesTopLevel":true,"laterWins":true} ↗
  • delayedUpdateTypes (✅ verified): major, minor, patch ↗
  • internalPresets (✅ verified): {"prefixes":[":","default:","abandonments:","config:","customManagers:","docker:","global:","group:","helpers:","mergeConfidence:","monorepo:","packages:","preview:","replacements:","schedule:","security:","workarounds:"],"settingDelay":["config:best-practices","security:minimumReleaseAgeCrate","security:minimumReleaseAgeNpm","security:minimumReleaseAgePypi"]} ↗
  • pypiPresets (✅ verified): {"presets":["security:minimumReleaseAgePypi"],"value":"3 days","since":"44.8.0","datasource":"pypi"} ↗
  • pnpmSecurityExclusions (❓ uncertain): {"managers":["pnpm"],"file":"pnpm-workspace.yaml","setting":"minimumReleaseAgeExclude","comment":"# Renovate security update: ","versionSeparator":" || "} ❓ ↗
  • pythonManagers (✅ verified): {"uv":"pep621","poetry":"poetry","pip":"pip_requirements","pdm":"pep621","pipenv":"pipenv"} ↗
  • managers (✅ verified): {"npm":"npm","pnpm":"npm","yarn":"npm","bun":"bun","deno":"deno","uv":"pep621","pdm":"pep621","poetry":"poetry","pip":"pip_requirements","pipenv":"pipenv","composer":"composer","bundler":"bundler","github-actions":"github-actions"} ↗
  • managerCategories (✅ verified): {"npm":["js"],"bun":["js"],"deno":["js"],"pep621":["python"],"pip_requirements":["python"],"poetry":["python"],"pipenv":["python"],"composer":["php"],"bundler":["ruby"],"github-actions":["ci"]} ↗
  • botOnlyEcosystems (✅ verified): {"cargo":{"manager":"cargo","datasource":"crate","categories":["rust"]},"gomod":{"manager":"gomod","datasource":"go","categories":["golang"]},"maven":{"manager":"maven","datasource":"maven","categories":["java"]},"gradle":{"manager":"gradle","datasource":"maven","categories":["java"]},"nuget":{"manager":"nuget","datasource":"nuget","categories":["dotnet"]}} ↗
  • cratePresets (✅ verified): {"presets":["security:minimumReleaseAgeCrate"],"value":"3 days","since":"44.5.0","datasource":"crate"} ↗
  • managerMatching (✅ verified): {"managerMatcher":"matchManagers","categoryMatcher":"matchCategories","customPrefix":"custom.","stringIsList":true} ↗
  • githubActions (✅ verified): {"manager":"github-actions","datasource":"github-tags","digestDatasource":"github-digest"} ↗
  • actionsMatching (✅ verified): {"fileMatcher":"matchFileNames","fileStringIsList":false,"depTypeMatcher":"matchDepTypes","depTypeStringIsList":true,"depType":"action"} ↗
  • actionsTimestamps (✅ verified): {"github-tags":"the commit date of a lightweight tag or the tagger date of an annotated tag, or the date of a GitHub release of that version when that is newer","github-digest":"the commit date","missing":"held"} ↗
  • passesDelayToManager (✅ verified): earlier: []
    44.34.0+: poetry ↗
  • missingTimestamp (✅ verified): earlier: updates without a release timestamp pass the check
    42.0.0+: minimumReleaseAgeBehaviour timestamp-required: such updates are held ↗
  • internalChecksFilter (✅ verified): Defaults to "strict" since 33.0.0; with "none" or "flexible" branches and PRs are created before the delay ends and only automerge waits ↗
  • independentOfPackageManager (✅ verified): minimumReleaseAge is set independently of the package manager's own release-age configuration ↗
  • digestBypassFixed (⚠️ disputed): ⚠️ 44.3.1 ↗ / 44.10.0 ↗

Dependabot

  • configLocation (✅ verified): {"from":"repository-root","branch":"default"} ↗
  • directories (✅ verified): {"keys":["directory","directories"],"relativeTo":"repository-root","globsIn":"directories"} ↗
  • yamlMergeKeys (❓ uncertain): false ❓ ↗
  • cooldownKeys (✅ verified): {"days":"default-days","exclude":"exclude","semverDays":["semver-major-days","semver-minor-days","semver-patch-days"]} ↗
  • excludeWildcards (✅ verified): {"since":"0.0.0","trailingOnly":false} ↗
  • excludeMatching (✅ verified): {"starMatchesSlash":true,"caseSensitive":true} ↗
  • cooldownInclude (✅ verified): {"key":"include","everything":"*"} ↗
  • ecosystems (✅ verified): {"npm":["npm","pnpm","yarn"],"bun":["bun"],"deno":["deno"],"pip":["pip","poetry","pipenv"],"uv":["uv"],"composer":["composer"],"bundler":["bundler"]} ↗
  • yamlAliases (✅ verified): {"accepted":false} ↗
  • yamlScalars (✅ verified): {"library":"psych","version":"5.5.0","integers":"legacy"} ↗
  • githubActions (✅ verified): {"ecosystem":"github-actions","semverDays":false} ↗
  • botOnlyEcosystems (✅ verified): {"cargo":{"ecosystem":"cargo","semverDays":true},"gomod":{"ecosystem":"gomod","semverDays":true},"maven":{"ecosystem":"maven","semverDays":true},"gradle":{"ecosystem":"gradle","semverDays":true},"nuget":{"ecosystem":"nuget","semverDays":true}} ↗
  • actionsReleaseDate (❓ uncertain): the publication date of the GitHub release of the tag, else the date of the tag, else the date of the commit; with no date the update does not wait ❓ ↗
  • dayRange (⚠️ disputed): ⚠️ 1 to 90 days ↗ / 0 removes the cooldown ↗
  • maximumDays (✅ verified): 90 ↗
  • missingPublishDate (✅ verified): Updates proceed when the registry gives no publication date (fail open); for Docker only Docker Hub tag_last_pushed is used ↗
  • transitiveGating (❓ uncertain): Regular updates pass the cooldown to npm (11.10+), pnpm (10.16+) and Yarn Berry to hold back transitive dependencies; the Bun updater passes none ❓ ↗
  • composerReleaseTime (✅ verified): {"field":"time","ignores":"published-time","composerVersion":"2.10.3"} ↗
  • composerContentHash (✅ verified): {"composerVersion":"2.10.3","hashesPolicy":false,"file":"composer.lock","key":"content-hash"} ↗
  • semverKeysScope (✅ verified): semver-major/minor/patch-days apply only to SemVer ecosystems such as npm, Bun and Deno; others use default-days ↗

Environment

How repositories pin tool versions (Corepack, devEngines, Volta, asdf), how GitHub Actions installs them, and the ecosystems whose new versions only the update bots delay (botOnlyEcosystems: Cargo, Go modules, Maven, Gradle and NuGet).

  • botOnlyEcosystems.cargo.project (✅ verified): {"name":"Cargo","client":"Cargo","files":["Cargo.toml","Cargo.lock"]} ↗
  • botOnlyEcosystems.cargo.releaseAge (❓ uncertain): {"setting":"registry.global-min-publish-age","since":"1.100.0","product":"Cargo","file":".cargo/config.toml"} ❓ ↗
  • botOnlyEcosystems.gomod.project (✅ verified): {"name":"Go modules","client":"Go","files":["go.mod","go.sum"]} ↗
  • botOnlyEcosystems.gomod.releaseAge (❓ uncertain): {"setting":null,"since":null} ❓ ↗
  • botOnlyEcosystems.maven.project (✅ verified): {"name":"Maven","client":"Maven","files":["pom.xml"]} ↗
  • botOnlyEcosystems.maven.releaseAge (❓ uncertain): {"setting":null,"since":null} ❓ ↗
  • botOnlyEcosystems.gradle.project (✅ verified): {"name":"Gradle","client":"Gradle","files":["build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle/libs.versions.toml"]} ↗
  • botOnlyEcosystems.gradle.releaseAge (❓ uncertain): {"setting":null,"since":null} ❓ ↗
  • botOnlyEcosystems.nuget.project (✅ verified): {"name":"NuGet","client":"NuGet","files":["packages.config","Directory.Packages.props","nuget.config","NuGet.config","NuGet.Config"],"extensions":[".csproj",".fsproj",".vbproj"]} ↗
  • botOnlyEcosystems.nuget.releaseAge (❓ uncertain): {"setting":"minPublishAgeHours","since":"11.0.100","product":".NET SDK","updatesOnly":true,"file":"nuget.config"} ❓ ↗
  • corepack.packageManagerField (✅ verified): {"key":"packageManager","managers":["npm","pnpm","yarn"]} ↗
  • corepack.devEnginesSince (✅ verified): 0.32.0 ↗
  • corepack.envFileSince (✅ verified): 0.32.0 ↗
  • corepack.bundledWithNode (✅ verified): earlier: false
    14.19.0+: true
    25.0.0+: false ↗
  • corepack.package (✅ verified): corepack ↗
  • corepack.toolPackages (✅ verified): {"npm":["npm"],"pnpm":["pnpm"],"yarn":["yarn","@yarnpkg/cli-dist"]} ↗
  • corepack.defaults (⚠️ disputed): ⚠️ {"since":"0.13.0","locations":[{"platforms":["linux","darwin"],"directories":[{"from":{"env":"COREPACK_HOME","emptyCounts":true},"path":""},{"from":{"env":"XDG_CACHE_HOME","emptyCounts":true},"path":"node/corepack"},{"from":{"env":"LOCALAPPDATA","emptyCounts":true},"path":"node/corepack"},{"from":"home","path":".cache/node/corepack"}],"file":"lastKnownGood.json"},{"platforms":["win32"],"directories":[{"from":{"env":"COREPACK_HOME","emptyCounts":true},"path":""},{"from":{"env":"XDG_CACHE_HOME","emptyCounts":true},"path":"node/corepack"},{"from":{"env":"LOCALAPPDATA","emptyCounts":true},"path":"node/corepack"},{"from":"home","path":"AppData/Local/node/corepack"}],"file":"lastKnownGood.json"}]} ↗ / {"since":"0.13.0","locations":[{"platforms":["linux","darwin"],"directories":[{"from":{"env":"COREPACK_HOME"},"path":""},{"from":"home","path":".cache/node/corepack"}],"file":"lastKnownGood.json"},{"platforms":["win32"],"directories":[{"from":{"env":"COREPACK_HOME"},"path":""},{"from":{"env":"LOCALAPPDATA"},"path":"node/corepack"}],"file":"lastKnownGood.json"}]} ↗
  • corepack.enableNpm (✅ verified): {"command":"enable","npmOnlyWhenNamed":true} ↗
  • corepack.manualInstall (✅ verified): {"package":"corepack","command":"npm install -g corepack","enable":"corepack enable"} ↗
  • installScriptPackages.esbuild (✅ verified): {"name":"esbuild","versions":["0.28.2"],"script":"postinstall: node install.js","kind":"not-needed","does":"it only puts the binary, which esbuild takes from an optional dependency for the platform, in place of the esbuild command and checks that it runs","withoutScript":"the esbuild command starts through a small Node.js script instead of the binary itself (install.js never makes that change on Windows or with Yarn anyway), and the install no longer checks that the binary runs","needsOptionalDependencies":true} ↗
  • installScriptPackages.fsevents (✅ verified): {"name":"fsevents","versions":["2.3.3"],"script":"install: node-gyp rebuild","kind":"not-needed","does":"it is the node-gyp rebuild that npm adds because the source has a binding.gyp, while the package already contains the built fsevents.node","withoutScript":"nothing changes","needsOptionalDependencies":false} ↗
  • installScriptPackages.lefthook (✅ verified): {"name":"lefthook","versions":["2.2.2"],"script":"postinstall: node postinstall.js","kind":"project-task","does":"it runs lefthook install, which installs the git hooks of the repository","withoutScript":"the install no longer installs the git hooks","needsOptionalDependencies":false,"projectStep":{"command":"lefthook install","after":"clone"}} ↗
  • node.bundledNpm (✅ verified): {"line":"0.6","latest":"0.6.21","bundles":[["0.6.3","1.1.0-alpha-2"],["0.6.4","1.1.0-alpha-6"],["0.6.6","1.1.0-beta-4"],["0.6.7","1.1.0-beta-10"],["0.6.8","1.1.0-2"],["0.6.9","1.1.0-3"],["0.6.11","1.1.1"],["0.6.12","1.1.4"],["0.6.13","1.1.9"],["0.6.14","1.1.12"],["0.6.15","1.1.16"],["0.6.16","1.1.19"],["0.6.17","1.1.21"],["0.6.19","1.1.24"],["0.6.20","1.1.37"]]}, {"line":"0.7","latest":"0.7.12","bundles":[["0.7.0","1.1.0-2"],["0.7.2","1.1.0-3"],["0.7.4","1.1.1"],["0.7.6","1.1.8"],["0.7.7","1.1.15"],["0.7.8","1.1.18"],["0.7.9","1.1.23"],["0.7.10","1.1.25"],["0.7.11","1.1.26"],["0.7.12","1.1.30"]]}, {"line":"0.8","latest":"0.8.28","bundles":[["0.8.0","1.1.32"],["0.8.1","1.1.33"],["0.8.2","1.1.36"],["0.8.3","1.1.43"],["0.8.4","1.1.45"],["0.8.5","1.1.46"],["0.8.6","1.1.48"],["0.8.7","1.1.49"],["0.8.8","1.1.59"],["0.8.9","1.1.61"],["0.8.10","1.1.62"],["0.8.12","1.1.63"],["0.8.13","1.1.65"],["0.8.15","1.1.66"],["0.8.16","1.1.69"],["0.8.17","1.2.0"],["0.8.18","1.2.2"],["0.8.19","1.2.10"],["0.8.20","1.2.11"],["0.8.22","1.2.14"],["0.8.23","1.2.18"],["0.8.24","1.2.24"],["0.8.25","1.2.30"]]}, {"line":"0.9","latest":"0.9.12","bundles":[["0.9.0","1.1.44"],["0.9.1","1.1.59"],["0.9.2","1.1.61"],["0.9.3","1.1.64"],["0.9.4","1.1.70"],["0.9.6","1.2.0"],["0.9.7","1.2.2"],["0.9.8","1.2.3"],["0.9.9","1.2.10"],["0.9.10","1.2.12"]]}, {"line":"0.10","latest":"0.10.48","bundles":[["0.10.0","1.2.14"],["0.10.1","1.2.15"],["0.10.3","1.2.17"],["0.10.4","1.2.18"],["0.10.7","1.2.21"],["0.10.8","1.2.23"],["0.10.9","1.2.24"],["0.10.10","1.2.25"],["0.10.11","1.2.30"],["0.10.12","1.2.32"],["0.10.13","1.3.2"],["0.10.14","1.3.5"],["0.10.16","1.3.8"],["0.10.19","1.3.11"],["0.10.22","1.3.14"],["0.10.23","1.3.17"],["0.10.24","1.3.21"],["0.10.25","1.3.24"],["0.10.26","1.4.3"],["0.10.27","1.4.8"],["0.10.28","1.4.9"],["0.10.29","1.4.14"],["0.10.30","1.4.21"],["0.10.31","1.4.23"],["0.10.32","1.4.28"],["0.10.41","1.4.29"],["0.10.44","2.15.0"],["0.10.45","2.15.1"]]}, {"line":"0.11","latest":"0.11.16","bundles":[["0.11.0","1.2.15"],["0.11.1","1.2.18"],["0.11.2","1.2.21"],["0.11.3","1.2.25"],["0.11.4","1.3.4"],["0.11.5","1.3.6"],["0.11.6","1.3.8"],["0.11.8","1.3.13"],["0.11.9","1.3.15"],["0.11.10","1.3.22"],["0.11.11","1.3.25"],["0.11.12","1.4.3"],["0.11.13","1.4.9"],["0.11.14","2.0.0"],["0.11.15","2.1.6"],["0.11.16","2.3.0"]]}, {"line":"0.12","latest":"0.12.18","bundles":[["0.12.0","2.5.1"],["0.12.2","2.7.4"],["0.12.3","2.9.1"],["0.12.4","2.10.1"],["0.12.5","2.11.2"],["0.12.7","2.11.3"],["0.12.8","2.14.9"],["0.12.13","2.15.0"],["0.12.14","2.15.1"],["0.12.18","2.15.11"]]}, {"line":"4","latest":"4.9.1","bundles":[["4.0.0","2.14.2"],["4.1.0","2.14.3"],["4.1.1","2.14.4"],["4.2.0","2.14.7"],["4.2.4","2.14.12"],["4.4.0","2.14.20"],["4.4.2","2.15.0"],["4.4.3","2.15.1"],["4.4.5","2.15.5"],["4.4.7","2.15.8"],["4.5.0","2.15.9"],["4.6.2","2.15.11"]]}, {"line":"5","latest":"5.12.0","bundles":[["5.0.0","3.3.6"],["5.1.0","3.3.12"],["5.6.0","3.6.0"],["5.8.0","3.7.3"],["5.10.0","3.8.3"],["5.11.0","3.8.6"]]}, {"line":"6","latest":"6.17.1","bundles":[["6.0.0","3.8.6"],["6.2.0","3.8.9"],["6.2.1","3.9.3"],["6.2.2","3.9.5"],["6.3.0","3.10.3"],["6.8.0","3.10.8"],["6.9.2","3.10.9"],["6.9.3","3.10.10"]]}, {"line":"7","latest":"7.10.1","bundles":[["7.0.0","3.10.8"],["7.1.0","3.10.9"],["7.2.1","3.10.10"],["7.4.0","4.0.5"],["7.5.0","4.1.2"],["7.8.0","4.2.0"]]}, {"line":"8","latest":"8.17.0","bundles":[["8.0.0","5.0.0"],["8.1.0","5.0.3"],["8.2.0","5.3.0"],["8.7.0","5.4.2"],["8.9.0","5.5.1"],["8.9.4","5.6.0"],["8.12.0","6.4.1"],["8.17.0","6.13.4"]]}, {"line":"9","latest":"9.11.2","bundles":[["9.0.0","5.5.1"],["9.4.0","5.6.0"]]}, {"line":"10","latest":"10.24.1","bundles":[["10.0.0","5.6.0"],["10.3.0","6.1.0"],["10.8.0","6.2.0"],["10.10.0","6.4.1"],["10.16.0","6.9.0"],["10.17.0","6.11.3"],["10.18.0","6.13.4"],["10.20.0","6.14.4"],["10.22.0","6.14.6"],["10.23.0","6.14.8"],["10.23.1","6.14.10"],["10.23.3","6.14.11"],["10.24.1","6.14.12"]]}, {"line":"11","latest":"11.15.0","bundles":[["11.0.0","6.4.1"],["11.6.0","6.5.0-next.0"],["11.7.0","6.5.0"],["11.10.0","6.7.0"]]}, {"line":"12","latest":"12.22.12","bundles":[["12.0.0","6.9.0"],["12.7.0","6.10.0"],["12.8.0","6.10.2"],["12.10.0","6.10.3"],["12.11.0","6.11.3"],["12.13.0","6.12.0"],["12.13.1","6.12.1"],["12.14.0","6.13.4"],["12.16.2","6.14.4"],["12.18.1","6.14.5"],["12.18.3","6.14.6"],["12.19.0","6.14.8"],["12.20.1","6.14.10"],["12.20.2","6.14.11"],["12.22.1","6.14.12"],["12.22.2","6.14.13"],["12.22.4","6.14.14"],["12.22.6","6.14.15"],["12.22.10","6.14.16"]]}, {"line":"13","latest":"13.14.0","bundles":[["13.0.0","6.12.0"],["13.1.0","6.12.1"],["13.2.0","6.13.1"],["13.4.0","6.13.4"],["13.7.0","6.13.6"],["13.9.0","6.13.7"],["13.12.0","6.14.4"]]}, {"line":"14","latest":"14.21.3","bundles":[["14.0.0","6.14.4"],["14.3.0","6.14.5"],["14.6.0","6.14.6"],["14.7.0","6.14.7"],["14.9.0","6.14.8"],["14.15.2","6.14.9"],["14.15.4","6.14.10"],["14.15.5","6.14.11"],["14.16.1","6.14.12"],["14.17.0","6.14.13"],["14.17.4","6.14.14"],["14.17.6","6.14.15"],["14.19.0","6.14.16"],["14.19.2","6.14.17"],["14.21.3","6.14.18"]]}, {"line":"15","latest":"15.14.0","bundles":[["15.0.0","7.0.2"],["15.0.1","7.0.3"],["15.1.0","7.0.8"],["15.3.0","7.0.14"],["15.4.0","7.0.15"],["15.5.0","7.3.0"],["15.6.0","7.4.0"],["15.7.0","7.4.3"],["15.8.0","7.5.1"],["15.9.0","7.5.3"],["15.11.0","7.6.0"],["15.12.0","7.6.3"],["15.13.0","7.7.6"]]}, {"line":"16","latest":"16.20.2","bundles":[["16.0.0","7.10.0"],["16.1.0","7.11.2"],["16.2.0","7.13.0"],["16.3.0","7.15.1"],["16.4.0","7.18.1"],["16.5.0","7.19.1"],["16.6.1","7.20.3"],["16.8.0","7.21.0"],["16.9.0","7.21.1"],["16.10.0","7.24.0"],["16.11.0","8.0.0"],["16.12.0","8.1.0"],["16.13.1","8.1.2"],["16.14.0","8.3.1"],["16.14.1","8.5.0"],["16.15.0","8.5.5"],["16.15.1","8.11.0"],["16.17.0","8.15.0"],["16.18.0","8.19.2"],["16.19.0","8.19.3"],["16.20.0","8.19.4"]]}, {"line":"17","latest":"17.9.1","bundles":[["17.0.0","8.1.0"],["17.1.0","8.1.2"],["17.2.0","8.1.4"],["17.3.0","8.3.0"],["17.4.0","8.3.1"],["17.5.0","8.4.1"],["17.6.0","8.5.1"],["17.7.0","8.5.2"],["17.8.0","8.5.5"],["17.9.1","8.11.0"]]}, {"line":"18","latest":"18.20.8","bundles":[["18.0.0","8.6.0"],["18.1.0","8.8.0"],["18.2.0","8.9.0"],["18.3.0","8.11.0"],["18.4.0","8.12.1"],["18.6.0","8.13.2"],["18.7.0","8.15.0"],["18.8.0","8.18.0"],["18.9.0","8.19.1"],["18.10.0","8.19.2"],["18.13.0","8.19.3"],["18.14.0","9.3.1"],["18.14.2","9.5.0"],["18.16.0","9.5.1"],["18.17.0","9.6.7"],["18.18.0","9.8.1"],["18.19.0","10.2.3"],["18.19.1","10.2.4"],["18.20.0","10.5.0"],["18.20.3","10.7.0"],["18.20.5","10.8.2"]]}, {"line":"19","latest":"19.9.0","bundles":[["19.0.0","8.19.2"],["19.1.0","8.19.3"],["19.3.0","9.2.0"],["19.5.0","9.3.1"],["19.6.0","9.4.0"],["19.7.0","9.5.0"],["19.8.0","9.5.1"],["19.9.0","9.6.3"]]}, {"line":"20","latest":"20.20.2","bundles":[["20.0.0","9.6.4"],["20.2.0","9.6.6"],["20.3.0","9.6.7"],["20.4.0","9.7.2"],["20.5.0","9.8.0"],["20.6.0","9.8.1"],["20.7.0","10.1.0"],["20.10.0","10.2.3"],["20.11.0","10.2.4"],["20.12.0","10.5.0"],["20.13.0","10.5.2"],["20.14.0","10.7.0"],["20.16.0","10.8.1"],["20.17.0","10.8.2"]]}, {"line":"21","latest":"21.7.3","bundles":[["21.0.0","10.2.0"],["21.2.0","10.2.3"],["21.3.0","10.2.4"],["21.7.0","10.5.0"]]}, {"line":"22","latest":"22.23.4","bundles":[["22.0.0","10.5.1"],["22.1.0","10.7.0"],["22.3.0","10.8.1"],["22.5.0","10.8.2"],["22.9.0","10.8.3"],["22.10.0","10.9.0"],["22.13.0","10.9.2"],["22.18.0","10.9.3"],["22.21.0","10.9.4"],["22.22.2","10.9.7"],["22.22.3","10.9.8"],["22.23.3","10.9.9"]]}, {"line":"23","latest":"23.11.1","bundles":[["23.0.0","10.9.0"],["23.4.0","10.9.2"]]}, {"line":"24","latest":"24.22.2","bundles":[["24.0.0","11.3.0"],["24.3.0","11.4.2"],["24.5.0","11.5.1"],["24.8.0","11.6.0"],["24.10.0","11.6.1"],["24.11.1","11.6.2"],["24.13.1","11.8.0"],["24.14.0","11.9.0"],["24.14.1","11.11.0"],["24.15.0","11.12.1"],["24.16.0","11.13.0"],["24.18.0","11.16.0"],["24.19.0","11.17.0"],["24.20.0","11.19.0"],["24.22.0","11.19.1"]]}, {"line":"25","latest":"25.9.0","bundles":[["25.0.0","11.6.2"],["25.4.0","11.7.0"],["25.5.0","11.8.0"],["25.6.1","11.9.0"],["25.7.0","11.10.1"],["25.8.0","11.11.0"],["25.8.2","11.11.1"],["25.9.0","11.12.1"]]}, {"line":"26","latest":"26.13.0","bundles":[["26.0.0","11.12.1"],["26.1.0","11.13.0"],["26.3.0","11.16.0"],["26.4.0","11.17.0"],["26.6.0","11.18.0"],["26.7.0","11.19.0"],["26.8.2","11.19.1"],["26.11.0","11.20.0"]]} ↗
  • node.releaseSchedule (✅ verified): {"line":4,"start":"2015-09-08","lts":"2015-10-12","end":"2018-04-30","codename":"argon"}, {"line":5,"start":"2015-10-29","end":"2016-06-30"}, {"line":6,"start":"2016-04-26","lts":"2016-10-18","end":"2019-04-30","codename":"boron"}, {"line":7,"start":"2016-10-25","end":"2017-06-30"}, {"line":8,"start":"2017-05-30","lts":"2017-10-31","end":"2019-12-31","codename":"carbon"}, {"line":9,"start":"2017-10-01","end":"2018-06-30"}, {"line":10,"start":"2018-04-24","lts":"2018-10-30","end":"2021-04-30","codename":"dubnium"}, {"line":11,"start":"2018-10-23","end":"2019-06-01"}, {"line":12,"start":"2019-04-23","lts":"2019-10-21","end":"2022-04-30","codename":"erbium"}, {"line":13,"start":"2019-10-22","end":"2020-06-01"}, {"line":14,"start":"2020-04-21","lts":"2020-10-27","end":"2023-04-30","codename":"fermium"}, {"line":15,"start":"2020-10-20","end":"2021-06-01"}, {"line":16,"start":"2021-04-20","lts":"2021-10-26","end":"2023-09-11","codename":"gallium"}, {"line":17,"start":"2021-10-19","end":"2022-06-01"}, {"line":18,"start":"2022-04-19","lts":"2022-10-25","end":"2025-04-30","codename":"hydrogen"}, {"line":19,"start":"2022-10-18","end":"2023-06-01"}, {"line":20,"start":"2023-04-18","lts":"2023-10-24","end":"2026-04-30","codename":"iron"}, {"line":21,"start":"2023-10-17","end":"2024-06-01"}, {"line":22,"start":"2024-04-24","lts":"2024-10-29","end":"2027-04-30","codename":"jod"}, {"line":23,"start":"2024-10-16","end":"2025-06-01"}, {"line":24,"start":"2025-05-06","lts":"2025-10-28","end":"2028-04-30","codename":"krypton"}, {"line":25,"start":"2025-10-15","end":"2026-06-01"}, {"line":26,"start":"2026-05-05","lts":"2026-10-28","end":"2029-04-30","codename":"lithium"}, {"line":27,"start":"2027-04-22","lts":"2027-10-20","end":"2030-04-30"} ↗
  • node.nvmrc (✅ verified): {"file":".nvmrc","comment":"#","newest":["node","stable"],"newestLts":"lts/*","ltsPrefix":"lts/","previousLtsPrefix":"lts/-"} ↗
  • node.nodeVersionFile (✅ verified): {"file":".node-version"} ↗
  • node.engines (✅ verified): {"key":"engines","runtimeKey":"node"} ↗
  • node.inheritedVersionFiles (✅ verified): .nvmrc, .node-version, .tool-versions ↗
  • node.environmentProxy (✅ verified): {"variable":"NODE_USE_ENV_PROXY","value":"1","option":"--use-env-proxy","since":["22.21.0","24.0.0"],"proxyVariables":["HTTPS_PROXY","HTTP_PROXY","NO_PROXY"]} ↗
  • docker.imageReference (✅ verified): {"defaultHost":"docker.io","hosts":["docker.io","index.docker.io","registry-1.docker.io"],"officialNamespace":"library","defaultTag":"latest"} ↗
  • docker.syntax (✅ verified): {"comment":"#","escapeDirective":"escape","escapeCharacters":["\\","`"],"globalArgInstruction":"ARG"} ↗
  • docker.copySources (✅ verified): {"relativeTo":"context","parentNavigation":"removed","trailingSlash":"ignored"} ↗
  • docker.environment (✅ verified): {"instruction":"ENV","inheritedByStages":true,"spaceForm":true} ↗
  • docker.buildArguments (✅ verified): {"instruction":"ARG","runEnvironment":true,"inheritedByStages":true,"globalNeedsDeclaration":true,"environmentWins":true} ↗
  • docker.dockerfileNames (✅ verified): {"defaultName":"Dockerfile","suffix":".Dockerfile"} ↗
  • docker.dockerfilePrefix (❓ uncertain): Dockerfile. ❓ ↗
  • docker.containerfile (✅ verified): Containerfile ↗
  • docker.nodeImage (✅ verified): {"image":"node","bundles":"npm","variants":["alpine","slim","alpine3.23","alpine3.24","bookworm","bookworm-slim","trixie","trixie-slim"]} ↗
  • docker.nodeImageTags (❓ uncertain): {"tags":{"latest":"26","current":"26","lts":"26"}} ❓ ↗
  • docker.pythonImage (✅ verified): {"image":"python","bundles":"pip","variants":["alpine","slim","trixie","slim-trixie","bookworm","slim-bookworm","alpine3.23","alpine3.24"]} ↗
  • docker.pythonImageTags (❓ uncertain): {"tags":{"3":"3.15","latest":"3.15"}} ❓ ↗
  • devEngines (✅ verified): {"key":"devEngines","packageManagerKey":"packageManager","runtimeKey":"runtime"} ↗
  • devEnginesSince (✅ verified): 10.9.0 ↗
  • volta.manifest (✅ verified): {"key":"volta","tools":["node","npm","pnpm","yarn"]} ↗
  • volta.maintained (✅ verified): false ↗
  • asdf.toolVersionsFile (✅ verified): .tool-versions ↗
  • asdf.plugins (✅ verified): {"nodejs":"node","pnpm":"pnpm","yarn":"yarn","bun":"bun","deno":"deno","python":"python","uv":"uv","poetry":"poetry"} ↗
  • mise.config (✅ verified): {"files":[".mise.toml","mise.toml","mise/config.toml",".mise/config.toml",".config/mise.toml",".config/mise/mise.toml",".config/mise/config.toml"],"table":"tools","versionKey":"version","tools":{"node":"node","python":"python"}} ↗
  • githubActions.workflows (✅ verified): {"directory":".github/workflows","extensions":[".yml",".yaml"]} ↗
  • githubActions.jobId (✅ verified): {"pattern":"^[A-Za-z_][A-Za-z0-9_-]*$"} ↗
  • githubActions.setupNode (✅ verified): {"action":"actions/setup-node","installs":["node"],"inputs":[{"name":"node-version","kind":"version","tool":"node"},{"name":"node-version-file","kind":"version-file","tool":"node"}]} ↗
  • githubActions.setupNodeVersions (✅ verified): {"newest":["latest","current","node","*"],"newestLts":"lts/*","ltsPrefix":"lts/","previousLtsPrefix":"lts/-"} ↗
  • githubActions.setupNodeVersionFile (✅ verified): {"packageJson":"package.json","packageJsonOrder":["volta.node","devEngines.runtime","engines.node"],"textPattern":"^(?:node(js)?\\s+)?v?(?<version>[^\\s]+)$","toml":{"table":"tools","key":"node","versionKey":"version"}} ↗
  • githubActions.jobContainer (✅ verified): {"key":"container","imageKey":"image","envKey":"env"} ↗
  • githubActions.environmentKeys (✅ verified): {"key":"env","levels":["workflow","job","step"]} ↗
  • githubActions.environmentFile (✅ verified): {"variable":"GITHUB_ENV","format":"NAME=value","multilineMarker":"<<","laterSteps":true,"stepEnvironmentWins":true} ↗
  • githubActions.yamlAliases (✅ verified): {"accepted":true} ↗
  • githubActions.pnpmActionSetup (✅ verified): {"action":"pnpm/action-setup","installs":["pnpm"],"inputs":[{"name":"version","kind":"version","tool":"pnpm"}]} ↗
  • githubActions.pnpmSetup (✅ verified): {"action":"pnpm/setup","installs":["pnpm"],"inputs":[{"name":"version","kind":"version","tool":"pnpm"},{"name":"runtime","kind":"runtime"},{"name":"node-version-file","kind":"version-file","tool":"node"}]} ↗
  • githubActions.setupBun (✅ verified): {"action":"oven-sh/setup-bun","installs":["bun"],"inputs":[{"name":"bun-version","kind":"version","tool":"bun"},{"name":"bun-version-file","kind":"version-file","tool":"bun"}]} ↗
  • githubActions.setupDeno (✅ verified): {"action":"denoland/setup-deno","installs":["deno"],"inputs":[{"name":"deno-version","kind":"version","tool":"deno"},{"name":"deno-version-file","kind":"version-file","tool":"deno"}]} ↗
  • githubActions.setupPython (✅ verified): {"action":"actions/setup-python","installs":["python"],"inputs":[{"name":"python-version","kind":"version","tool":"python"},{"name":"python-version-file","kind":"version-file","tool":"python"},{"name":"pip-version","kind":"version","tool":"pip"}]} ↗
  • githubActions.setupUv (✅ verified): {"action":"astral-sh/setup-uv","installs":["uv"],"inputs":[{"name":"version","kind":"version","tool":"uv"},{"name":"version-file","kind":"version-file","tool":"uv"}]} ↗
  • githubActions.setupPdm (✅ verified): {"action":"pdm-project/setup-pdm","installs":["pdm"],"inputs":[{"name":"version","kind":"version","tool":"pdm","keywords":["head"]},{"name":"python-version","kind":"version","tool":"python"},{"name":"python-version-file","kind":"version-file","tool":"python"}]} ↗
  • githubActions.miseAction (✅ verified): {"action":"jdx/mise-action","inputs":{"install":"install","inlineConfig":"mise_toml","workingDirectory":"working_directory"},"inlineFile":"mise.toml"} ↗
  • githubActions.installPoetry (✅ verified): {"action":"snok/install-poetry","installs":["poetry"],"inputs":[{"name":"version","kind":"version","tool":"poetry"}]} ↗
  • githubActions.actionsPoetry (✅ verified): {"action":"abatilo/actions-poetry","installs":["poetry"],"inputs":[{"name":"poetry-version","kind":"version","tool":"poetry"}]} ↗
  • githubActions.setupRuby (✅ verified): {"action":"ruby/setup-ruby","installs":["bundler"],"inputs":[{"name":"bundler","kind":"version","tool":"bundler","keywords":["Gemfile.lock","default","latest","none"]}]} ↗
  • githubActions.codeScanningUpload (✅ verified): {"action":"github/codeql-action/upload-sarif","inputs":{"sarifFile":"sarif_file","category":"category"},"permissions":{"always":{"security-events":"write"},"privateRepositories":{"actions":"read","contents":"read"}}} ↗
  • githubActions.stopCommands (✅ verified): {"stop":"::stop-commands::{token}","resume":"::{token}::"} ↗
  • githubActions.annotations (✅ verified): {"commands":{"error":"error","warning":"warning","note":"notice"},"properties":{"file":"file","line":"line","title":"title"},"escape":[["%","%25"],["\r","%0D"],["\n","%0A"]],"escapeProperty":[[":","%3A"],[",","%2C"]]} ↗
  • githubActions.annotationLimits (✅ verified): {"perLevelPerStep":10,"perJob":50} ↗
  • githubActions.checkRuns (✅ verified): {"endpoints":{"create":"/repos/{repository}/check-runs","update":"/repos/{repository}/check-runs/{id}","list":"/repos/{repository}/commits/{ref}/check-runs"},"query":{"checkName":"check_name","filter":"filter","latest":"latest"},"apiVersion":"2022-11-28","permission":{"checks":"write"},"summaryMaxLength":65535,"annotationsPerRequest":50,"annotationLevels":{"error":"failure","warning":"warning","note":"notice"},"annotationTitleMaxLength":255,"annotationMessageMaxBytes":64000,"variables":{"apiUrl":"GITHUB_API_URL","repository":"GITHUB_REPOSITORY","sha":"GITHUB_SHA","eventPath":"GITHUB_EVENT_PATH","eventName":"GITHUB_EVENT_NAME"},"pullRequestHeadSha":["pull_request","head","sha"],"mergeCommitEvents":["pull_request","pull_request_review","pull_request_review_comment"]} ↗
  • githubActions.stepSummary (✅ verified): {"variable":"GITHUB_STEP_SUMMARY","maxBytes":1048576} ↗
  • npmRegistry.api (✅ verified): {"url":"https://registry.npmjs.org/","packagePath":"/{escaped name}","timeField":"time","distTagsField":"dist-tags","defaultTag":"latest","versionsField":"versions","scriptsField":"scripts","deprecatedField":"deprecated","installScripts":["preinstall","install","postinstall"]} ↗
  • npmRegistry.notFoundStatus (❓ uncertain): 404 ❓ ↗
  • npmRegistry.search (❓ uncertain): {"path":"/-/v1/search","maxSize":250,"weeklyDownloadsField":"downloads.weekly"} ❓ ↗
  • npmRegistry.githubPackagesTarballs (✅ verified): {"host":"npm.pkg.github.com","path":"/download/{scope}/{name}/{version}/{digest}"} ↗
  • npmRegistry.gitlabTarballs (✅ verified): {"path":"{scope}/{name}/-/{scope}/{name}-{version}.tgz"} ↗
  • npmRegistry.artifactoryTarballs (✅ verified): {"path":"{scope}/{name}/-/{scope}/{name}-{version}.tgz"} ↗
  • pypiIndex.api (✅ verified): {"url":"https://pypi.org/simple/","accept":"application/vnd.pypi.simple.v1+json","notFoundStatus":404,"filesField":"files","filenameField":"filename","uploadTimeField":"upload-time","yankedField":"yanked","versionsField":"versions","statusField":"project-status","statusValueField":"status","statusReasonField":"reason"} ↗
  • pypiIndex.projectStatus (✅ verified): {"blocked":["quarantined"],"warned":["archived","deprecated"]} ↗
  • claudeCode.hooks (✅ verified): {"settingsFile":".claude/settings.json","event":"PreToolUse","matcherSeparator":"|","input":{"event":"hook_event_name","tool":"tool_name","command":"tool_input.command","cwd":"cwd"},"output":{"container":"hookSpecificOutput","event":"hookEventName","decision":"permissionDecision","reason":"permissionDecisionReason"},"decisions":{"deny":"deny","ask":"ask"},"blockingExitCode":2,"onFailure":{"field":"onFailure","value":"block","since":"2.1.295"},"projectDir":"${CLAUDE_PROJECT_DIR}","settings":{"hooks":"hooks","matcher":"matcher","handlers":"hooks","type":"type","commandType":"command","command":"command","args":"args"}} ↗
  • claudeCode.hookContext (❓ uncertain): {"field":"additionalContext","withoutDecision":true,"inlineLimit":10000} ❓ ↗
  • claudeCode.sessionStart (✅ verified): {"event":"SessionStart","matchers":["startup","resume"],"projectDirVariable":"CLAUDE_PROJECT_DIR","firstResponseWaits":true,"missingScriptWithBlock":"blocks","blockedNotice":"failed; blocking because onFailure is \"block\"","cloudSetupScriptRunsBeforeClaudeCode":true} ↗
  • claudeCode.shellTools (✅ verified): {"tool":"Bash","shell":"bash"}, {"tool":"PowerShell","shell":"powershell"}, {"tool":"Monitor","shell":"bash"} ↗
  • claudeCode.commandlessInputs (✅ verified): {"tool":"Monitor","input":"tool_input.ws"} ↗
  • mcp.revisions (✅ verified): {"legacy":["2025-11-25","2025-06-18","2025-03-26","2024-11-05"],"modern":["2026-07-28"]} ↗
  • mcp.lifecycle (✅ verified): {"initialize":"initialize","initialized":"notifications/initialized","ping":"ping","request":{"protocolVersion":"protocolVersion","capabilities":"capabilities","clientInfo":"clientInfo"},"result":{"protocolVersion":"protocolVersion","capabilities":"capabilities","serverInfo":"serverInfo","instructions":"instructions"}} ↗
  • mcp.stateless (✅ verified): {"metaField":"_meta","protocolVersion":"io.modelcontextprotocol/protocolVersion","clientCapabilities":"io.modelcontextprotocol/clientCapabilities","clientInfo":"io.modelcontextprotocol/clientInfo","serverInfo":"io.modelcontextprotocol/serverInfo","discover":"server/discover","discoverResult":{"supportedVersions":"supportedVersions","capabilities":"capabilities","instructions":"instructions"},"resultType":{"field":"resultType","complete":"complete"},"caching":{"ttl":"ttlMs","scope":"cacheScope","publicScope":"public"},"unsupportedVersionData":{"supported":"supported","requested":"requested"}} ↗
  • mcp.tools (✅ verified): {"list":"tools/list","call":"tools/call","capability":"tools","fieldsSince":{"annotations":"2025-03-26","title":"2025-06-18","structuredContent":"2025-06-18"}} ↗
  • mcp.cancellation (✅ verified): {"method":"notifications/cancelled","requestId":"requestId"} ↗
  • mcp.errorCodes (✅ verified): {"parseError":-32700,"invalidRequest":-32600,"methodNotFound":-32601,"invalidParams":-32602,"internalError":-32603,"unsupportedProtocolVersion":-32022} ↗
  • mcp.errorId (✅ verified): {"optionalSince":"2025-11-25"} ↗
  • mcp.stdio (✅ verified): {"delimiter":"\n","batchRevisions":["2025-03-26"]} ↗
  • mcp.clients.claudeCode (✅ verified): {"addCommand":["claude","mcp","add"],"separator":"--","scopeOption":"--scope","projectScope":"project","transportOption":"--transport","stdioTransport":"stdio","projectFile":".mcp.json","serversKey":"mcpServers","projectDirVariable":"CLAUDE_PROJECT_DIR","projectDirReference":"${CLAUDE_PROJECT_DIR:-.}"} ↗
  • mcp.clients.claudeDesktop (✅ verified): {"configFiles":{"darwin":"~/Library/Application Support/Claude/claude_desktop_config.json","win32":"%APPDATA%\\Claude\\claude_desktop_config.json","linux":"~/.config/Claude/claude_desktop_config.json"},"serversKey":"mcpServers"} ↗
  • mcp.clients.vscode (✅ verified): {"file":".vscode/mcp.json","serversKey":"servers","typeField":"type","stdioType":"stdio","cwdField":"cwd","workspaceFolder":"${workspaceFolder}","addOption":"--add-mcp"} ↗
  • git.ignore (✅ verified): {"file":".gitignore","excludeFile":".git/info/exclude","indexFile":".git/index","trackedFilesIgnored":false} ↗
  • git.ignoreCase (✅ verified): {"configFile":".git/config","section":"core","key":"ignorecase","trueValues":["yes","on","true","1"]} ↗
  • git.repositoryEntry (✅ verified): {"entry":".git","submoduleEntry":"file"} ↗
  • windows.commandShims (✅ verified): {"extensions":[".cmd",".ps1"],"batchExtension":".cmd","argumentsVariable":"%*"} ↗
  • windows.batchArguments (✅ verified): {"extensions":[".bat",".cmd"]} ↗
  • osv.api (✅ verified): {"url":"https://api.osv.dev","queryBatchPath":"/v1/querybatch","vulnerabilityPath":"/v1/vulns/{id}","recordPage":"https://osv.dev/vulnerability/{id}","queriesField":"queries","resultsField":"results","vulnsField":"vulns","idField":"id","nextPageTokenField":"next_page_token","pageTokenField":"page_token","maxQueriesPerBatch":1000} ↗
  • osv.paging (✅ verified): {"perQuery":1000,"perBatch":3000} ↗
  • osv.ids (✅ verified): {"pattern":"^[a-zA-Z0-9:_.-]+$"} ↗
  • osv.service (✅ verified): {"rateLimit":null,"freshnessMinutes":15,"freshnessShare":0.995,"responseLimitBytes":33554432} ↗
  • osv.withdrawn (✅ verified): {"field":"withdrawn","inQueryResponses":false,"inRecordResponses":true} ↗
  • osv.malicious (✅ verified): {"idPrefix":"MAL-","database":"OpenSSF Malicious Packages","license":"Apache-2.0"} ↗
  • osv.ecosystems (✅ verified): {"npm":"npm","pypi":"PyPI","packagist":"Packagist"} ↗
  • osv.versionMatching (✅ verified): {"packagist":{"ignoredPrefixes":["v","V"]}} ↗
  • osv.dataExport (✅ verified): {"url":"https://storage.googleapis.com/osv-vulnerabilities","archivePath":"/{folder}/all.zip","folders":{"npm":"npm","pypi":"PyPI","packagist":"Packagist"},"recordEntry":"{id}.json","withdrawnIncluded":true} ↗
  • osv.affected (✅ verified): {"affectedField":"affected","packageField":"package","nameField":"name","ecosystemField":"ecosystem","versionsField":"versions","rangesField":"ranges","typeField":"type","eventsField":"events","versionRangeTypes":["SEMVER","ECOSYSTEM"],"events":{"introduced":"introduced","fixed":"fixed","lastAffected":"last_affected","limit":"limit"},"earliest":"0","unlimited":"*"} ↗
  • python.nameNormalization (✅ verified): {"separators":"[-_.]+","replacement":"-"} ↗
  • python.namePattern (✅ verified): ^([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9._-]*[A-Za-z0-9])$ ↗
  • python.projectFile (✅ verified): pyproject.toml ↗
  • python.wheelExtension (✅ verified): .whl ↗
  • python.sourceDistributionExtensions (✅ verified): .tar.gz, .zip, .tar.bz2, .tbz, .tgz, .tar, .tar.xz, .txz, .tlz, .tar.lz, .tar.lzma ↗
  • python.bundledPip (✅ verified): {"line":"3.9","latest":"3.9.25","bundles":[["3.9.0","20.2.3"],["3.9.5","21.1.1"],["3.9.6","21.1.3"],["3.9.7","21.2.3"],["3.9.8","21.2.4"],["3.9.11","22.0.4"],["3.9.17","23.0.1"]]}, {"line":"3.10","latest":"3.10.22","bundles":[["3.10.0","21.2.3"],["3.10.1","21.2.4"],["3.10.3","22.0.4"],["3.10.6","22.2.1"],["3.10.7","22.2.2"],["3.10.9","22.3.1"],["3.10.11","23.0.1"]]}, {"line":"3.11","latest":"3.11.18","bundles":[["3.11.0","22.3.0"],["3.11.1","22.3.1"],["3.11.4","23.1.2"],["3.11.5","23.2.1"],["3.11.8","24.0.0"]]}, {"line":"3.12","latest":"3.12.16","bundles":[["3.12.0","23.2.1"],["3.12.2","24.0.0"],["3.12.5","24.2.0"],["3.12.8","24.3.1"],["3.12.10","25.0.1"]]}, {"line":"3.13","latest":"3.13.18","bundles":[["3.13.0","24.2.0"],["3.13.1","24.3.1"],["3.13.3","25.0.1"],["3.13.4","25.1.1"],["3.13.6","25.2.0"],["3.13.10","25.3.0"],["3.13.13","26.0.1"],["3.13.14","26.1.2"],["3.13.15","26.2.1"],["3.13.17","26.2.2"]]}, {"line":"3.14","latest":"3.14.10","bundles":[["3.14.0","25.2.0"],["3.14.1","25.3.0"],["3.14.4","26.0.1"],["3.14.5","26.1.1"],["3.14.6","26.1.2"],["3.14.7","26.2.1"],["3.14.9","26.2.2"]]}, {"line":"3.15","latest":"3.15.2","bundles":[["3.15.0","26.2.1"],["3.15.1","26.2.2"]]} ↗
  • python.hatch (✅ verified): {"pyprojectTable":"tool.hatch","configFile":"hatch.toml"} ↗
  • python.virtualEnvironment (✅ verified): {"marker":"pyvenv.cfg","scripts":[{"platform":"posix","directory":"bin","names":["activate","activate.fish","activate.csh","Activate.ps1"]},{"platform":"windows","directory":"Scripts","names":["activate.bat","Activate.ps1"]}]} ↗
  • python.interpreter (✅ verified): {"executables":["python","python3","py"],"moduleOption":"-m","commandOption":"-c","valueOptions":["-W","-X","--check-hash-based-pycs"],"groupedShortOptions":true} ↗

Notes

Context recorded with verified facts.

npm

  • cooldown.configFiles: Any npm config layer works: project .npmrc (read only at the project root and not for global installs), ~/.npmrc, the global npmrc, npm_config_min_release_age or the CLI. package.json cannot set it. ↗
  • cooldown.unit: Type is null or Number; 0 turns the delay off. Fractional days are not documented. ↗
  • cooldown.default: Unchanged in npm 12. ↗
  • cooldown.securityUpdates: npm audit fix keeps the vulnerable version, warns that the fix was blocked (since 11.18.0) and exits non-zero. Add the package to min-release-age-exclude or relax the delay. ↗
  • installScripts.defaultPolicy: strict-allow-scripts (default false) turns a dependency script that allowScripts does not cover "from a warning into a hard error ... instead of running with a notice", so from 11.16.0 such scripts still run. npm 11.21.1 ran esbuild's postinstall on 2026-10-29 ("has install scripts not yet covered by allowScripts"); npm 12.2.1 blocked it ("had install scripts blocked"). The v11 install-scripts command page says scripts are blocked by default, which the config definition, the 11.16.0 pull request, the GitHub changelog and the test contradict. npm 12 also blocks implicit node-gyp builds and prepare scripts of git, file and link dependencies. ↗
  • installScripts.allowList.file: Only the root package.json counts; allowScripts in dependencies is ignored. npx, npm exec and global installs use the allow-scripts config instead. ↗
  • installScripts.disableAll: Default false. Overrides allowScripts and dangerously-allow-all-scripts. npm run/test/start still run the named script, but not its pre/post scripts. ↗
  • sources.git.values: root allows only git dependencies listed in the project package.json. ↗
  • sources.remoteTarball.values: Tarballs on the configured registry hostname are always allowed. The 2026-05-22 GitHub changelog mentions only all and none; the config reference also lists root. ↗
  • sources.file.values: The 2026-05-22 GitHub changelog mentions only all and none; the config reference also lists root. ↗
  • sources.file.default: npm 12 did not change the default. ↗
  • sources.directory.values: The 2026-05-22 GitHub changelog mentions only all and none; the config reference also lists root. ↗
  • sources.directory.default: npm 12 did not change the default. ↗
  • project.lockfiles: npm 11 and earlier prefer npm-shrinkwrap.json over package-lock.json when both exist; npm 12 no longer reads or writes npm-shrinkwrap.json (same format, rename it). ↗
  • project.workspaces: An array of folder paths or globs. ↗
  • user.files: userconfig defaults to ~/.npmrc ("The location of user-level configuration settings. This may be overridden by the npm_config_userconfig environment variable or the --userconfig command line option"); ~ is resolved against `this.env.HOME || homedir()`. Same in 11.21.1. The project .npmrc is loaded first and may set userconfig= itself. Only the keys above the first [section] header are settings (extra.npmrcFormat). ↗
  • user.settings: Every config definition is read from any config file; only prefix is refused in a project .npmrc. allowScripts in package.json is project-only: at user level the allow-list is the allow-scripts key (allow only, every name becomes true; resolve-allow-scripts.js), used where the root package.json has no allowScripts and for npx, npm exec and npm install -g. The source keys use the later of the disputed first versions. ↗
  • user.unknownKeys: Unknown .npmrc (file) configs warn by default, matching pre-npm-12 behavior, but error when strict-npmrc is set. ↗
  • user.invalidValueFails: A value of the wrong type is reported as invalid config and the default is used. ↗
  • user.weakening: A key in the project .npmrc replaces the user value, lists included (prototype chain, no merging); the CLI and npm_config_* variables beat both. dangerously-allow-all-scripts is on for every value but false, null and undefined: npm reads .npmrc values and npm_config_* variables with parseField (https://github.com/npm/cli/blob/v11.21.1/workspaces/config/lib/parse-field.js), which trims them, turns an empty value of a Boolean setting into true and only "true", "false", "null" and "undefined" into their values, and leaves 0, 1, yes or no as strings; load() does not run the nopt type check (validate() runs only in npm config), and arborist tests the flat option for truth (!this.options.dangerouslyAllowAllScripts in workspaces/arborist/lib/arborist/rebuild.js at 11.21.1). ↗
  • user.variables: Environment variables starting with npm_config_ are interpreted as configuration parameters; config values are case-insensitive, so NPM_CONFIG_FOO=bar works the same. loadEnv in workspaces/config/lib/index.js (11.21.1 and 12.2.1) skips variables whose value is empty and reads them in the order of the environment, so of two spellings the later one wins. userconfig defaults to ~/.npmrc (definitions.js), and npm exports the resolved path as npm_config_userconfig to every command it runs (see extra.childEnvironment), so that value names the default file. ↗
  • extra.environmentNames: loadEnv takes every variable whose name matches /^npm_config_/i, cuts the prefix and lowercases the rest (with _ as - but for a leading _), so NPM_CONFIG_REGISTRY and Npm_Config_Registry set registry as npm_config_registry does (decision D-143). ↗
  • extra.localPrefix: loadLocalPrefix: --prefix on the command line is the local prefix. Otherwise npm walks up from the current directory (walk-up-path yields the directory and each parent up to the root, with no other stop; "for (const p of walkUp(this.cwd))") and takes the first directory with a package.json file or a node_modules directory ("hasPackageJson || await dirExists(p, 'node_modules')"). Unless workspaces are set to false on the command line ("this.#get('workspaces', 'cli')", so --no-workspaces or --workspaces=false; .npmrc and npm_config_workspaces do not count) or npm runs in global mode, it walks on: each higher directory with a package.json is read with @npmcli/package-json normalize, and one that cannot be read or normalized (".catch(() => ({ content: {} }))") or has no workspaces is passed over; the first whose mapped workspaces include that directory ("w === this.localPrefix", the same path) becomes the prefix, and a .npmrc of the workspace is skipped ("ignoring workspace config at ${this.localPrefix}/.npmrc"). Without a match the prefix is the current directory ("this.localPrefix = this.cwd"). loadProjectConfig reads "resolve(this.localPrefix, '.npmrc')" as the project configuration, except in global mode and when that path is the userconfig file. Workspaces (@npmcli/map-workspaces 6.0.0, the version npm 12.2.1 locks, with glob 13.0.6 and minimatch 10.2.5, https://github.com/npm/map-workspaces/blob/v6.0.0/lib/index.js): an array of patterns or an object with a packages array, else EWORKSPACESCONFIG, and an entry that is not text throws too; the leading ! are removed and an odd number of them negates, then a leading ./ or leading slashes ("pattern.replace(/^\.?\/+/, '')"); a pattern drops the earlier negated patterns it matches as text, and each negated pattern drops the patterns it matches as text and is given to glob as ignore, with **/node_modules/**; glob gets every pattern with a trailing / (directories only) and its defaults: * and ** do not match a name that starts with a dot, ** does not follow symlinked directories, and matching ignores case on macOS and Windows; a match without package.json (ENOENT, ENOTDIR) is no workspace, another error and two workspaces of one name throw, and npm stops. normalize (https://github.com/npm/package-json/blob/v8.0.0/lib/normalize.js, steps bin and binDir) throws for a bin list with an entry that is not text and for directories.bin that is not text when bin is not set. No .git or home directory stops the walk. ↗
  • extra.childEnvironment: setEnvs gives the scripts and commands npm runs (npm run, npx, npm exec) every setting that is not its default as npm_config_<key> in lower case with - as _, whichever file or flag set it, unless the definition has envExport: false (allow-scripts, min-release-age and min-release-age-exclude in 11.21.1 and 12.2.1); keys npm does not know, such as pnpm keys in .npmrc, are exported too. userconfig is always exported, because its default is the literal ~/.npmrc and the value the resolved path. It also sets npm_execpath to the npm it runs. The same in 10.9.4 and 12.2.1 (12.x and 11.x also export npm_config_node_gyp and npm_config_npm_version). ↗
  • extra.denyList: A false entry in the root package.json allowScripts is an explicit denial: deny wins over allow, and denied packages are skipped silently, also under strict-allow-scripts ("const verdict = isScriptAllowed(node, policy); if (verdict === true || verdict === false) { continue }", the same in 11.16.0 check-allow-scripts.js). npm install-scripts deny writes a name-only false entry. ↗
  • extra.trustedPublishing: Publishing from GitHub-hosted runners with OIDC instead of a token. Provenance is generated automatically, only for a public package from a public repository. A new trusted publisher configuration expires unless its first publish succeeds within 2 days. It can be limited to npm stage publish (the default for configurations created after 2026-09-03). ↗
  • extra.stagedPublishing: Staging needs no 2FA, so CI can do it; approving or rejecting needs 2FA (CLI or npmjs.com). Staging a package that does not exist yet creates it with the public placeholder version 0.0.0-stage. Pre-release versions need an explicit --tag. --provenance also applies to npm stage publish. Rejecting the only staged version of such a new package also unpublished the placeholder (observed 2026-10-29 with npm 11.21.1), and after a whole package is unpublished its name is blocked for 24 hours (https://github.com/npm/documentation/blob/main/content/policies/unpublish.mdx). ↗
  • extra.trustCommand: Configures a trusted publisher from the CLI; needs 2FA on the account and write access, and the package must already exist. At least one permission flag is required. ↗
  • extra.tarballIdentity: What npm installs for an entry of package-lock.json is the tarball of resolved (after replace-registry-host), whatever its version field says: #extractOrLink in workspaces/arborist/lib/arborist/reify.js extracts <name>@<resolved> when resolved is set, and <name>@<version> only without it (12.2.1; the same code in 10.9.9). The allowScripts matcher of npm 12.2.1 takes the name and version of a registry package from resolved with this function (getTrustedRegistryIdentity in workspaces/arborist/lib/script-allowed.js: "Never use node.packageName / node.version here: those read from the tarball's own package.json and can be forged"): the path part after the last /-/ must be the file name of the URL, the part before it ends with the name, with the scope before it when that starts with @ (separated by / or %2f), and the file name is <name>-<version>.tgz with a version that semver.parse reads (semver 7.8.5 in npm 12.2.1: three numbers without leading zeros, an optional pre-release and build, an optional leading v, at most 256 characters; the version drops the v and the build). A path in another layout gives no name and version. versionFromTgz reads the whole URL, so a query or a fragment after the file name (.tgz?x=1, .tgz#x) gives none either, while npm still fetches the tarball: pacote 22.0.0 (the version npm 12.2.1 locks) fetches resolved as it is, or, when replace-registry-host replaces its host, new URL(path, registry) without query or fragment (lib/remote.js), and minipass-fetch 6.0.0 requests pathname and search, never the fragment (lib/request.js). The registry serves the file the path names, with its percent-escapes decoded as an HTTP server reads a path (decision D-136). ↗
  • extra.lockfileFormat: Entries under packages: resolved is the registry tarball URL, the git URL with its commit (git+ssh://… or git+https://…#sha), file:<path> for local tarballs and directories, or the link target when link is true. hasInstallScript marks a preinstall, install or postinstall script (prepare scripts of non-registry sources are not flagged). npm tells registry tarballs from other URLs with the registryTarball pattern (workspaces/arborist/lib/install-scripts.js), so a tarball URL on a registry host looks like a registry package. An entry without resolved is installed as <name>@<version> (workspaces/arborist/lib/arborist/reify.js, #extractOrLink, in 11.19.1 and 12.2.1), so its version field is the source then. Entries keep the dependency fields of their package.json: dependencies, optionalDependencies and peerDependencies for every package, devDependencies for the root (workspaces/arborist/lib/shrinkwrap.js, pkgMetaKeys and the isTop branch, in 11.21.1 and 12.2.1); a dependency declared there as a URL comes from that URL even when it is a registry tarball. ↗
  • extra.overrides: Only the root package.json counts. Keys are package names, optionally with a version or range (name@range), and nest to any depth to scope an override under a parent; "." inside a nested object overrides the parent package itself; values take any dependency specifier, including tarball URLs, and $name refers to the spec of a direct dependency. Overrides are not written to package-lock.json (checked with npm 11.21.1), so a URL override of a registry tarball looks like a registry package there. With replace-registry-host at its default npmjs, npm writes the configured registry in place of registry.npmjs.org in resolved URLs (workspaces/config/lib/definitions/definitions.js). ↗
  • extra.npmrcScope: Only the .npmrc at the root of the project npm runs in is read. Inside a workspace package npm moves the prefix to the workspace root (using-npm/workspaces.md) and warns "ignoring workspace config" for the package .npmrc (workspaces/config/lib/index.js). The project .npmrc "is not read in global mode, such as when running npm install -g" (same page, v11.21.1 and v12.2.1). ↗
  • extra.npmrcFormat: npm reads .npmrc with the ini package: 7.0.0 in npm 12.2.1, and 6.0.0, whose lib/ini.js is the same, in npm 11.10.0 to 11.21.1 (package-lock.json of npm/cli). A line whose first non-blank character is # or ; is a comment. An unquoted key or value ends at the first # or ; that is not escaped with a backslash, so ignore-scripts=true # note sets true; a value in double quotes is parsed as a JSON string and one in single quotes loses its quotes, both keeping # and ;. A line without = sets the key to true. A [name] header at the start of a line, with nothing but spaces after it, starts a section: the keys below it belong to that section until the next header. npm applies only the top-level keys as settings (#loadObject in workspaces/config/lib/index.js at v12.2.1), so a key below a header has no effect. ↗
  • extra.npmrcListSyntax: Array values are written by adding [] after the key, one line per value, e.g. min-release-age-exclude[]=@myorg/*. ↗
  • extra.allowAllScripts: Boolean, default false: runs every dependency install script whether or not allowScripts approves it; --ignore-scripts still wins. First present in the 11.16.0 definitions. ↗
  • extra.excludeWildcards: min-release-age-exclude takes package names or minimatch globs from its first version. ↗
  • extra.latestVersion: Marked as the latest GitHub release on 2026-10-28; the 11.x line is still maintained (11.21.1). ↗
  • extra.lineReleases: The newest release of each minor line from 9.0 to 12.2, and of the major lines 6, 7 and 8, among the versions of the npm package in the registry on 2026-11-03 (modified 2026-10-21); none of 10.x to 12.x is deprecated. The dist-tags agree (https://registry.npmjs.org/-/package/npm/dist-tags: latest 12.2.1, next-11 11.21.1, next-10 10.9.9, next-9 9.9.4, next-8 8.19.4, latest-7 7.24.2, latest-6 6.14.18), and so do the v<version> tags of npm/cli. npm does not publish a release twice, so a later run of npm install -g npm@11 installs this release or a newer 11.x. ↗
  • extra.rangeInstall: npm 12.2.1 depends on npm-pick-manifest ^12.0.0 and npm 11.21.1 on ^11.0.3 (package.json of npm/cli at those tags). For a range (npm install -g npm@11, npm@^11.10.0) or a tag (npm@latest, a bare npm), pickManifest returns the version of the latest dist-tag when it satisfies the range, runs on the Node.js in use (engineOk with nodeVersion, process.version by default) and is not deprecated; otherwise it sorts the versions that satisfy the range by: not avoided, not restricted, not staged, not deprecated and engine ok, engine ok, not deprecated, then semver.rcompare, and returns the first. So npm installs the newest release of the range that runs on that Node.js, and the newest release of the range when none does. ↗
  • extra.beforeInteraction: before is a date: npm installs only versions available on or before it. In 11.10.0 to 11.14.x the definitions of min-release-age and before name each other as exclusive, and npm stops with "--min-release-age cannot be provided when using --before" (or the reverse) once both are set in its config sources (#loadObject in workspaces/config/lib/index.js and definitions.js at v11.14.1). Since 11.15.0 both may be set: "If before and min-release-age are both set in the same source, before wins"; across sources the usual precedence applies (cli > env > project > user > global), so a before in the project .npmrc replaces its own min-release-age (definitions.js at v11.15.0 and v12.2.1; release notes of 11.15.0). ↗
  • extra.strictAllowScripts: strict-allow-scripts=true makes the install fail on a dependency with install scripts that allowScripts does not cover, instead of running them with a notice (default false). Entries denied with false are skipped silently; --ignore-scripts and --dangerously-allow-all-scripts override it. ↗
  • extra.strictAllowScriptsEffect: npm 12.2.1 still defines strict-allow-scripts (default false): "If true, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by allowScripts will fail the install instead of being blocked with a warning." Dependencies denied with false are still skipped silently; --ignore-scripts and --dangerously-allow-all-scripts override it. So the same .npmrc line keeps npm 11.16 to 11.x from running such scripts and makes npm 12 stop the install at them. The 11.16.0 effect is the one in strictAllowScripts (definitions.js at v11.16.0). ↗
  • extra.unknownNpmrcKeys: Matters for generated .npmrc files: keys npm does not know (e.g. pnpm-only keys) print a warning on every npm command. The 12.0.0 entry: unknown CLI flags "now throw instead of warning. (Unknown .npmrc configs still warn by default; opt into erroring with the new strict-npmrc config.)"; lib/base-cmd.js at 12.2.1 does the same. ↗
  • extra.commandLine: Aliases of install (add, i and the typo aliases in, ins, inst, insta, instal, isnt, isnta, isntal, isntall), install-test (it), exec (x) and init (create, innit), the same in 11.19.1. install-test takes the same arguments as install (docs/lib/content/commands/npm-install-test.md). npm exec and npx take the packages to download from --package; -p means --package only in npx (in npm it is --parseable); without --package the first positional argument names the package, and -c/--call takes a command string that runs with the packages, shell operators included (npm-exec.md). npm init <initializer> runs npm exec create-<initializer>: foo → create-foo, @usr → @usr/create, @usr/foo@2.0.0 → @usr/create-foo@2.0.0 (npm-init.md). ↗
  • extra.runnerOptions: npm parses its whole command line with nopt and the types of every setting (load in workspaces/config/lib/index.js at v12.2.1), and lib/commands/exec.js takes the packages from the setting package and the command line from call, so --package and --call count wherever they stand before --: before exec (npm --package=x exec y) and after the arguments. npm-exec.md ("npx vs npm exec"): "npm exec foo@latest bar --package=@npmcli/foo" resolves @npmcli/foo and runs foo@latest bar, and "a double-hyphen -- flag can be used to suppress npm's parsing of switches and options that should be sent to the executed command". npx puts -- before its first positional argument (bin/npx-cli.js), so there the options after it belong to the command. npm init and npm create do not pass --package on (lib/commands/init.js). Decision D-160. ↗
  • extra.valueOptions: npm options that always take a value: every definition whose type does not include Boolean, as --name, and the short forms -C (prefix), -L (location), -c (call), -m (message) and -w (workspace). Options whose type includes Boolean (such as color and browser) may stand alone, so they are taken for flags. ↗
  • extra.flagOptions: npm options whose type includes Boolean, which may stand alone: the definitions of 12.2.1 and of 11.21.1 (where shrinkwrap is one too; 12.2.1 adds ignore-existing, ignore-extension, ignore-patch-failures, allow-unused-patches, keep-edit-dir and strict-npmrc). With valueOptions they are every npm option, so an abbreviated option can be resolved as npm resolves it. ↗
  • extra.parsing: The shorthands npm passes to nopt: the list in definitions/index.js and the short names of the definitions (the same in 11.21.1). nopt (node_modules/nopt/lib/nopt-lib.js, versions 8.1.0 in npm 10.9.4, 9.0.0 in 11.21.1 and 10.0.1 in 12.2.1, same parse and resolveShort) strips every leading dash, so -reg, --reg and -registry work; takes an exact option first, then an exact shorthand, then a word of one-letter shorthands (-gD), then an unambiguous prefix of an option name (abbrev), then a prefix of a shorthand; and reads --no-<name> as a negated flag that takes no value. After the shorthands (resolveShort) nopt strips every leading no- in any case, each one inverting the flag, and then takes <name> as an exact option or an unambiguous prefix (abbrevs), so --no-ign is --no-ignore-scripts where no other option starts with ign (npm 11; npm 12 has ignore-existing too) and --no-no-ignore-scripts sets ignore-scripts to true; a negated flag takes a following true or false, inverted (definitions/index.js and definitions.js at v12.2.1 and lib/nopt-lib.js of nopt 10.0.1, read again 2026-11-01). npm 10 expands abbreviations silently, npm 11 warns "Expanding --regis to --registry. This will stop working in the next major version of npm." and npm 12 refuses them with EUNKNOWNCONFIG (abbrevHandler in workspaces/config/lib/index.js of 11.21.1 and 12.2.1). Shorthands are expanded only on the command line, not in .npmrc or npm_config_ variables. npx turns -p into --package and expands exact shorthands itself before npm exec reads the rest (bin/npx-cli.js). ↗
  • extra.versionSelection: tag (default latest): "If you ask npm to install a package and don't tell it a specific version, then it will install the specified tag"; like any setting it comes from --tag, npm_config_tag or .npmrc. A name without a version is name@* (npm-package-arg 14.0.0, lib/npa.js). npm-pick-manifest 12.0.0 (node_modules/npm-pick-manifest/lib/index.js) picks the version of that dist-tag when the range is * or the version satisfies the range, unless it is deprecated; otherwise the highest satisfying version, preferring versions that are not deprecated; prereleases match a range only when it names one, so name@* with latest on a prerelease installs that prerelease. npm exec and npm init pick with the same settings. ↗
  • extra.packageSpecs: Forms of npm install <spec>: a folder; a tarball file, whose name must end in .tar, .tar.gz or .tgz; a tarball URL, which must start with http:// or https://; a git remote URL with the protocol git, git+ssh, git+http, git+https or git+file; <githubname>/<githubrepo> or github:<githubname>/<githubrepo>; gist:, bitbucket: and gitlab: shorthands; <alias>@npm:<name>. The file: prefix for local paths is documented in docs/lib/content/configuring-npm/package-json.md (Local Paths). ↗
  • extra.registryConfig: userconfig, the location of user-level settings, defaults to ~/.npmrc; registry is the base URL of the npm registry (default https://registry.npmjs.org/); a per-project .npmrc can set it like any config key (docs/lib/content/using-npm/config.md). npm config set @myco:registry=http://reg.example.com associates a scope with a registry, and any npm install of a package with that scope then requests it from there (https://docs.npmjs.com/cli/v12/using-npm/scope#associating-a-scope-with-a-registry). ↗
  • extra.globalConfig: load() reads the builtin config, the command line, the environment (loadEnv), the project .npmrc, the user file (#get("userconfig")) and the global file (#get("globalconfig")), and a key of an earlier source in the order above wins. loadGlobalPrefix: the default prefix is PREFIX of the environment, else on Windows the directory of the Node.js executable ("c:\node\node.exe --> prefix=c:\node\") and elsewhere the directory above it ("/usr/local/bin/node --> prefix=/usr/local"), with DESTDIR joined in front on POSIX only; the default of globalconfig is a getter, resolve(prefix, "etc/npmrc"), of the prefix the command line, the environment or the user file sets (loadDefaults). userconfig, globalconfig and prefix are of type path (definitions.js), which parseField (parse-field.js at the same tag) trims, expands ${VAR} in and resolves: ~/ against the home directory, anything else against the current directory. ↗
  • extra.registryHostTarballs: #isRegistryResolvedTarball: a node whose every dependency edge has a registry spec (node.isRegistryDependency, workspaces/arborist/lib/node.js: npa(edge.spec).registry) and whose resolved URL, after replace-registry-host, has the origin of pickRegistry(npa(node.name)), the registry of its scope or else registry, and a path that starts with that registry's path, is extracted with allowRemote "all": "pacote's npa re-parses our name@URL spec as type=remote, so allowRemote would mis-fire on registry tarballs". The allow-remote definition says so for users: "Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally" (workspaces/config/lib/definitions/definitions.js). ↗
  • extra.registryOverrides: registry is a URL; userconfig and globalconfig are the user and global configuration files. Putting --foo bar on the command line sets the foo configuration parameter, and environment variables that start with npm_config_ are configuration parameters too, without regard to case (docs/lib/content/using-npm/config.md); @scope:registry is the key of a scope's registry (https://docs.npmjs.com/cli/v12/using-npm/scope). ↗
  • extra.configCommands: npm config set sets keys (in the user configuration unless location is given), delete (also rm and del) removes keys from every configuration file, edit opens a configuration file in an editor and fix repairs invalid items; get and list (ls) only read (the switch in exec, and docs/lib/content/commands/npm-config.md). npm set <key>=<value> runs npm config set with its arguments and fails without any (lib/commands/set.js); npm get only reads (lib/commands/get.js). npm pkg set, delete and fix write package.json back, get only reads (lib/commands/pkg.js). Other spellings of these commands come from commandNames. ↗
  • extra.linkCommands: npm link with package specs (linkInstall in lib/commands/link.js at v12.2.1, the same in 11.21.1): it loads the top-level packages of the global space, takes every spec that no package there matches (missingArgsFromTree), and installs those into the global space first (globalArb.reify with add: missing, after the strict-allow-scripts preflight of npm install and with its allow-scripts policy), so a registry name comes from the registry as with npm install -g; then it links each package into the project (localArb.reify with add: file:<global>/node_modules/<name>). A directory spec links that folder, and a spec that resolves to the project directory itself is dropped; without specs npm link links the current package into the global space (linkPkg). Its params include ignore-scripts, allow-directory, allow-file, allow-git and allow-remote; it refuses --global (ELINKGLOBAL). ln is its alias (commandNames), and unlink is an alias of uninstall. ↗
  • extra.commandNames: deref resolves a command name: camelCase to kebab-case (installTest is install-test), an exact command, a direct alias, else a unique abbreviation of the commands and alias names (abbrev 5.0.0, node_modules/abbrev/lib/index.js: every prefix that only one name starts with, and each name itself), whose aliases are followed to the command (npm install-cl is install-clean, then ci). So npm c, npm con, npm conf and npm confi are npm config, npm pk is npm pkg, npm exe is npm exec, npm ini is npm init and npm cre is npm create, so npm init; npm ex (exec, explain, explore) and npm install- are ambiguous. lib/npm.js resolves the first word with deref, and lib/cli/entry.js prints the usage and exits with 1 when it finds no command. deref and its use are the same in v11.21.1 and v10.9.9; their lists differ (11.21.1 also has adduser, add-user, shrinkwrap, star, stars and unstar and not patch; 10.9.9 has hook and run-script with the alias run, and not approve-scripts, deny-scripts, install-scripts, stage, trust, undeprecate or u, which the 11.13.0 changelog adds), and with them no word is install, install-test, install-ci-test, ci, update, exec, init, config, set or pkg that is not one with the lists of 12.2.1 (ad is install only with those of 12.2.1, u is update from 11.13.0). Decision D-162. ↗
  • extra.installOverrides: Settings that a single npm command can change on its command line or in its environment: "Putting --foo bar on the command line sets the foo configuration parameter", "--flag without specifying any value will set the value to true", "Any environment variables that start with npm_config_ will be interpreted as a configuration parameter", case-insensitive, and an environment configuration without a value is true (docs/lib/content/using-npm/config.md at v12.2.1). Types in definitions.js at v12.2.1: ignore-scripts Boolean, default false ("If true, npm does not run scripts specified in package.json files"); min-release-age null or Number of days; before null or Date; min-release-age-exclude a list exempt from min-release-age and before; dangerously-allow-all-scripts Boolean, which bypasses the allowScripts policy; allow-scripts a list of packages whose install scripts may run. A value other than true for ignore-scripts, any true value of dangerously-allow-all-scripts (the false values as in user.variables), any allow-scripts, before or min-release-age-exclude, and a min-release-age shorter than the policy weaken what depcurfew apply wrote. ↗
  • extra.settingOverrides: The settings depcurfew apply writes into .npmrc for installScripts and sources that installOverrides (the options and variables the install guard asks about) does not list, for doctor (decision D-166). npm takes its configuration from, "sorted by priority", the command line ("Putting --foo bar on the command line sets the foo configuration parameter", "Using --flag without specifying any value will set the value to true"), then the environment ("Any environment variables that start with npm_config_ will be interpreted as a configuration parameter", "Config values are case-insensitive", with underscores instead of dashes), then the .npmrc files, so either replaces a key of the project .npmrc for the commands it reaches; a --no- prefix sets false (booleanWords). In definitions.js at v12.2.1 strict-allow-scripts is a Boolean (default false), and parseField (workspaces/config/lib/parse-field.js) turns only "false", "null" and "undefined" into values that turn it off, so those weaken it where .npmrc sets it to true (apply writes it for an npm 11.16 to 11.x in use, which runs uncovered scripts without it). allow-git, allow-remote, allow-file and allow-directory take all, none or root; apply writes none for a source the policy denies, root allows the dependencies listed in the root package.json, and a value npm does not accept is reported as invalid and replaced by the default (all before npm 12; user.invalidValueFails), so every value but none weakens a denied source. ↗
  • extra.directoryOptions: prefix (short C, so -C dir is --prefix dir): "The location to install global items. If set on the command line, then it forces non-global commands to run in the specified folder." loadLocalPrefix in workspaces/config/lib/index.js (v12.2.1) reads it only from the command line ("this.#get('prefix', 'cli')"), takes it as the local prefix as given and does not walk up, so npm_config_prefix and .npmrc do not move a command; the project .npmrc is the one in that folder. ↗
  • extra.booleanWords: nopt, which parses the npm command line, also supports "--bool true or --bool false": a Boolean option followed by the word true or false takes it as its value and skips it, and a --no- prefix inverts the value (parse in lib/nopt-lib.js at v10.0.1, used by npm 12.2.1, and the same code at v9.0.0, used by npm 11.21.1). ↗
  • extra.installCommands: Commands that install packages into the project and their aliases: install (add, i, typo aliases, install-test and it), ci (clean-install, ic, install-clean, isntall-clean) with install-ci-test (cit, clean-install-test, sit), and update (up, upgrade, udpate; u only from npm 11.13.0, whose changelog adds it, so left out). The same in v10.9.9 (lib/utils/cmd-list.js). npm also accepts unique abbreviations of command names, which are not listed. ↗
  • extra.globalOption: global (short g) "Operates in global mode, so that packages are installed into the prefix folder instead of the current working directory" and sets location to global; npm install -g npm@<version> replaces the npm that runs (docs/lib/content/commands/npm-install.md: "In global mode (ie, with -g or --global appended to the command)"). ↗
  • extra.unknownConfigKeys: npm 10 loads every key of an .npmrc without checking whether it knows it (#loadObject only checks deprecated and exclusive keys), so a setting it does not have yet, such as min-release-age, is ignored without any message. checkUnknown first appears in v11.2.0 (workspaces/config/lib/index.js), which warns: Unknown project config "<key>". This will stop working in the next major version of npm. The 11.2.0 changelog does not name the change; the version comes from reading the code at the tags. npm 12 collects unknown keys to fail the command (v12.2.1), with the exact behavior not read. ↗
  • extra.cleanInstall: npm ci (the clean commands of installCommands): "The project must have an existing package-lock.json"; "If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock"; "It will never write to package.json or package-lock.json: installs are essentially frozen." lib/commands/ci.js at v12.2.1 loads the lockfile (loadVirtual), builds the ideal tree, throws "`npm ci` can only install packages when your package.json and package-lock.json are in sync" when validateLockfile finds a difference, and reifies with packageLock: true and save: false. So npm ci installs exactly the versions package-lock.json records, and a release-age delay cannot change which versions it installs; the settings of its params (ignore-scripts, allow-scripts, strict-allow-scripts, allow-git, allow-remote, allow-file, allow-directory) still apply. ↗
  • extra.scriptsOff: ignore-scripts (Boolean, default false; definitions.js at v12.2.1: "If true, npm does not run scripts specified in package.json files") is one of the params of npm ci and npm install (lib/commands/ci.js). On the command line --ignore-scripts sets it; "Any environment variables that start with npm_config_ will be interpreted as a configuration parameter", with underscores for dashes, and "Config values are case-insensitive, so NPM_CONFIG_FOO=bar will work the same". depcurfew counts only the value true (and the flag without a value) as off: parseField turns only "true" into true, and loadEnv skips empty values (user.variables). ↗
  • extra.nodeEngines: engines.node of npm/cli package.json, the same at the tags v11.0.0, v11.10.0, v11.16.0, v11.19.1 and v11.21.1 (^20.17.0 || >=22.9.0) and at v12.0.0 and v12.2.1 (^22.22.2 || ^24.15.0 || >=26.0.0, https://github.com/npm/cli/blob/v12.2.1/package.json). On a Node.js outside the range npm only warns that it does not support it: lib/cli/entry.js at v11.19.1 runs log.warn('cli', validateEngines.unsupportedMessage) when !satisfies(node, engines), for a Node.js "still unsupported and untested and might not work reliably", and lib/cli/validate-engines.js prints "ERROR: npm ... is known not to run on Node.js ..." when it fails with a SyntaxError. So npm install -g npm@11 on Node.js 18 installs an npm that is not meant to run there. ↗
  • extra.rootLifecycleScripts: A bare npm install in a project runs the lifecycle scripts of the project itself with runScript, outside arborist and its allowScripts gate: "const runRootLifecycle = !args.length && !isGlobalInstall && !ignoreScripts", preinstall before reify and install, postinstall, prepublish, preprepare, prepare and postprepare after it. npm ci does the same "if (!ignoreScripts)" (lib/commands/ci.js), and so do install.js and ci.js at v11.16.0. collectUnreviewedScripts in workspaces/arborist/lib/unreviewed-scripts.js skips "node.isProjectRoot || node.isWorkspace", so strict-allow-scripts never stops at them. using-npm/scripts.md: prepare "Runs on local npm install without package arguments (runs with flags like --production or --omit=dev, but does not run when installing specific packages like npm install express)". ↗
  • extra.omitOptional: omit: [Array, "dev", "optional", "peer"], "Dependency types to omit from the installation tree on disk"; include: "Dependency types specified in --include will not be omitted, regardless of the order in which omit/include are specified on the command-line"; optional: deprecated, "Alias for --include=optional or --omit=optional" (buildOmitList: obj.optional === false pushes optional to omit, true to include; omit then drops what include lists). --no-optional sets optional to false. Each is one key: the value of the highest layer that sets it wins (command line, then npm_config_* variables in any case, then the project .npmrc). parseField in workspaces/config/lib/parse-field.js splits a list from the environment at two line breaks ("list types get put in the environment separated by double-\n"), so NPM_CONFIG_OMIT=optional omits them and dev,optional is one unknown value. ↗

pnpm

  • cooldown.configFiles: pnpm-workspace.yaml works in every version that has the setting. The global config.yaml exists only from 11.0.0 ("the new global config.yaml"); pnpm 10 reads user-level settings from ~/.npmrc and <configDir>/rc instead (see user.files). pnpm 10 also reads minimum-release-age from .npmrc; pnpm 11+ reads only auth and registry settings from .npmrc and ignores the package.json "pnpm" field. ↗
  • cooldown.unit: Integer number of minutes, e.g. 1440 = 1 day; no duration strings. ↗
  • cooldown.default: The built-in 1440 is non-strict: pnpm adds immature versions to minimumReleaseAgeExclude instead of failing (see strictMode). ↗
  • cooldown.securityUpdates: No setting bypasses the delay. Since 11.0.0, pnpm audit --fix adds the minimum patched version of each advisory to minimumReleaseAgeExclude (since 11.22.0 only while it is still inside the window). ↗
  • installScripts.defaultPolicy: Unreviewed builds only warn in pnpm 10; strictDepBuilds is true by default since 11.0.0, so they fail the install. Prepare scripts of git-hosted dependencies are blocked since 10.26.0. ↗
  • installScripts.allowList.setting: Replaced onlyBuiltDependencies, which was removed in 11.0.0 (see legacyAllowList). Since 12.11.0, permissions.<package>.build takes precedence over allowBuilds (extra.buildPermissions). ↗
  • installScripts.disableAll: Default false; --ignore-scripts on the CLI. Also skips the project's own scripts. It does not stop the pnpmfiles (.pnpmfile.mjs, .pnpmfile.cjs, the pnpmfile and globalPnpmfile settings and the pnpmfiles of config-dependency plugins, extra.pnpmfiles), whose hooks still run and can change every setting; only ignorePnpmfile does ("Useful together with --ignore-scripts when you want to make sure that no script gets executed during install", pnpm/docs/pnpmfile.md at v12.17.0). resolve_pnpmfile_paths in pnpm/crates/cli/src/config_deps/hooks.rs at v12.17.0 tests ignore_pnpmfile only. ↗
  • sources.git.setting: Blocks git repositories and tarball URLs for transitive dependencies only; no setting blocks them as direct dependencies. ↗
  • sources.remoteTarball.setting: Blocks git repositories and tarball URLs for transitive dependencies only; no setting blocks them as direct dependencies. ↗
  • project.workspaces: Globs with ! exclusions. Without packages only the root is in the workspace; pnpm still reads settings from the file in single-package projects. pnpm ignores workspaces in package.json. ↗
  • user.files: getConfigDir: $XDG_CONFIG_HOME/pnpm when it is set, else ~/Library/Preferences/pnpm on macOS, %LOCALAPPDATA%/pnpm/config on Windows (~/.config/pnpm without LOCALAPPDATA) and ~/.config/pnpm elsewhere; the same in 10.34.9 (config/config/src/dirs.ts) and 12.17.0 (pnpm/crates/config-dir/src/lib.rs). pnpm 10 reads <configDir>/rc, INI with kebab-case keys (config/config/src/index.ts at 10.34.9; first version not tracked), and also ~/.npmrc for every setting, which beats rc: loadNpmConf reads the command line, npm_config_* variables, the project and workspace .npmrc, ~/.npmrc (userconfig, path.resolve(os.homedir(), ".npmrc") in https://github.com/pnpm/npm-conf/blob/v3.0.3/lib/defaults.js) and the global npmrc, and only then is rc added as "pnpm-global", below all of them (index.ts at 10.34.9). From 11.0.0 the settings file is <configDir>/config.yaml with camelCase keys (11.0.0 changelog: "the new global config.yaml"), and ~/.npmrc and <configDir>/auth.ini carry only auth, registry and network settings. The 11.x and 12.x docs page cli/config.md still names a global rc file for registry and auth settings, which that code no longer reads. ↗
  • user.settings: pnpm 10 reads the kebab-case keys from rc as from any .npmrc (config/config/src/types.ts: only-built-dependencies at 10.0.0, strict-dep-builds at 10.3.0, minimum-release-age and minimum-release-age-exclude at 10.16.0, block-exotic-subdeps at 10.26.0); since 10.13.0 build settings from these files apply only to projects whose package.json "pnpm" field and pnpm-workspace.yaml set none of dangerouslyAllowAllBuilds, onlyBuiltDependencies(File), neverBuiltDependencies or allowBuilds, and always to global installs. pnpm 11+ applies a config.yaml key only when isConfigFileKey accepts it and it is camelCase: the minimumReleaseAge keys and blockExoticSubdeps since 11.0.0, strictDepBuilds since 11.0.7 (in excludedPnpmKeys in 11.0.0-11.0.6). allowBuilds is project-only from 11.0.0 and dropped with a warning, so pnpm 11+ has no user-level allow-list. pnpm 12 silently drops blockExoticSubdeps from config.yaml although its key gate accepts it (clear_workspace_resolution_fields in pnpm/crates/config/src/workspace_yaml/workspace_scope.rs, 12.0.0 to 12.17.0). pnpm self-update takes the minimumReleaseAge settings only from config.yaml, the environment and the command line, never from the project. ↗
  • user.weakening: A key in pnpm-workspace.yaml replaces the user value, lists included (applyWorkspaceSetting: pnpmConfig[key] = value); PNPM_CONFIG_* variables and the command line beat both. In pnpm 10 the same keys in ~/.npmrc beat rc, and since 10.13.0 build settings from either file reach only projects without build settings of their own, and global installs (config/config/src/index.ts at 10.34.9; before 10.13.0 dangerously-allow-all-builds also joined a project's onlyBuiltDependencies). In config.yaml, dangerouslyAllowAllBuilds also overrides a project's allowBuilds: false in pnpm 11 and 12.0.0-12.11.x (see extra.allowAllBuilds). pnpm 10 has no default delay and its strict-dep-builds and block-exotic-subdeps default to false, so 0 or false there weakens nothing; trustLockfile is a global key since it appeared in 11.3.0. The switch that allows every build is on for any value pnpm does not read as off, because pnpm tests it for truth (see extra.allowAllBuilds): in config.yaml only false, 0, null and an empty string are off, so "false", yes and "true" (strings for js-yaml) are on; in rc and ~/.npmrc pnpm 10 parses values with parseField of @pnpm/npm-conf (lib/util.js at https://github.com/pnpm/npm-conf/blob/v3.0.2/lib/util.js, the same in 3.0.3, which pnpm 10.28.0 and 10.34.9 use), which turns only "false", "null" and "undefined" into falsy values, an empty value of a Boolean setting into true, and leaves yes, 1 and 0 as strings, which are true. ↗
  • user.variables: pnpm 11 reads pnpm_config_<key> in lower case or PNPM_CONFIG_<KEY> in upper case, not mixed case (getEnvKeySuffix), over pnpm-workspace.yaml and under the command line; pnpm 12 reads the same two forms (pnpm/crates/config/src/env_overlay.rs at 12.17.0). pnpm 11+ ignores npm_config_* except npm_config_userconfig, which then moves only the auth .npmrc. The 11.0.0 release notes (https://github.com/pnpm/pnpm/releases/tag/v11.0.0): "pnpm no longer reads npm_config_* environment variables", "Added support for loading environment variables whose names start with pnpm_config_ into config"; pnpm 10.34.9 reads pnpm_config_ only for verify-deps-before-run (config/config/src/index.ts). pnpm 10 reads npm_config_* in any case, skipping empty values (addEnv in lib/conf.js of @pnpm/npm-conf 3.0.3), under pnpm-workspace.yaml (npmrcPrecedence), and parses them with the same parseField as .npmrc, so npm_config_dangerously_allow_all_builds is off only for false, null and undefined (1 and yes stay true strings); its npm_config_userconfig defaults to ~/.npmrc (lib/defaults.js). pnpm 11 parses a Boolean pnpm_config_ value with parseBoolean of env.ts, which takes only true as true (false gives false, any other text no value). XDG_CONFIG_HOME and LOCALAPPDATA move the config directory (user.files). ↗
  • extra.environmentNames: pnpm 11 reads pnpm_config_<key> only with the prefix and the key in lower case, or PNPM_CONFIG_<KEY> with both in upper case (getEnvKeySuffix with isLowerSnakeCase and isUpperSnakeCase), so Pnpm_Config_Registry sets nothing; pnpm 12 looks up PNPM_CONFIG_<KEY> and then pnpm_config_<key> (read_env in pnpm/crates/config/src/env_overlay/string_reader.rs, https://github.com/pnpm/pnpm/blob/v12.17.0/pnpm/crates/config/src/env_overlay/string_reader.rs). pnpm 10 reads npm_config_* in any case: addEnv in lib/conf.js of @pnpm/npm-conf 3.0.3 filters with /^npm_config_/i, and envKeyToSetting lowercases the key (https://github.com/pnpm/npm-conf/blob/v3.0.3/lib/envKeyToSetting.js). Decision D-143. ↗
  • extra.denyList: allowBuilds: { pkg: false } records a denial: the build is decided, not reported as unreviewed and does not fail strictDepBuilds ("A recorded build the policy denies was decided on purpose"). pnpm 10.26 maps false to ignoredBuiltDependencies, which only silences the report. Under dangerouslyAllowAllBuilds a denied package still builds before pnpm 12.12.0. ↗
  • extra.projectInstall: Commands that install the dependencies of the project: "pnpm install is used to install all dependencies for a project", "Aliases: i". pnpm add (commandLine.add) adds packages. pnpm without a command does not install. ↗
  • extra.commandLine: From cli/add.md, cli/pnx.md, cli/create.md and pnpm-cli.md at that commit. pnx (pnpm 12) has the aliases pnpm dlx and pnpx; pnpm 10 documents pnpm dlx with the alias pnpx (versioned_docs/version-10.x/cli/dlx.md). --shell-mode (-c) runs the command inside a shell, e.g. pnx --package cowsay -c 'echo hi | cowsay'. pnpm create maps foo and create-foo to create-foo, @scope to @scope/create and @scope/foo to @scope/create-foo, and runs it with pnx. --registry and --allow-build are shown with =, the other value options with a separate value. --package belongs to pnx (pnpm dlx) only and is listed there; before dlx it counts too (runnerOptions). -F is the short form of --filter (filtering.md). --reporter takes the name of a reporter (cli/install.md) and --loglevel a level (the loglevel setting in settings/cli.md, given as a flag); both take a separate value too. ↗
  • extra.runnerOptions: pnpm 10 parses the command line twice with @pnpm/nopt: first with the universal options and those of add and install, to find the command (there --package is taken for package-import-method, its only unambiguous expansion, so the word after it is its value), then the whole line with the options of that command, so the options of dlx count before dlx too, up to the first argument after dlx, from which on every word goes to the command (SPECIALLY_ESCAPED_CMDS). pnpm 11 does the same (https://github.com/pnpm/pnpm/blob/v11.28.10/pnpm11/cli/parse-cli-args/src/index.ts; package-import-method is still the only option of add and install that starts with package). pnpm 12 moves the options of the invoked subcommand that stand before it to right after it (relocate_pre_subcommand_flags, https://github.com/pnpm/pnpm/blob/v12.17.0/pnpm/crates/cli/src/flag_relocation.rs), and its dlx has --package and -c (pnpm/crates/cli/src/cli_args/dlx.rs). The documentation shows pnpm --package=@pnpm/meta-updater dlx meta-updater --help and pnpm --package cowsay --package lolcatjs -c dlx 'echo "hi pnpm" | cowsay | lolcatjs' (versioned_docs/version-10.x/cli/dlx.md in pnpm/pnpm.io). pnpm exec has no --package (exec/plugin-commands-script-runners/src/exec.ts at v10.34.9), and pnpm stops at an option the command does not know (pnpm/src/main.ts), so pnpm --package=x exec y downloads nothing. Decision D-160. ↗
  • extra.packageSpecs: Sources of pnpm add: the npm registry, jsr:, crate: and pypi: (other registries), workspace packages (the workspace: range protocol, docs/workspaces.md), local directories (./dir is saved as link:, file:./dir is copied), local tarballs ending in .tar, .tar.gz or .tgz, remote tarballs starting with http:// or https://, and git repositories as user/repo (github: by default), github:, bitbucket:, gitlab:, gist: or a full URL such as git+ssh://… or https://github.com/….git. ↗
  • extra.registryOverrides: registry and @scope:registry are read from the command line over .npmrc (docs/npmrc.md in pnpm/pnpm.io). Every pnpm_config_<key> or PNPM_CONFIG_<KEY> variable whose key is a setting sets it (src/env.ts, parseEnvVars), registry included. The user-level .npmrc, which may set any registry, is the file named by --npmrc-auth-file, --userconfig, pnpm_config_npmrc_auth_file, pnpm_config_userconfig, npmrcAuthFile in the global config.yaml or npm_config_userconfig (getNpmrcAuthFile; src/loadNpmrcFiles.ts reads it in place of ~/.npmrc). pnpm 10 reads npm_config_* variables as npm does. ↗
  • extra.parsing: pnpm parses its command line with @pnpm/nopt 0.3.1 (github.com/pnpm/nopt, lib/nopt.js), a fork of nopt: every leading dash is stripped, an exact shorthand or a word of one-letter shorthands is expanded, and an unambiguous prefix of an option of the command is taken for that option, so pnpm add --reg=<url> sets registry; --no-<name> is a negated flag: lib/nopt.js strips every leading no- in any case, each one inverting it, before the prefix is resolved, so --no-ign is --no-ignore-scripts when no other option of the command starts with ign (parse-cli-args, shorthands.ts and pnpm/nopt read again 2026-11-01). Options pnpm does not know make it stop with an error (pnpm11/pnpm/src/main.ts, dropUnknownOptions). --config.<key>=<value> sets the setting <key> (separateConfigDotArgs, normalizeOptions), also in pnpm 10.34.9 (cli/parse-cli-args/src/index.ts). The shorthands are pnpm11/pnpm/src/shorthands.ts; pnpm 10.34.9 has the same without y. ↗
  • extra.booleanWords: The nopt fork pnpm imports (@pnpm/nopt, imported by pnpm11/cli/parse-cli-args/src/index.ts at v12.16.1) reads a Boolean option followed by the word true or false as that value and skips the word, inverted after --no- (parse in lib/nopt.js). ↗
  • extra.directoryOptions: -C <path>, --dir <path>: "Run as if pnpm was started in <path> instead of the current working directory." -C is the shorthand of --dir (parsing.shorthands). pnpm11/cli/parse-cli-args/src/index.ts at v12.16.1 takes dir from the options nopt parsed from the whole command line ("let dir = parsedOpts['dir']") and looks for the workspace from it ("findWorkspaceDir((dir ?? process.cwd()) as string)"). -w, --workspace-root ("Run as if pnpm was started in the root of the workspace") is not listed: it names no directory. ↗
  • extra.configCommands: pnpm config (aliases: c) manages the configuration files: set <key> <value>, get <key>, delete <key> and list; get and list only read. pnpm pkg "Manages the contents of package.json from the command line": get, set, delete and fix, no aliases (docs/cli/pkg.md). ↗
  • extra.installOverrides: pnpm add takes --ignore-scripts ("Same as the ignoreScripts setting") and --allow-build, which lists packages allowed to run postinstall scripts (docs/cli/add.md in pnpm/pnpm.io; a ! prefix denies one instead, still asked about). Any setting can be given as --config.<key>=<value>, the key kept as written (normalizeOptions in pnpm11/cli/parse-cli-args/src/index.ts at v12.16.1), so both spellings are listed and the scanner reads the key without --config.. pnpm_config_<key> and PNPM_CONFIG_<KEY> set the setting of the camel-cased key; a Boolean only from the exact words true and false, a number with Number (parseEnvVars in env.ts). pnpm 10 reads npm_config_* variables as npm does (registryOverrides). minimumReleaseAgeStrict false installs a younger version when no older one matches (user.weakening). ↗
  • extra.minimumReleaseAgeStrict: When false, pnpm falls back to a version that does not meet minimumReleaseAge; when true, resolution fails. It defaults to true when minimumReleaseAge is set explicitly, except in 11.0.0-11.0.3 and 12.0.0-12.2.x (see strictMode): pnpm 11.0.0 and 12.0.0 installed a version 4 hours old with minimumReleaseAge: 4320 on 2026-10-29, and 12.0.0 added it to minimumReleaseAgeExclude. ↗
  • extra.cooldownExactVersions: pnpm 10.17.0: "Don't ignore the minimumReleaseAge check, when the package is requested by exact version". pnpm 10.16.0 installed typescript@7.1.0-dev.20261029.1, 4 hours old, with minimumReleaseAge: 4320 on 2026-10-29. ↗
  • extra.lockfileDocuments: A lockfile whose first line is --- has two YAML documents: a boot document with configDependencies and packageManagerDependencies, written when the project has config dependencies, declares devEngines.packageManager or pins pnpm 12 or newer; then the project lockfile (importers, packages, snapshots), which is always the last document. Seen with pnpm 12.16.1 and packageManager pnpm@12.16.1 on 2026-10-29. ↗
  • extra.lockfileFormat: lockfileVersion 9.0 (pnpm 9 to 12). Registry packages are keyed name@version; git dependencies name@git+<repo>#<commit> with resolution type git, or a tarball from a git host (gitHosted: true; older lockfiles lack the flag, so the host decides); tarball URLs name@https://…; local tarballs name@file:….tgz; local directories have resolution type directory; link: and workspace: dependencies appear only under importers. requiresBuild was removed in lockfile v9, so install scripts are not recorded. A tarball URL under the configured registry is resolved as that registry package and version (resolving/npm-resolver/src/parseBareSpecifier.ts in v10.34.9), so it is keyed name@version and keeps the URL only in the importer specifier; seen in lockfiles written by pnpm 10.34.9 and 12.16.1. ↗
  • extra.npmrcPrecedence: pnpm 10 applies pnpm-workspace.yaml settings over .npmrc and npm_config_* variables; command-line options win over both (same order on v10.16.0). The 10.18.3 changelog says pnpm config set --location=project writes to pnpm-workspace.yaml "matching read priority". The 10.x docs do not state the order. ↗
  • extra.npmrcCooldownKey: pnpm 10 reads minimum-release-age from .npmrc as a number and maps it to minimumReleaseAge (minutes), so the value means the same in both files; pnpm-workspace.yaml wins when both set it (npmrcPrecedence). pnpm 11.0.0 stopped reading it from .npmrc (ignoredSince). ↗
  • extra.sharedWorkspaceLockfile: Same name and default in pnpm 11 and 12, where it is read only from pnpm-workspace.yaml. ↗
  • extra.ignoredSince: Structured form of npmrcIgnored: from 11.0.0 on, other .npmrc settings and the package.json "pnpm" field have no effect. ↗
  • extra.allowAllBuilds: off: the values that leave it off. pnpm tests the value for truth and checks no type: pnpm 10 and 11 read pnpm-workspace.yaml with js-yaml (extra.yamlMergeKeys) and copy each key as it is (getOptionsFromPnpmSettings at 10.28.0, applyWorkspaceSetting at 11.28.10), so a string such as "false", "no" or "true" is on; depcurfew treats every value but false, 0, null and an empty string as on. pnpm 12 reads it into an Option<bool> (dangerously_allow_all_builds in pnpm/crates/config/src/workspace_yaml/settings.rs at 12.16.1) with the YAML 1.1 words of serde-saphyr 0.0.29 (parse_yaml11_bool: true, yes, y, on and false, no, n, off, in any case and also quoted), and stops on any other value, so no value is on there that depcurfew reads as off. Boolean, default false; added in 10.9.0 ("Added a new setting, dangerouslyAllowAllBuilds, for automatically running any scripts of dependencies without the need to approve any builds", pnpm/CHANGELOG.md at v10.26.0). Packages set to false in allowBuilds (or build: false in permissions) stay blocked only from pnpm 12.12.0 (release notes at https://github.com/pnpm/pnpm/releases/tag/v12.12.0: "A package set to false in allowBuilds no longer runs its build scripts when dangerouslyAllowAllBuilds is true", "Previously, dangerouslyAllowAllBuilds ignored the denials"). pnpm 10, 11 and 12.0.0-12.11.x run them too: createAllowBuildFunction returns before it reads the lists ("if (opts.dangerouslyAllowAllBuilds) return () => true" in building/policy at 11.28.10 and builder/policy/src/index.ts at 10.34.9; allow_build_policy.rs at 12.0.0). ↗
  • extra.excludeWildcards: Globs such as @myorg/* in minimumReleaseAgeExclude since 10.17.0. ↗
  • extra.onlyBuiltDependencies: The allow-list before allowBuilds: package.json pnpm.onlyBuiltDependencies, added in 6.32.0 ("If this field exists, only mentioned packages will be able to run install scripts") and working since 6.32.1 ("released with a bug in v6.32.0"); also pnpm-workspace.yaml since 10.5.0 (10.5.0 changelog); removed in 11.0.0 (settings/build.md, see legacyAllowList). Before pnpm 10 any list, even an empty one, lets only the listed packages build (createAllowBuildFunction in @pnpm/builder.policy 3.0.0, which pnpm 9.15.0 uses). ↗
  • extra.ignoredBuiltDependencies: The record of denied builds before allowBuilds (denyList): package.json pnpm.ignoredBuiltDependencies since 10.1.0 ("for explicitly listing packages that should not be built. When a package is in the list, pnpm will not print an info message about that package not being built"), and pnpm-workspace.yaml since 10.5.0 ("Allow to set the \"pnpm\" settings from package.json via the pnpm-workspace.yaml file"). The 10.26.0 entry for allowBuilds says that allowBuilds: { core-js: false } "achieves the same result as" ignoredBuiltDependencies: [core-js]. It only silences the report: createAllowBuildFunction (builder/policy/src/index.ts at v10.25.0) does not read it, so a package onlyBuiltDependencies names still builds. Deprecated in 10.26.0 and removed in 11.0.0 (see legacyAllowList). ↗
  • extra.npmrcBuildSettings: pnpm 10 reads dangerously-allow-all-builds from the project .npmrc as from every .npmrc, with parseField of @pnpm/npm-conf, so every value but false, null and undefined is on (user.weakening). From 10.13.0 config/config/src/index.ts takes the build settings of all .npmrc files and npm_config_* variables aside (extractAndRemoveDependencyBuildOptions) and applies them only when pnpm-workspace.yaml and the "pnpm" field of package.json (from which getOptionsFromRootManifest takes onlyBuiltDependencies, onlyBuiltDependenciesFile and neverBuiltDependencies) set none of projectKeys (hasDependencyBuildOptions: a key that is not null or undefined); the list gained allowBuilds in 10.26.0 (dependencyBuildOptions.ts at 10.13.0, 10.25.0, 10.26.0 and 10.28.0; the file does not exist in 10.12.1). Before 10.13.0 the .npmrc value applies unless pnpm-workspace.yaml sets dangerouslyAllowAllBuilds itself (npmrcPrecedence). pnpm 11 reads only auth and registry settings from .npmrc (ignoredSince). ↗
  • extra.yamlMergeKeys: pnpm-workspace.yaml and the global config.yaml (readWorkspaceManifest with cfgFileName) are read with read-yaml-file, which calls load of js-yaml with its default schema, and that schema has the merge type: read-yaml-file 3.0.0 with @zkochan/js-yaml 0.0.11 in 11.28.10, read-yaml-file 2.1.0 with @zkochan/js-yaml 0.0.9 in 10.28.0 and 0.0.11 in 10.34.9 (workspace/read-manifest/src/index.ts and pnpm-lock.yaml at those tags; lib/schema/default.js of the packages). pnpm 12 reads both files with serde_saphyr::from_str (pnpm/crates/config/src/workspace_yaml/parse_settings.rs at 12.16.1), whose default MergeKeyPolicy is Merge (serde-saphyr 0.0.29). So <<: *defaults brings the keys of the anchored map into the map, and settings set that way apply (a review run with pnpm 10.28.0: pnpm config get dangerouslyAllowAllBuilds gave true and installs ran scripts). A key written in the map itself wins over a merged one whatever their order (mergeMappings of js-yaml adds only missing keys; serde-saphyr adds merged entries whose key is not seen), and earlier maps of <<: [*a, *b] win over later ones; a quoted "<<" is an ordinary key. ↗
  • extra.latestVersion: pnpm 12.0.0 shipped on 26 Aug and 11.0.0 on 28 Apr (GitHub shows no year; 2026 inferred from release order). 11.x and 10.x still receive patches. ↗
  • extra.buildPermissions: permissions.<package>.build in pnpm-workspace.yaml: true lets the package run its build scripts, false denies them; the keys take the same forms as those of allowBuilds, and the entry outranks the package's allowBuilds entry (decided_build_approvals and apply_permissions in pnpm/crates/config/src/workspace_yaml/permissions.rs at v12.16.1, which warns when a package is in both). A string is an undecided placeholder (AllowBuild::Undecided in sections.rs). Added in 12.11.0 (docs/settings/build.md and docs/cli/permissions.md); pnpm approve writes a build decision there only when the file already has permissions. ↗
  • extra.strictDepBuilds: When true, an unreviewed dependency build script fails the install. ↗
  • extra.strictMode: In non-strict mode pnpm silently writes immature picks into minimumReleaseAgeExclude. Strict mode fails CI installs with ERR_PNPM_NO_MATURE_MATCHING_VERSION. ↗
  • extra.tarballResolution: pnpm fetches a registry package of pnpm-lock.yaml (a key name@version) from the tarball URL get-npm-tarball-url builds from the name and version, unless its resolution has tarball: then from that URL, resolved against the registry (new url.URL(resolution.tarball, registry)). pnpm 11.28.10 does the same (resolveTarballUrl in pnpm11/lockfile/utils/src/pkgSnapshotToResolution.ts). assertRegistryShapedResolution (lockfile/utils/src/assertRegistryShapedResolution.ts at v10.34.9) accepts any http(s) URL there for such a key, and a relative path without a scheme or a leading slash, which "is resolved against the configured registry", while the allowBuild policy "derives a trusted package identity from that key shape". pnpm writes tarball for a registry package whose tarball is not at the URL it would build. The fetch requests the path and the query of the URL, never the fragment, and the registry serves the file the path names. ↗
  • extra.rootLifecycleScripts: pnpm 11.28.10 runs the projects' own lifecycle scripts after linking "if (!opts.ignoreScripts && !opts.virtualStoreOnly)" (runProjectLifecycleScripts), with PROJECT_LIFECYCLE_STAGES = preinstall, install, postinstall, preprepare, prepare, postprepare for a full install and only the install stages for --prod or deploy (exec/lifecycle/src/runLifecycleHooksConcurrently.ts); allowBuilds only goes to the build of dependencies (allowBuild). pnpm 10.34.9 does the same in pkg-manager/core/src/install/index.ts and, for a frozen lockfile, pkg-manager/headless/src/index.ts ("if (!opts.ignoreScripts && !opts.ignorePackageManifest) await runLifecycleHooksConcurrently([preinstall, install, postinstall, preprepare, prepare, postprepare], ...)"). pnpm 12.16.1 picks PROJECT_LIFECYCLE_STAGES for a full install with devDependencies (project_script_stages in pnpm/crates/package-manager/src/install/lifecycle/uninstall.rs). ↗
  • extra.managesOwnVersion: 10.0.0: "manage-package-manager-versions: enabled by default. pnpm now manages its own version based on the packageManager field in package.json by default" (added in 9.7.0, off by default: "pnpm will switch to the version specified in the packageManager field of package.json ... This is the same field used by Corepack"). The 11.0.0 release notes replace the setting with pmOnFail, which "directly sets the onFail behavior of both packageManager and devEngines.packageManager" (https://github.com/pnpm/pnpm/releases/tag/v11.0.0); pnpm 12 documents pmOnFail with the default download: "download and run the declared pnpm version (this is the default and matches the previous managePackageManagerVersions: true behavior)" (pnpm/docs/settings/cli.md at v12.16.1). So any pnpm 10 or later honors a pnpm pin without Corepack. ↗
  • extra.configIncludes: "Added in: v12.15.0" (12.15.0 release notes, 21 Oct: "can now delegate settings to other YAML files and to config dependencies through a new include field"). include in the root pnpm-workspace.yaml maps a source to the settings it may define: a list of settings, which the source both may define and owns ("A list both permits and reserves its settings ... no other source may define them, even when the file omits them"), or '*' for a local file, which then owns the settings it defines that no other source owns. A local source starts with ./ or ../, is resolved from the workspace root, must end in .yaml or .yml and exist; a glob is rejected, and so is a file named twice or the root itself. Every other source is a config dependency named in configDependencies, which always needs a list. Settings defined in pnpm-workspace.yaml itself belong to it; a setting reserved twice, or defined where another source owns it, fails with ERR_PNPM_DUPLICATE_SETTING, a listed file that defines another setting with ERR_PNPM_SETTING_NOT_DELEGATED, a bad source with ERR_PNPM_INVALID_WORKSPACE_INCLUDE. A delegated setting the owner omits is not set by the project. Writes go to the owner: a delegated setting to its file even when the file omits it, a setting a '*' file defines stays there, one no source owns goes to pnpm-workspace.yaml, and one a config dependency owns cannot be changed (ERR_PNPM_SETTING_OWNED_BY_CONFIG_DEPENDENCY). Relative paths in an included file are relative to that file. The included files are read with merge keys like the root (normalize.rs applies <<). The spellings share one owner, so permissions and allowBuilds are one setting for ownership (canonical_setting_name in pnpm/crates/workspace/src/include/selector.rs); catalog is catalogs.default, catalogs.<name> one catalog and catalogs every catalog. Code: pnpm/crates/workspace/src/include.rs, include/selector.rs (parse_source, is_package_name_shaped, parse_delegation, SETTINGS_FORBIDDEN_TO_PACKAGES in include.rs), include/ownership.rs (reservations before definitions; the owner of a setting is its reservation, else its definition), include/package.rs (a config dependency's settings come from the YAML file its package.json names in pnpm.config, read from node_modules/.pnpm-config/<name> once installed); the same code at v12.15.0. Decision D-164. ↗
  • extra.bootConfig: bootConfig in pnpm-workspace.yaml sets the release-age and trust policy pnpm resolves and installs config dependencies and the pnpm version of packageManager under, before the settings of config dependencies are loaded (12.15.0 release notes: "The new bootConfig setting sets the release-age and trust policy pnpm uses to install config dependencies"). A setting it leaves unset or null takes its regular value; for a setting a config dependency owns, the value of the global config.yaml, the environment or the built-in default. The environment and the command line beat bootConfig (for_boot in pnpm/crates/config/src/boot_config.rs at v12.17.0). A config dependency cannot be delegated bootConfig (configIncludes.notForDependencies). Config dependencies pinned with version+integrity keep that pin (docs/config-dependencies.md). depcurfew neither writes nor checks it. ↗
  • extra.pnpmfiles: hooks.updateConfig "Allows you to modify the configuration settings used by pnpm" and "runs after the settings are merged and can still change any of them" (config-includes.md); since v12.4.1 it receives the resolved configuration, and since v12.8.0 only a setting given on the command line wins over it. Added in 10.8.0 ("Experimental. A new hook is supported for updating configuration settings. The hook can be provided via .pnpmfile.cjs", pnpm/CHANGELOG.md at v10.34.9). The project pnpmfile sits next to the lockfile (the workspace root): .pnpmfile.cjs since 6.0.0 ("pnpmfile.js renamed to .pnpmfile.cjs"); since 11.0.0 .pnpmfile.mjs, which "takes priority over .pnpmfile.cjs when present" (11.0.0 release notes). When the pnpmfile setting is set, also to [], pnpm does not look for these files ("Set pnpmfile: [] in pnpm-workspace.yaml when the workspace has no pnpmfile, so a new .pnpmfile.mjs is not picked up automatically", config-includes.md); its paths are relative to the file that sets it. globalPnpmfile is loaded first. ignorePnpmfile: true loads no pnpmfile, those of config-dependency plugins included: cli/cli-utils/src/getConfig.ts at v10.34.9, pnpm11/pnpm/src/getConfig.ts at v11.28.10 (installConfigDepsAndLoadHooks, tryLoadDefaultPnpmfile = config.pnpmfile == null), pnpm/crates/hooks/src/finder.rs (find_pnpmfiles) and pnpm/crates/cli/src/config_deps/hooks.rs (resolve_pnpmfile_paths, may_update_config) at v12.17.0; pnpm 12 does not take ignorePnpmfile from the global config.yaml (workspace_scope.rs). With sharedWorkspaceLockfile: false each project also runs the pnpmfile in its own directory (pnpmfile.md). ignoreScripts does not stop any of them (installScripts.disableAll). ↗
  • extra.configPlugins: "If your config dependency is named following the pnpm-plugin-*, @*/pnpm-plugin-*, or @pnpm/plugin-* pattern, pnpm will automatically load its pnpmfile.mjs (falling back to pnpmfile.cjs) from the package root." 10.13.0: "pnpm will now automatically load the pnpmfile.cjs file from any config dependency named @pnpm/plugin-* or pnpm-plugin-*"; 10.15.0: "Automatically load pnpmfiles from config dependencies that are named @*/pnpm-plugin-*" (pnpm/CHANGELOG.md at v10.34.9). The test is a prefix pnpm-plugin- or @pnpm/plugin-, or a scoped name containing /pnpm-plugin- (isPluginName in cli/cli-utils/src/getConfig.ts at v10.34.9 and pnpm11/pnpm/src/getConfig.ts at v11.28.10, is_plugin_name in pnpm/crates/hooks/src/finder.rs at v12.17.0). Such a pnpmfile loads also when the package supplies settings through include ("A config dependency whose name follows the plugin naming pattern still loads its pnpmfile", config-includes.md), unless ignorePnpmfile is true (extra.pnpmfiles). Config dependencies came in 10.0.0 ("configurational dependencies", then in the pnpm field of package.json); the docs of 10.x, 11.x and 12.17.0 declare them in pnpm-workspace.yaml. ↗
  • extra.knownPlugins: The official plugin's updateConfig sets minimumReleaseAge: 1 * 24 * 60 ("1 day in minutes") and blockExoticSubdeps: true with Object.assign, so it replaces a longer delay of pnpm-workspace.yaml. Versions 0.1.0 to 0.2.1 (the pnpmfile.cjs of the published packages on registry.npmjs.org) set neither; 0.3.0, published on 2026-03-01, is the latest. pnpm/docs/pnpmfile.md at v12.17.0 names it as the example of the hook. ↗

Yarn (Berry)

  • cooldown.configFiles: Also YARN_NPM_MINIMAL_AGE_GATE (general YARN_ env rule) and, since 4.17.0, npmScopes.<scope>.npmMinimalAgeGate. package.json cannot set it. ↗
  • cooldown.unit: npmMinimalAgeGate is a DURATION setting with unit: DurationUnit.MINUTES, and parseDuration (yarnpkg-core miscUtils.ts) takes a number without a unit in that unit, so bare numbers are minutes. Since 4.11.0 duration strings with ms, s, m, h, d or w (e.g. 3d, 1w) also work; on 4.10.x a string such as 7d silently had no effect. ↗
  • cooldown.availableSince: The setting arrived in 4.10.0 (release notes, pull request and source; the security docs page at https://yarnpkg.com/features/security says 4.12). 4.10.2 fixed it: "Bust the metadata cache" (#6908) and "support registries without publish times using minimalAgeGate" (#6907). On 2026-10-29 Yarn 4.10.1 with npmMinimalAgeGate: 4320 refused zod@3.23.8 and esbuild@0.25.0, both over a year old ("No candidates found"), while 4.10.2, 4.10.3, 4.11.0 and 4.12.0 installed them and refused a version 4 hours old. depcurfew writes the setting from 4.10.2 on. ↗
  • installScripts.defaultPolicy: Workspace scripts still run. Upgraded projects with an old lockfile get enableScripts: true written to .yarnrc.yml. Yarn 1 runs scripts unless --ignore-scripts is passed. ↗
  • installScripts.allowList.file: Root package.json only; ignored inside workspaces. ↗
  • installScripts.disableAll: Set in .yarnrc.yml; the default since 4.14.0. yarn install --mode=skip-build skips builds for one run. Berry ignores YARN_IGNORE_SCRIPTS. ↗
  • sources.git.default: Upgraded projects with an old lockfile get ["**"] written to .yarnrc.yml. ↗
  • project.lockfiles: Yarn Classic uses the same name; see berryLockfileMarker and classicLockfileHeader to tell them apart. ↗
  • project.workspaces: Array of folder glob patterns. ↗
  • user.files: Configuration.find adds .yarnrc.yml from the home folder (folderUtils.getHomeFolder: os.homedir(), else /usr/local/share) with the lowest priority, also for projects outside the home folder; the name stays .yarnrc.yml even when YARN_RC_FILENAME is set. The yarnrc page does not describe it; yarn config set -H writes the home file (https://yarnpkg.com/cli/config/set). The lookup is the same in 4.0.0, and the 2.2.0 changelog already speaks of the home configuration file; the first version was not tracked. ↗
  • user.settings: Configuration.use knows no project-only settings, so the home file sets these wherever the version has them; the first versions are those of cooldown, cooldown.exclude and sources.git, and enableScripts is checked in 4.0.0. enableScripts: false denies every dependency build script (scriptsSwitch); buildsDeny is the closest purpose, since Yarn has no strict mode. The allow-list dependenciesMeta.<package>.built is read from the root package.json only (Project.getDependencyMeta), so Yarn has no user-level allow-list. depcurfew does not write npmScopes.<scope>.npmMinimalAgeGate. ↗
  • user.unknownKeys: Configuration.use sets a key it does not know aside without an error when it comes from the home file, even with enableStrictSettings; other files throw. The 2.2.0 changelog: "Unsupported options will simply be silently ignored." ↗
  • extra.environmentNames: getEnvironmentSettings lowercases every name of process.env and takes those that start with yarn_ (ENVIRONMENT_PREFIX), and getRcFilename compares the lowercased name with yarn_rc_filename, so yarn_enable_scripts and Yarn_Enable_Scripts set enableScripts as YARN_ENABLE_SCRIPTS does (decision D-143). ↗
  • extra.registrySettings: npmRegistryServer: "Define the registry to use when fetching packages"; npmScopes: "Per-scope registry configurations", whose entries take npmRegistryServer ("See npmRegistryServer"), keyed by the scope without @. "While Yarn will automatically find them in the parent directories, they should usually be kept at the root of your project". Yarn (Berry) does not read registry= from .npmrc. ↗
  • extra.yamlMergeKeys: parseSyml reads .yarnrc.yml with load of js-yaml and FAILSAFE_SCHEMA, which has no merge type (only strings, sequences and maps), so <<: *defaults is an ordinary key named <<: Configuration.use rejects it as an unrecognized setting in a project .yarnrc.yml (enableStrictSettings, default true) and sets it aside in the home file, so merged values never apply. Every scalar is a string to Yarn, which parses it per setting (parseValue in packages/yarnpkg-core/sources/Configuration.ts). ↗
  • extra.classicUserFile: Yarn Classic (1.x, last release 1.22.22) reads .yarnrc and .npmrc from the project, its parent folders, the home folder (homeConfigLoc = ~/.yarnrc) and the global prefix (getPossibleConfigLocations in src/registries/npm-registry.js), and of .yarnrc.yml only yarnPath (yarnPathRuns), whose other settings only Yarn 2 and later read. depcurfew does not configure Yarn Classic. ↗
  • extra.yarnPathRuns: Yarn Classic 1.18.0 and later read yarnPath from .yarnrc.yml (CHANGELOG 1.18.0: "Adds support for reading yarnPath from v2-produced .yarnrc.yml files", #7350): getRcPaths in src/util/rc.js looks for .yarnrc and .yarnrc.yml in the folder and its parents, loadRcFile in src/rc.js keeps only yarnPath of a .yml file, resolved against its folder, and start() in src/cli/index.js runs node <yarnPath> before anything else, also before the check that packageManager names Yarn 1 (which only main() does). Yarn 2 and later do the same (run and runYarnPath in packages/yarnpkg-cli/sources/lib.ts at @yarnpkg/cli/4.18.1), unless YARN_IGNORE_PATH is set. So a release committed under yarnPath is the Yarn that runs, whichever Yarn starts, with or without Corepack, and its version (from the file name, extra.yarnPath) is the version of the project (decision D-165). ↗
  • extra.setVersion: setVersion saves the release as .yarn/releases/yarn-<version>.cjs, points yarnPath of the project .yarnrc.yml to it (a path relative to the project) and sets packageManager of package.json to yarn@<version>. In 4.18.1 it keeps yarnPath when the project already has one, when the release cannot be represented by Corepack, with --yarn-path or without Corepack enabled; otherwise it removes yarnPath and sets only packageManager. 3.6.4 always writes both (the same file at https://github.com/yarnpkg/berry/blob/%40yarnpkg/cli/3.6.4/packages/plugin-essentials/sources/commands/set/version.ts). The command runs in the Yarn yarnPath names, which is the one to upgrade. ↗
  • extra.classicLockfile: Yarn Classic (1.22.22) reads yarn.lock with its own parser: a comment that says yarn lockfile v<N> with N above LOCKFILE_VERSION 1 (src/constants.js) makes it throw "Can't install from a lockfile of version N"; indentation is two spaces per level (an odd count throws), keys and values are JSON strings in double quotes or words, several keys separated by commas share one value, key: value and key value both set a value, and a later key replaces an earlier one. A file with git conflict markers is read as its two sides, the second side winning per key (parseWithConflict). When the parser fails Yarn retries the file as YAML (FAILSAFE_SCHEMA), and a file with __metadata (Yarn 2 and later) is ignored (src/lockfile/index.js). Each top-level key is a pattern name@range (normalizePattern), an npm: range names another package (registry-resolver.js: npm:<name>@<range>), and its value is an entry, or a string naming another pattern that Yarn follows (Lockfile.getLocked). Lockfile.getLockfile writes version, resolved and integrity of an entry, and its name only when it differs from the name of the pattern, which it never does. An entry with resolved is fetched from that URL without the part after # (explodeHashedUrl in src/util/version.js; getLocked in src/package-request.js), with git (git+<protocol>:// or git://) for URLs that match gitResolved and from the disk for file: and relative paths (src/fetchers/tarball-fetcher.js), whatever its version field says; an entry without resolved is resolved again from its pattern. file:, link:, ./, ../ and absolute paths are local (file-resolver.js, link-resolver.js), whose entries have no resolved. depcurfew reads the name and version of a registry tarball URL as for package-lock.json (npm extra.tarballIdentity and lockfileFormat.registryTarball). ↗
  • extra.denyList: With built: false in the root package.json, Yarn reports that the build "has been explicitly disabled through configuration" as an info message instead of the warning that all build scripts are disabled; built: false also wins over enableScripts: true. Only the top-level manifest counts (CHANGELOG 2.0.0). ↗
  • extra.projectInstall: The install command ("install the project dependencies") has the paths [`install`] and Command.Default, so yarn without a command installs too. yarn add (commandLine.add) adds packages. ↗
  • extra.commandLine: dlx.ts (documented at https://yarnpkg.com/cli/dlx) downloads the package named by the command, or the ones given with -p/--package, into a temporary environment and runs it. create.ts (yarn create, not on yarnpkg.com) takes -p/--package as well and runs create-<name>: @foo becomes @foo/create, @foo/app becomes @foo/create-app, foo becomes create-foo, and a name that already matches ^create(-|$) is kept (so is create alone). yarn add (https://yarnpkg.com/cli/add) takes packages as arguments; of its options only --mode takes a value. yarn workspace <workspaceName> <commandName> … runs a command within that workspace, e.g. yarn workspace components add -D react (https://yarnpkg.com/cli/workspace). ↗
  • extra.runnerOptions: Clipanion, the command-line parser of Yarn, registers the options of a command with a path also before that path ("We allow options to be specified before the path"), so yarn -p x dlx y and yarn --package=x dlx y download x, as yarn dlx -p x y does; the words after the command go to it (Option.Proxy in packages/plugin-dlx/sources/commands/dlx.ts). lib/core.js of clipanion 4.0.0-rc.2, the version yarn.lock of @yarnpkg/cli/4.18.1 resolves, does the same; Clipanion has no release tags for its 4.0.0 releases, so the source is the commit of master that is 4.0.0-rc.4. Yarn passes its command line to Clipanion after taking a leading --cwd (checkCwd in packages/yarnpkg-cli/sources/lib.ts at @yarnpkg/cli/4.18.1). Decision D-160. ↗
  • extra.packageSpecs: Protocols besides npm: and git: exec:, file:, jsr:, link:, patch:, portal: and workspace:. link: connects an external directory (https://yarnpkg.com/protocol/link), portal: a relative path to a package folder (https://yarnpkg.com/protocol/portal) and file: copies a folder or tarball. ↗
  • extra.registryOverrides: Environment variables that start with yarn_ (any case) set the setting named by the camel-cased rest, so YARN_NPM_REGISTRY_SERVER sets npmRegistryServer, the registry packages are fetched from (https://yarnpkg.com/configuration/yarnrc#npmRegistryServer). getRcFilename reads yarn_rc_filename (any case) as the name of the configuration file instead of .yarnrc.yml. npmScopes, an object, cannot be set this way. ↗
  • extra.registryFetch: Yarn fetches a registry package of yarn.lock by its resolution: getLocatorUrl builds <registry>/<name>/-/<name>-<version>.tgz from the name of the locator and the version after npm:, cleaned by semverUtils.clean (packages/yarnpkg-core/sources/semverUtils.ts, which drops leading spaces, v and = and trailing spaces and keeps pre-release and build), and supports only a reference whose part before ? semver.valid accepts. The version field of the entry goes into the package Yarn builds from the lockfile (setupResolutions in packages/yarnpkg-core/sources/Project.ts) and is not used for the fetch. A patch: locator wraps the locator it patches, URL-encoded, up to #. An npm: reference with an __archiveUrl parameter is fetched from that URL instead (NpmHttpFetcher.ts). ↗
  • extra.lockfileFormat: Each entry has resolution: name@<locator>: npm:<version> for the registry, <repository>#commit=<sha> for git (GitHub shortcuts become https://github.com/<owner>/<repo>.git), an http(s) URL for tarballs, file:<path> (a .tgz or .tar.gz path is a tarball, anything else a directory), portal: and link: for directories, workspace: for workspace packages, and patch: around the URL-encoded original locator. No field records install scripts; dependenciesMeta.built: false is a user opt-out. ↗
  • extra.durationStrings: The 4.11.0 release notes list "Core: Create DURATION settings type" (#6942): npmMinimalAgeGate accepts a number followed by ms, s, m, h, d or w (e.g. 3d, 1w) since 4.11.0 (the pattern ^(\d*\.?\d+)(ms|s|m|h|d|w)?$ in the settings schema at 4.18.1); on 4.10.x such a string silently had no effect. ↗
  • extra.scriptsSwitch: off: the values Yarn reads as false. Configuration.ts reads a BOOLEAN setting with parseBoolean of miscUtils.ts, which takes true, 1, "true" and "1" as true and false, 0, "false" and "0" as false and throws on anything else, so enableScripts: 1 or "true" runs dependency build scripts like true (yarnrc docs: enableScripts, default true); depcurfew counts every value but the off ones as on, as for YARN_ENABLE_SCRIPTS (decision D-092). ↗
  • extra.excludeWildcards: Name globs such as @scope/* or package* in npmPreapprovedPackages. ↗
  • extra.classicLockfileHeader: Written as # yarn lockfile v${LOCKFILE_VERSION} with LOCKFILE_VERSION = 1 (src/constants.js). ↗
  • extra.latestVersion: Yarn 6 is still in preview. ↗
  • extra.directoryOptions: checkCwd takes --cwd <dir> or --cwd=<dir> only as the first argument ("argv[0] === `--cwd`", "argv[0].startsWith(`--cwd=`)"), and for yarn add also as the last two words ("argv[0] === `add` && argv[argv.length - 2] === `--cwd`"; "CRA adds `--cwd` at the end of the command"), removes them and runs the command with cli.defaultContext.cwd = ppath.resolve(cwd). Yarn finds the project and its .yarnrc.yml files from that directory. ↗
  • extra.configCommands: plugin-essentials registers config get, config set and config unset next to config (commands/config/*.ts at 4.18.1). yarn config set updates the project configuration, or the home configuration with -H/--home (commands/config/set.ts); yarn config and yarn config get only print settings (commands/config.ts: "This command prints the current active configuration settings"). ↗
  • extra.installOverrides: yarn add declares noTimeGate = Option.Boolean(`--no-time-gate`), "Disable the minimum release age check for this command" (plugin-essentials/sources/commands/add.ts at 4.18.1). getEnvironmentSettings lowercases every environment variable, keeps those starting with yarn_ and camel-cases the rest into a setting (ENVIRONMENT_PREFIX), so YARN_NPM_MINIMAL_AGE_GATE sets npmMinimalAgeGate, YARN_NPM_PREAPPROVED_PACKAGES npmPreapprovedPackages and YARN_ENABLE_SCRIPTS enableScripts; the values that keep scripts off are those of user.variables. ↗
  • extra.perScopeGate: getMinimalAgeGate: for a scoped package, a number in npmScopes.<scope>.npmMinimalAgeGate (the scope name without @) replaces the global gate, longer or shorter, and 0 turns the gate off for that scope (acceptance tests "npmScopes override" in features/npmMinimalAgeGate.test.ts at 4.18.1; the code is the same in 4.17.0 and absent in 4.16.0). Each npmScopes entry is a shape whose unset properties get their defaults (parseShape and getDefaultValue in yarnpkg-core Configuration.ts), so a scope listed only for its registry gets the default of 1d (scopablePackageGateSettings in plugin-npm index.ts) instead of the global gate; read from the code, no test covers that case. ↗
  • extra.upgradeMigration: LOCKFILE_MIGRATION_RULES: a lockfile of version below 9 gets approvedGitRepositories ["**"] and enableScripts true, below 10 npmMinimalAgeGate 0, each only when no configuration source sets the key (configuration.sources.get(rule.name) === undefined), saved with Configuration.updateConfiguration ("Migrated your project to the latest Yarn version"). Explicit values written by depcurfew prevent the migration. ↗
  • extra.missingPublishTime: shouldBeQuarantined: with a gate, a version whose publish time is missing from the registry document (publishTimes?.[version] undefined) is quarantined; since 4.10.2 ("fix: support registries without publish times using minimalAgeGate", #6907). ↗

Bun

  • cooldown.configFiles: Also the global $HOME/.bunfig.toml or $XDG_CONFIG_HOME/.bunfig.toml; local keys override global ones. Bun's .npmrc support has no min-release-age key. ↗
  • cooldown.cliFlag: bun install, add and update; bunx honors it only since 1.4.4. ↗
  • cooldown.unit: Plain numbers are seconds; 0 turns it off. Since 1.4.4 duration strings such as 90m, 12 hours, 3d or 2 weeks also work (the bunfig reference still documents seconds only). ↗
  • cooldown.exclude.patternSyntax: Since 1.4.4 --minimum-release-age-excludes replaces the bunfig list for one command. ↗
  • installScripts.defaultPolicy: Dependency scripts run only for Bun's built-in trusted list (npm-registry packages only since 1.4) or trustedDependencies; the root project's scripts run. First version of this policy not tracked. ↗
  • installScripts.allowList.setting: Replaces the built-in default list rather than extending it. bun pm trust and bun add --trust write it. ↗
  • installScripts.disableAll: Default false. Also --ignore-scripts or ignore-scripts=true in .npmrc. Skips the project's own scripts and trustedDependencies too. ↗
  • project.workspaces: Full glob syntax, including ! patterns. ↗
  • project.workspacesObjectKey: The object form also holds catalog and catalogs. ↗
  • user.files: Since 1.4.4 get_home_config_path takes the first of XDG_CONFIG_HOME and HOME that is a fully qualified path ("The XDG specification says to ignore $XDG_CONFIG_HOME when it is empty or a relative path"; docs/runtime/bunfig.mdx at 1.4.4: "When XDG_CONFIG_HOME is set to an absolute path, Bun reads the file there and not the one in $HOME"); HOME is USERPROFILE on Windows (src/bun_core/env_var.rs). Before 1.4.4 Bun uses XDG_CONFIG_HOME whenever it is set, also to an empty or relative value (XDG_CONFIG_HOME.get().or_else(HOME) in src/bunfig/arguments.rs at bun-v1.4.3; the same in 1.4.0 and, in Zig, getHomeConfigPath in src/cli/Arguments.zig at bun-v1.3.0 and bun-v1.3.14), and joins it with join_abs_string_buf, which puts a / in place of the first character of a value without a leading separator (_joinAbsStringBuf in src/resolver/resolve_path.zig at bun-v1.3.0, src/paths/resolve_path.rs at bun-v1.4.0): XDG_CONFIG_HOME=cfg gives /fg/.bunfig.toml, an empty value /bunfig.toml, so Bun then reads neither the file below the current directory nor ~/.bunfig.toml. Only one file is read, with no fallback when the XDG one is missing. Only package manager commands read it (bun install, add, remove, update, pm, bunx and so on), before the project bunfig.toml, whose keys win. 1.2.0 already reads it; the first version was not tracked. ↗
  • user.settings: parse_install reads both from the user file as from bunfig.toml (only globalDir and globalBinDir are user-only), as in 1.3.0 (bunfig.zig). trustedDependencies exists only in package.json and bunfig has no such key, so Bun has no user-level allow-list; install.ignoreScripts only turns scripts off. Write whole seconds: duration strings need 1.4.4. ↗
  • user.unknownKeys: The parser looks up only the keys it knows (install_obj.get), so another key, such as install.minimumReleaseAge before 1.3.0, is neither read nor reported. ↗
  • user.invalidValueFails: load_global_bunfig ends the process through report_bunfig_load_failure when the user file has a value Bun cannot read, e.g. minimumReleaseAge = "3d" before 1.4.4 ("Expected number of seconds for minimumReleaseAge"), so every package manager command fails; 1.3.0 crashed the same way. A file Bun cannot read at all is skipped. ↗
  • user.weakening: Both files fill one set of options, the user file first, so a key in the project bunfig.toml replaces the user value; an empty minimumReleaseAgeExcludes list is skipped, so a project's [] does not clear the user list. 0 turns the delay off (src/install/PackageManager/PackageManagerOptions.rs keeps only values above 0). The command line beats both files. ↗
  • extra.environmentNames: Options::load looks up BUN_CONFIG_REGISTRY, NPM_CONFIG_REGISTRY and npm_config_registry with env.get, each spelling as written; the map behind env.get (HashTable in src/dotenv/env_loader.rs, https://github.com/oven-sh/bun/blob/bun-v1.4.4/src/dotenv/env_loader.rs) is a StringArrayHashMap outside Windows and a CaseInsensitiveAsciiStringArrayHashMap on Windows, where names are not told apart by case. Decision D-143. ↗
  • extra.registrySettings: "Put bunfig.toml in your project root, alongside your package.json"; the global $HOME/.bunfig.toml (or $XDG_CONFIG_HOME/.bunfig.toml) is loaded too, and local keys win. "The default registry is https://registry.npmjs.org/. To change it": [install] registry, a string or { url, token }. "To configure a registry for a particular scope (for example, @myorg/<package>), use install.scopes": a key per scope (myorg = "https://registry.myorg.com/" or a table with url). ↗
  • extra.projectInstall: "if your project has a package.json, you can use bun install"; the page names no alias, so none is listed. bun add (commandLine.add) adds packages. ↗
  • extra.commandLine: Options of bun add (snippets/cli/add.mdx) and bunx (snippets/cli/bunx.mdx) typed string or number; --catalog takes its name only after =. -p is --package for bunx but the flag --production for bun add, so it is listed with bunx only. The short forms -F (--filter) and -c (--config) of bun add are left out because bunx does not document them, and an option wrongly read as taking a value would hide the package after it. bunx is an alias for bun x (docs/pm/bunx.mdx). bun create <template> runs the create-<template> package from npm unless a local template has that name; it also takes GitHub repositories and local paths (docs/runtime/templating/create.mdx). ↗
  • extra.runnerOptions: bun x reads every option before the package name, also those before x: Options::parse gets the command line after bun, with x as the subcommand name, and takes --package <name>, --package=<name>, -p <name> and -p=<name> wherever they stand before it, so bun --package=x x y and bun -p=x x y download x. bun finds its command by skipping each word that starts with - (which in src/runtime/cli/mod.rs at bun-v1.4.4), so in bun --package x x y it takes the value x for the command, and bun x runs only when that value is x. Decision D-160. ↗
  • extra.commandNames: Command::which compares the first word that does not start with - with each name as written (RootCommandMatcher::case, no prefixes and no other case): add and a run AddCommand, create and c CreateCommand (bun_create, which reads the word after the command word as the template whatever the command word was, so bun c foo runs bunx create-foo), install and i InstallCommand, or AddCommand with -g or --global anywhere on the line, ci InstallCommand, update and up, r, remove, rm and uninstall, build and bun; deploy, cloud, config, use, auth, login and logout are reserved, whoami and list run bun pm. Any other word runs a script, a file or a binary of the project (AutoCommand). AddCommand runs the same Subcommand::Add whichever word chose it (src/runtime/cli/add_command.rs). Decision D-162. ↗
  • extra.packageSpecs: Git dependencies: "Bun supports a variety of protocols, including github, git, git+ssh, and git+https", with the examples git@github.com:moment/moment.git and github:colinhacks/zod. Tarball URLs, local folders and local .tgz files are accepted too. ↗
  • extra.registryOverrides: bun add takes --registry and --config (-c), a configuration file (snippets/cli/add.mdx). BUN_CONFIG_REGISTRY sets the npm registry and environment variables take priority over bunfig.toml (pm/cli/install.mdx). ↗
  • extra.lockfileFormat: bun.lock (text, the default since 1.2) maps each package to a tuple starting with name@<spec>: name@<version> followed by the registry for npm, name@git+<repo>#<sha> and name@github:<owner>/<repo>#<sha> for git, name@https://… for tarball URLs, name@./x.tgz (without file:) for local tarballs, name@file:<dir> and name@link:<dir> for directories, name@workspace:<dir> for workspace packages. The info object carries hasInstallScript: true only since 1.4.4, with no lockfileVersion change, so a missing flag proves nothing for older files. bun.lockb is an undocumented binary format. ↗
  • extra.durationStrings: Since 1.4.4 minimumReleaseAge also takes duration strings such as 90m, 12 hours, 3d or 2 weeks; plain numbers stay seconds. ↗
  • extra.excludeWildcards: minimumReleaseAgeExcludes takes exact package names (and name@version since 1.4.4), no wildcards. ↗
  • extra.trustedDependenciesReplacesDefaults: So an empty list trusts no package: without the field Bun 1.4.4 ran esbuild's postinstall (esbuild is on the built-in list); with "trustedDependencies": [] it blocked it (bun pm untrusted listed it), tested on 2026-10-29. ↗
  • extra.directoryOptions: bun add: <ParamField path="--cwd" type="string"> "Set a specific current working directory" (Global Configuration & Context); bun install has the same option, "Set a specific cwd" (docs/snippets/cli/install.mdx at the same tag, General Configuration). ↗
  • extra.installOverrides: bun add @types/bun --minimum-release-age 259200 # seconds: "A number is in seconds", or a number with a unit such as 90m, 12 hours, 3d or 2 weeks (durationStrings). The page lists no environment variable for it. bun add --trust "adds the package to trustedDependencies in the project's package.json and installs it", so its lifecycle scripts run (docs/snippets/cli/add.mdx and docs/pm/lifecycle.mdx at bun-v1.4.4); lifecycle.mdx names no variable that turns scripts on, and ignore-scripts read from the environment "only turns scripts off". ↗

Deno

  • cooldown.setting: A number or string, or the object form { "age": ..., "exclude": [...] }. Covers npm and JSR packages. ↗
  • cooldown.configFiles: min-release-age in .npmrc since 2.8; also NPM_CONFIG_MIN_RELEASE_AGE. This page does not state precedence; denoland/deno#35458 gives CLI flag, deno.json, .npmrc, environment, built-in default. ↗
  • cooldown.fileSettings: NpmRc::parse reads min-release-age "in days" (min_release_age_days: Option<u64>; "npm interprets the value as a number of days"), the same in the .npmrc next to package.json or deno.json and in the home one (discover_npmrc in libs/resolver/npmrc.rs at v2.9.8); deno.json and --minimum-dependency-age take minutes (unit). ↗
  • cooldown.cliFlag: Alias --min-dep-age since 2.9.3. deno install honors it since 2.5.5; deno add, deno remove and deno x since 2.9.4. ↗
  • cooldown.unit: Numbers are minutes; strings may be an ISO-8601 duration (P3D, PT72H), an absolute date or an RFC3339 timestamp; 0 turns it off. The .npmrc format differs (see npmrcFormat). ↗
  • cooldown.default: Since 2.9 a 24-hour minimum applies when nothing is configured; set 0 to turn it off. Whether the default covers JSR is not stated. ↗
  • cooldown.exclude.patternSyntax: Before 2.9.2 wildcard entries were stored literally and never matched. No CLI flag or .npmrc key for exclusions. ↗
  • installScripts.defaultPolicy: npm lifecycle scripts run only when approved, and only with a node_modules directory. deno x / dx runs them after its download prompt is accepted. ↗
  • installScripts.allowList.setting: deno approve-scripts writes it. --allow-scripts=npm:pkg on the CLI exists since 1.45. ↗
  • installScripts.allowList.file: Must be set at the workspace root. ↗
  • sources.git.setting: git+https: and git+ssh: dependencies are not supported in package.json. ↗
  • sources.remoteTarball.setting: Tarball URL dependencies are not supported in package.json. ↗
  • sources.file.setting: No setting. Since 2.8 file: and link: entries are silently skipped (scope disputed, see fileLinkSkipped); deno.json "links" overrides dependencies with local packages. ↗
  • sources.directory.setting: No setting; local directories behave like file: and link: entries (see fileLinkSkipped). ↗
  • project.lockfiles: The default location; lock.path in deno.json can move it and "lock": false turns it off. ↗
  • project.workspaces: Paths of members; globs and ! exclusions since Deno 2.1. ↗
  • user.files: Deno has no user configuration file of its own (deno.json is looked up from the working directory upwards). It reads .npmrc next to package.json or deno.json and in the home directory (HOME, USERPROFILE on Windows), not the file named by NPM_CONFIG_USERCONFIG and not under XDG_CONFIG_HOME. Home discovery arrived in 1.45.0 (#24021); since 2.1.8 (#27119) the project and home files are merged key by key, before that a project .npmrc hid the home one (Releases.md). This is the ~/.npmrc that npm reads. A home .npmrc Deno may not read is skipped; one that does not parse stops the command. ↗
  • user.settings: 2.8.0: "feat(npmrc): support min-release-age (#33983)". A whole number of days (cooldownUnit); the same line sets npm's min-release-age, also in days. minimumDependencyAge.exclude and allowScripts exist only in deno.json (allowScripts at the workspace root), so Deno has no user-level exclusions or script settings. ↗
  • user.cooldownUnit: NpmRc::parse reads min-release-age "in days" (min_release_age_days: Option<u64>; "npm interprets the value as a number of days"): an INI number of 0 or more, or a text that parses as a whole number after ${VAR} expansion; anything else, such as 72h or 1.5, is ignored without a message, so the age comes from the next source. The project .npmrc wins over the home file (libs/resolver/npmrc.rs), and the days count only where deno.json and --min-dep-age set nothing; those take minutes, an ISO-8601 duration or an RFC 3339 date (libs/config/util.rs, libs/cli_parser/src/defs.rs). ↗
  • user.unknownKeys: NpmRc::parse reads registry, auth, replace-registry-host, min-release-age and trust-policy keys and skips every other key without a message. ↗
  • user.invalidValueFails: A min-release-age that is not a whole number of days, such as 72h, is ignored without a message (test "invalid value is ignored"), so the age silently comes from the next source. A home .npmrc that does not parse at all stops the command (libs/resolver/npmrc.rs). ↗
  • user.weakening: The age comes from the command line, then minimumDependencyAge in deno.json, then .npmrc (the project file over the home file), then NPM_CONFIG_MIN_RELEASE_AGE, then the built-in 1440 minutes; 0 from .npmrc turns it off (apply_minimum_dependency_age_fallbacks). The same line turns npm's delay off too. ↗
  • extra.denyList: The object form "allowScripts": { "allow": [...], "deny": ["npm:pkg"] } (schema since 2.6.0: "List of npm package constraints to deny running lifecycle scripts for"); deny beats allow, and a denied package is not added to the packages whose scripts were not run, so Deno does not warn about it. ↗
  • extra.commandLine: install.md: deno install [PACKAGES] installs packages and adds them to deno.json or package.json, deno add is its alias, deno install --global installs a package or script as a binary, and deno install --entrypoint (-e) [FILES] installs what the files use. -n/--name, --root, --os and --arch take a value; --allow-scripts and --node-modules-dir are shown with =. Since Deno 2.8 a name without a prefix is an npm package; JSR packages need jsr: (add.md). x.md: deno x runs a package from npm or JSR without installing it, like npx (deno x npm:create-vite my-app); --package (-p) names the package when the binary differs (deno x -p typescript tsc), and npm:<package>/<binary> picks one binary; deno x --install-alias creates the dx alias. In Deno 2.9.8 (github.com/denoland/deno, cli/args/flags.rs) an executable whose name ends in dx, denox or dnx runs as deno x, and libs/cli_parser/src/defs.rs (X_SUBCOMMAND with COMPILE_ARGS, PERMISSION_ARGS, RUNTIME_MISC_ARGS and INSPECT_ARGS) gives the options of deno x that take a separate value; the permission flags take theirs after =. -L/--log-level is a global option with a value. ↗
  • extra.lockfileFormat: deno.lock version 5 (the default since Deno 2.3) marks npm packages with lifecycle scripts as scripts: true (hasInstallScript from the registry or a preinstall, install or postinstall script, libs/npm/resolution/graph.rs); version 4 has no such field. An npm key is name@version, followed by _ and the versions of its peer dependencies when it has some: libs/lockfile/lib.rs takes the part before the first _ as name@version (key.split_once('_')). tarball is written only for registries other than the default one. Deno rejects git and http(s) dependencies in package.json and keeps file: dependencies out of the lockfile. ↗
  • extra.durationStrings: Strings are ISO-8601 durations (P3D, PT72H), an absolute date or an RFC3339 timestamp; the last two set a fixed cut-off instead of a delay. ↗
  • extra.cutoffDates: parse_enabled_minutes_duration_or_date: a string of digits is minutes, then an RFC 3339 timestamp (DateTime::parse_from_rfc3339), a timestamp whose offset has no colon or that has no seconds (%Y-%m-%dT%H:%M:%S%z, %Y-%m-%dT%H:%M%z), a date YYYY-MM-DD ("treat as midnight UTC"), then an ISO 8601 duration; "0" turns the delay off. A timestamp or a date is a fixed cutoff (NewestDependencyDate::Enabled), in the age of the object form too (to_minimum_dependency_age_config in libs/config/deno_json/mod.rs); a time without an offset is none of these and an error. The schema names the same forms: "'2025-09-16' for cutoff date, '2025-09-16T12:00:00+00:00' for cutoff time" (cli/schemas/config-file.v1.json). ↗
  • extra.ageObjectKey: In the object form of minimumDependencyAge, age holds the delay and exclude the exemptions. ↗
  • extra.excludeWildcards: A trailing * matches by prefix (npm:@scope/*) since 2.9.2; earlier wildcard entries never matched. ↗
  • extra.npmSpecifierPrefix: Exclusions and allowScripts entries name npm packages as npm:<name>. ↗
  • extra.allowAllScripts: allowScripts: true allows every npm lifecycle script. Only the JSON value true does: to_allow_scripts_config (libs/config/deno_json/mod.rs at v2.9.8) gives every package for true, none for false and null, and stops with "expected string array, boolean, or object" for a string or a number, so "true" or 1 cannot turn it on silently. ↗
  • extra.installOverrides: deno install --minimum-dependency-age=P3D: deno.json and the flag accept an ISO-8601 duration such as P3D or PT72H, or an integer of minutes, and 0 turns it off; --min-dep-age is its alias (cooldown.cliFlag). deno install --allow-scripts=<packages> lets those packages run their lifecycle scripts, which Deno does not run by default (runtime/reference/cli/install.md in denoland/docs). ↗

uv

  • cooldown.setting: Limits candidate packages to those uploaded before a date or, since 0.9.17, a duration ago. Compared with the upload time of each file, not the release date. false turns off a value from a lower-priority source (since 0.11.24). ↗
  • cooldown.configFiles: Top level of uv.toml or the [tool.uv] table of pyproject.toml. uv searches the current directory and its parents and uses the first directory with uv.toml or a pyproject.toml that has [tool.uv]; uv.toml wins over [tool.uv] in the same directory, with a warning. In a workspace only the root is read. User (~/.config/uv/uv.toml) and system (/etc/uv/uv.toml) files are merged below the project file; uv tool and uvx read only those. UV_EXCLUDE_NEWER overrides the files. ↗
  • cooldown.cliFlag: Also the UV_EXCLUDE_NEWER environment variable. ↗
  • cooldown.unit: A "friendly" duration such as 24 hours, 1 week or 30 days, or an ISO 8601 duration such as P7D; months and years are rejected, a day is always 24 hours. An RFC 3339 timestamp is a fixed cutoff instead of a rolling delay. ↗
  • cooldown.availableSince: Durations ("dependency cooldowns") since 0.9.17; before that exclude-newer took only dates, which do not move with time. Tested on 2026-10-30: uv 0.9.16 printed a warning that "100000 days" is not a date and resolved with no delay at all; 0.9.17 and later held back every version. ↗
  • cooldown.default: No default: without a value every upload time is accepted. ↗
  • cooldown.exclude.setting: A table mapping package names to false (exempt), a date or a duration; package values take precedence over the global and index values. ↗
  • cooldown.exclude.availableSince: The table exists since 0.8.4 (dates); false, which exempts a package, since 0.9.25. Tested on 2026-10-30: with a false entry, uv 0.9.17 warned "data did not match any variant of untagged enum" and ignored the whole [tool.uv] table, the delay included; 0.9.25 and 0.13.6 exempted the package. ↗
  • cooldown.exclude.patternSyntax: Keys are package names, compared after name normalization. ↗
  • installScripts.defaultPolicy: no-build defaults to false: source distributions, git and directory dependencies are built, which runs their build backend. Installing a wheel runs no package code. ↗
  • installScripts.allowList.setting: With no-build = true, the packages in no-binary-package are the only ones built from source ("Allow `all` to be overridden by specific binary exclusions"). Their wheels are not used, so they are always built. ↗
  • installScripts.allowList.file: Or uv.toml; the same table as exclude-newer. ↗
  • installScripts.allowList.availableSince: Project settings no-build, no-build-package, no-binary and no-binary-package; uv sync and related commands respect them since 0.4.6. ↗
  • installScripts.disableAll: Operations that need to build a source distribution fail. Workspace members, editable requirements and wheels built earlier and kept in the cache are still used. With uv 0.13.6 on 2026-10-30, uv sync refused a git dependency and a non-editable local directory dependency as well ("marked as --no-build but has no binary distribution"), so those need an exception too. An explicit no-build = false in a higher-priority file makes uv ignore no-build-package. ↗
  • project.lockfiles: Created next to pyproject.toml. ↗
  • project.workspaces: The [tool.uv.workspace] table of the root pyproject.toml lists members and exclude (globs or paths); exclude wins over members, and the root is a member too. ↗
  • project.workspacesObjectKey: The workspace guide calls members required, while the settings reference (crates/uv-workspace/src/pyproject.rs) gives it a default of []. ↗
  • user.files: User-level configuration is <config dir>/uv/uv.toml: $XDG_CONFIG_HOME/uv, else ~/.config/uv on Linux and macOS (not ~/Library), %APPDATA%\uv, else uv in the Roaming AppData known folder, on Windows (FilesystemOptions::user in crates/uv-settings/src/lib.rs). The directory comes from the etcetera crate (crates/uv-dirs/src/lib.rs), which uses XDG_CONFIG_HOME only when it is an absolute path. Keys sit at the top level, as in [tool.uv] without the prefix; "User- and system-level configuration files cannot use the pyproject.toml format" (docs/concepts/configuration-files.md). The system file (/etc/uv/uv.toml, %PROGRAMDATA%\uv\uv.toml) is merged below it. Same path code at 0.9.0, 0.9.16 and 0.13.6; earlier versions are not tracked. ↗
  • user.settings: Settings of uv.toml are merged with project-level configuration taking precedence over the user-level configuration: a project exclude-newer or no-build wins, exclude-newer-package tables are merged with the project keys winning, and lists such as no-build-package and no-binary-package are concatenated (crates/uv-settings/src/combine.rs). uv tool and uvx read only the user and system files, so the user file is the only file that gives them these settings; uv pip applies the top-level keys unless its [pip] table overrides them. The versions are those of the values depcurfew writes: a duration in exclude-newer since 0.9.17, package = false in exclude-newer-package since 0.9.25. no-build-package takes effect only while no-build is unset. ↗
  • user.unknownKeys: uv.toml is parsed with deny_unknown_fields (OptionsWire), and fields allowed only in pyproject.toml (workspace, sources, dev-dependencies, conflicts, managed, package and others) are rejected by validate_uv_toml (crates/uv-settings/src/lib.rs, Error::PyprojectOnlyField); both are errors of the user file (see invalidValueFails). ↗
  • user.invalidValueFails: FilesystemOptions::user() returns nothing only for a missing, not-a-directory or unreadable file; a TOML or schema error (Error::UvToml) is passed on, and crates/uv/src/lib.rs stops every command that reads configuration with it, unlike an invalid pyproject.toml, which is only warned about. So a value the installed uv does not know (a duration before 0.9.17, package = false before 0.9.25, exclude-newer = false before 0.11.24) breaks every uv command instead of being dropped. A required-version mismatch is reported before a schema error. ↗
  • user.weakening: Tables are merged with the project keys winning, lists are extended and scalars come from the project when it sets them (combine.rs); with no-build = false, NoBuild::from_args ignores the package list (crates/uv-configuration/src/build_options.rs). exclude-newer = false (since 0.11.24) turns off a value from a lower-priority source, the system file included. Read from the code, not run: a [pip] exclude-newer in the user file is combined above the top-level keys for uv pip, so it can override a project exclude-newer there, and a user [[index]] with exclude-newer = false (preview, 0.11.5) exempts the packages of that index. The [pip] table configures "just the uv pip command line interface", and its settings win over the top-level ones there ("many of the settings in this section have corollaries in the top-level namespace which do apply to the uv pip interface unless they are overridden by a value in the uv.pip section", docs/concepts/configuration-files.md); PipOptions has exclude-newer (false disables it), exclude-newer-package, no-build and no-binary (a list, :all: for every package), and the top level no-binary = true builds every package from source (settings.rs). [pip] no-build = false weakens nothing: PipSettings::combine passes it to NoBuild::from_pip_args, which gives NoBuild::None (or the [pip] only-binary list) for false, and combines that with the top-level no-build and no-build-package (NoBuild::combine: All wins, None gives the other side), so it cannot turn the top-level no-build or no-build-package off; a project [tool.uv.pip] no-build wins over the user value anyway (crates/uv-cli/src/settings.rs and crates/uv-configuration/src/build_options.rs at 0.13.6, the same in crates/uv/src/settings.rs at 0.9.17). ↗
  • user.variables: "Settings provided via environment variables take precedence over persistent configuration, and settings provided via the command line take precedence over both" (docs/concepts/configuration-files.md). UV_NO_BUILD_PACKAGE since 0.6.5, UV_NO_BINARY and UV_NO_BINARY_PACKAGE since 0.5.30 (lists separated by spaces), UV_NO_CONFIG since 0.2.30, UV_CONFIG_FILE since 0.1.34. UV_NO_BUILD, UV_NO_BINARY and UV_NO_CONFIG are flags parsed with the BoolishValueParser of clap (crates/uv-cli/src/lib.rs), whose true values are y, yes, t, true, on and 1 and false values n, no, f, false, off and 0, in any case (https://github.com/clap-rs/clap/blob/v4.6.7/clap_builder/src/util/str_to_bool.rs, the clap_builder version in the Cargo.lock of uv); a false value leaves the flag unset (flag() in crates/uv-cli/src/options.rs gives None), so the files decide (with UV_NO_BUILD=0 uv 0.11.32 still refused to build in a review test on 2026-10-31). XDG_CONFIG_HOME and APPDATA move the user directory (see files). ↗
  • extra.machineSettings: UV_DEFAULT_INDEX ("uv will use this index as the default index") and UV_INDEX_URL (the same, deprecated) replace PyPI; UV_INDEX ("this space-separated list of additional indexes", entries may be name=url), UV_EXTRA_INDEX_URL (space-separated, deprecated) and UV_FIND_LINKS ("this comma-separated list of additional locations") add places to install from; UV_CONFIG_FILE "Expects a path to a local uv.toml file to use as the configuration file", which "will be used in place of any discovered configuration files (e.g., user-level configuration will be ignored)" (docs/concepts/configuration-files.md at the same tag, which also says that variables win over configuration files and that the user uv.toml is merged under the project's, arrays concatenated). uv reads none of pip's variables or files (docs/pip/compatibility.md). ↗
  • extra.dockerImage: The distroless image is published as ghcr.io/astral-sh/uv:latest, :{major}.{minor}.{patch} and :{major}.{minor} ("the latest patch version"), and each derived image (uv on a base such as python3.12-bookworm-slim, alpine or debian) "is published with uv version tags as ghcr.io/astral-sh/uv:{major}.{minor}.{patch}-{base} and ghcr.io/astral-sh/uv:{major}.{minor}-{base}"; tags of a base alone (debian, alpine) and latest name no version. "Use one of the above images with uv pre-installed or install uv by copying the binary from the official distroless Docker image": COPY --from=ghcr.io/astral-sh/uv:0.13.6 /uv /uvx /bin/, which it calls best practice to pin. COPY --from takes an image, a build stage or a named context (frontend/dockerfile/docs/reference.md of moby/buildkit at c1cfdbd30b79b4a4908cdccc3c0f9849c30e34e5). ↗
  • extra.installedPackage: Besides the standalone installer, the installation page installs uv from PyPI with pipx install uv or pip install uv. So uv==<version> in such a command of a CI job or a Dockerfile is the uv the later commands run (decision D-173). ↗
  • extra.environmentNames: The options take their variables through clap (env = EnvVars::UV_PROJECT and the others), and clap_builder Arg::env reads the variable with env::var_os(name) (https://github.com/clap-rs/clap/blob/v4.6.7/clap_builder/src/builder/arg.rs, the clap_builder version in the Cargo.lock of uv), which outside Windows finds only that spelling, so uv_project sets nothing (decision D-143). ↗
  • extra.registrySettings: ResolverInstallerSchema: index ("The package indexes to use when resolving dependencies", [[tool.uv.index]] with name and url), index-url ("The URL of the Python package index (by default: <https://pypi.org/simple>)"), extra-index-url ("Extra URLs of package indexes to use, in addition to --index-url") and find-links ("Locations to search for candidate distributions, in addition to those found in the registry indexes"); PipOptions ([tool.uv.pip]) has index-url, extra-index-url and find-links too. uv.toml takes the same keys at its top level (extra.configTables). docs/concepts/indexes.md: "Indexes are prioritized in the order in which they're defined", the default index is "always treated as lowest priority", with the default first-index strategy uv "will stop at the first index on which a given package is available", default = true replaces PyPI ("set default = true on another index entry" to "exclude PyPI from the list of indexes"), so an entry without it adds an index that is asked before the default one, and an explicit = true index is used only for packages pinned to it in tool.uv.sources. Each [[index]] entry is read as entries says (decision D-120): explicit = true counts only for the packages tool.uv.sources pins to it by name, default = true replaces PyPI, any other entry adds an index (see INDEX_ENTRIES). ↗
  • extra.pylockCreatedBy: uv export --format pylock.toml (and uv pip compile to pylock.toml) writes created-by = "uv". The project itself and workspace members are written as directory = { path = …, editable = true }, with the path relative to the lock file, "." for the project. ↗
  • extra.configTables: Settings sit in [tool.uv] in pyproject.toml and at the top level of uv.toml. uv.toml cannot hold workspace, sources and a few other project fields. ↗
  • extra.pyprojectTable: A pyproject.toml without a [tool.uv] table is ignored when uv searches for configuration. ↗
  • extra.configPrecedence: A nested pyproject.toml with any [tool.uv] table hides the configuration of its parent directories. ↗
  • extra.configFileOrder: "configuration will be read from uv.toml, and the [tool.uv] section in the accompanying pyproject.toml will be ignored"; uv prints a warning listing the ignored fields. ↗
  • extra.workspaceRootOnly: "In workspaces, uv will begin its search at the workspace root, ignoring any configuration defined in workspace members." Project fields such as tool.uv.sources of a member still apply. ↗
  • extra.buildSwitch: The project setting that forbids building source distributions. It also stops git and local directory dependencies (uv sync with uv 0.13.6 on 2026-10-30) and source archives, which also need a build; workspace members and editable requirements are still built. ↗
  • extra.durationStrings: Either a "friendly" duration (24 hours, 1 week, 30 days) or an ISO 8601 duration (PT24H, P7D, P30D). ↗
  • extra.durationUnits: Units in the documented examples: 24 hours, 1 week, 30 days. ↗
  • extra.cutoffDates: FromStr of ExcludeNewerValue tries an RFC 3339 timestamp (jiff Timestamp, which needs an offset), then a date, which counts from the start of the next day in the system time zone (date.checked_add(1.day()) and to_zoned(TimeZone::system())), then a span. A timestamp or a date is a fixed cutoff: uv uses no file uploaded after it (docs/concepts/resolution.md, "Reproducible resolutions"), so it holds back more every day. ↗
  • extra.excludeWildcards: exclude-newer-package keys are exact package names. ↗
  • extra.excludeValue: exclude-newer-package = { name = false } exempts the package from the delay. ↗
  • extra.missingUploadTime: Unless the package is exempt, or the index has its own exclude-newer value or is exempt with [[tool.uv.index]] exclude-newer = false. ↗
  • extra.requiredVersion: A PEP 440 specifier; uv exits with an error when its version does not match. Also at the top level of uv.toml. ↗
  • extra.lockedSettings: uv.lock records these in [options] (a relative exclude-newer as exclude-newer-span); after a change uv lock --check and uv sync --locked fail until uv lock runs again ("Resolving despite existing lockfile due to addition of global exclude newer", seen with uv 0.13.6 on 2026-10-30). no-build and no-binary-package are not recorded. ↗
  • extra.lockOptions: write_options writes [options] when exclude-newer is set: an absolute value as exclude-newer = "<timestamp>"; a relative one as exclude-newer = the placeholder "0001-01-01T00:00:00Z" (with the comment "This has no effect and is included for backwards compatibility when using relative exclude-newer values") and exclude-newer-span = the span as jiff prints it, ISO 8601 (P3D, P1W); since 0.11.8 exclude-newer may be missing next to exclude-newer-span. [options.exclude-newer-package] holds name = "<timestamp>", name = { timestamp = <placeholder>, span = "P3D" } or name = false. The placeholder is ExcludeNewerValue::PLACEHOLDER in crates/uv-distribution-types/src/exclude_newer.rs. ↗
  • extra.lockComparison: ExcludeNewer::compare (lock against the settings, in crates/uv-lock-operations/src/validated_lock.rs after lock.filter_exclude_newer) resolves again on an added or removed global value, a span that differs (ExcludeNewerSpan compares self.0.fieldwise() == other.0.fieldwise() in crates/uv-distribution-types/src/exclude_newer.rs, so "7 days" and P1W differ), a span added to or removed from an absolute value, and an absolute timestamp that is earlier than the locked one (a later one does not count); only a new timestamp of the same span is ignored. Per package (only names of locked packages and names the lock already records, filter_exclude_newer in crates/uv-lock/src/lock/mod.rs): a cutoff removed, a disabled one enabled, an enabled one added, or a changed value; an enabled one that is now disabled does not count. A date without a time (2026-01-01) is the start of the next day in the system time zone, so the timestamp it gives depends on the machine. Messages such as "Resolving despite existing lockfile due to change of exclude newer span from `P3D` to `P1W`" come from the Display of ExcludeNewerValueChange. ↗
  • extra.spanSyntax: jiff 0.2.37 is the version in Cargo.lock of uv 0.13.6. uv parses a relative exclude-newer with jiff's Span (FromStr of ExcludeNewerValue tries a timestamp, then a date, then a span), which reads the friendly format ("3 days", "1w", "2 weeks, 3 days", with each unit at most once, larger units first, a leading sign or a trailing "ago") and ISO 8601 (P3D, PT36H). Span prints as ISO 8601 by default, which is what uv.lock records. uv rejects years and months ("use days instead", crates/uv-distribution-types/src/exclude_newer.rs). The friendly format also has HH:MM:SS and fractions of hours and smaller units, which depcurfew does not read. ↗
  • extra.commandLine: clap arguments of uv add, uv pip install, uv tool install, uv run and uv tool run (uvx), with the global options, IndexArgs, ResolverInstallerArgs, BuildOptionsArgs and DependencyConstraintsArgs they share. --opt value, --opt=value, -o value and -ovalue all work; long options cannot be shortened. Options of uv run, uv tool run and uvx come before the command. --with, --with-editable and --with-executables-from add packages, as a list split at commas outside [...] that are not followed by !, =, <, > or ~ (comma.rs). uvx and uv tool run take the package from the first argument (name@version is ==version, name@latest the newest) unless --from names it; a first argument such as python, python3.12, pypy@3.8 or graalpy runs an interpreter (PythonRequest::try_from_tool_name in uv-python-types, implementation names cpython, pypy, graalpy and pyodide). uv run runs a command and downloads only what --with names, or a script given as an http or https URL. -e takes a path in uv pip install but is a flag in uv tool install, and --editable a flag in uv add; --no-binary and --only-binary take values in uv pip install only, -m is --marker in uv add and --module in uv run. ↗
  • extra.registryOverrides: IndexArgs (lib.rs): --index adds an index (name=url allowed), --default-index replaces PyPI, --index-url and --extra-index-url are their deprecated forms, --find-links adds a page or directory of archives; each has the variable named here. --config-file and UV_CONFIG_FILE name a uv.toml that may set any index. uv does not read pip.conf or PIP_INDEX_URL (docs/pip/compatibility.md). ↗
  • extra.selection: VersionSelectionArgs: --prerelease takes disallow, allow, if-necessary, explicit or if-necessary-or-explicit (UV_PRERELEASE); allow considers pre-releases of every package and disallow none (docs/concepts/resolution.md); --prerelease-package takes PACKAGE=MODE; the hidden --pre means allow. BuildOptionsArgs of uv add, uv run, uv tool install and uv tool run (uvx): --no-binary (UV_NO_BINARY, a boolean) installs every package from source, --binary turns it off, --no-binary-package names one package (UV_NO_BINARY_PACKAGE, separated by spaces). uv pip install takes --no-binary and --only-binary as lists separated by commas with :all: and :none:, as pip does (PipInstallArgs). ↗
  • extra.latestVersion: Released on 2026-10-26. ↗
  • extra.directoryOptions: GlobalArgs (global = true, so before or after the subcommand): --directory "Change to the given directory prior to running the command. Relative paths are resolved with the given directory as the base", env UV_WORKING_DIR; --project "Discover a project in the given directory. All pyproject.toml, uv.toml, and .python-version files will be discovered by walking up the directory tree from the project root … Other command-line arguments (such as relative paths) will be resolved relative to the current working directory … This setting has no effect when used in the uv pip interface", env UV_PROJECT. crates/uv-static/src/env_vars.rs: UV_WORKING_DIR is "Equivalent to the --directory command-line argument. UV_WORKING_DIRECTORY (added in v0.9.1) is also supported for backwards compatibility", UV_PROJECT "Equivalent to the --project command-line argument". ↗
  • extra.installOverrides: ExcludeNewerArgs: #[arg(long, env = EnvVars::UV_EXCLUDE_NEWER)] exclude_newer accepts RFC 3339 timestamps, local dates, friendly and ISO 8601 durations, and false to disable it; PackageExcludeNewerArgs adds --exclude-newer-package PACKAGE=DATE and is flattened into ResolverArgs, InstallerArgs and ResolverInstallerArgs. A date is not compared with the policy, so it is asked about. ↗
  • extra.pipTable: For uv pip commands, PipSettings::combine merges the [pip] table of a configuration file above its top-level keys ("Merge the top-level options (`tool.uv`) with the pip-specific options (`tool.uv.pip`), preferring the latter"): [pip] exclude-newer replaces the top-level value (false turns the delay off), [pip] exclude-newer-package entries win over top-level entries for the same package, and [pip] no-binary (package names, or :all:) is added to the top-level no-binary-package (NoBinary::combine in crates/uv-configuration/src/build_options.rs). [pip] no-build and only-binary are joined with the top-level no-build, so they cannot turn it off. Commands outside uv pip ignore [pip] ("These values will be ignored when running commands outside the `uv pip` namespace", PipOptions in crates/uv-settings/src/settings.rs). keys maps each top-level key depcurfew writes to the [pip] key that overrides or extends it. The same code in 0.11.32 (crates/uv/src/settings.rs). ↗

pip

  • cooldown.setting: Only files uploaded before the given time are considered; applies to packages from remote indexes, not to local files, find-links directories or VCS requirements. Isolated build environments get the same cutoff. ↗
  • cooldown.configFiles: pip reads no configuration from the project: only the global, user and site (virtual environment) pip.conf, the file named by PIP_CONFIG_FILE and PIP_* environment variables. --uploaded-prior-to is not allowed in requirements files, so a project sets it through PIP_UPLOADED_PRIOR_TO or the command line, e.g. in CI. ↗
  • cooldown.cliFlag: pip install, download, wheel, lock, index and list; environment variable PIP_UPLOADED_PRIOR_TO. ↗
  • cooldown.unit: A duration is written PnD, a whole number of days (P3D, matched by ^P(\d+)D$); P1W, PT24H and "7 days" are rejected. An ISO 8601 date or time is a fixed cutoff instead. A day is always 24 hours. ↗
  • cooldown.availableSince: pip 26.1 accepts a duration in days ("P3D for 3 days ago"); the option itself exists since 26.0 with dates only. ↗
  • cooldown.default: Off unless given. ↗
  • installScripts.defaultPolicy: pip builds a source distribution when no wheel fits, which runs its build backend; the secure-installs guide recommends --only-binary :all:. Installing a wheel runs no package code. ↗
  • installScripts.allowList.setting: After --only-binary=:all:, a package named in --no-binary may only be installed from source: a name wins over :all:, so its wheels are not used. --only-binary=:all: given after it clears the exception. ↗
  • installScripts.allowList.file: --only-binary and --no-binary are among the options a requirements file may contain. ↗
  • installScripts.allowList.format: Each use adds to the set; :all: and :none: are special values. ↗
  • installScripts.disableAll: Allowed in requirements files and pip.conf (only-binary). Enforced only for packages from indexes and find-links: VCS, local directory and direct URL source requirements are still built. ↗
  • project.lockfiles: pip lock (experimental since 25.1) writes pylock.toml; pip install -r pylock.toml is experimental since 26.1. The specification also allows pylock.<name>.toml (extra.lockfilePattern). ↗
  • project.manifests: "requirements.txt is usually what these files are named (although, that is not a requirement)"; the format is meant only for pip. ↗
  • user.files: The user file is pip.conf (pip.ini on Windows) in appdirs.user_config_dir("pip") (configuration.py), written in INI with [global] and per-command sections. Linux: $HOME/.config/pip/pip.conf, "which respects the XDG_CONFIG_HOME environment variable" (used when it is not empty after stripping spaces, vendored platformdirs _xdg.py). A relative XDG_CONFIG_HOME is used as it is, so pip reads <value>/pip/pip.conf relative to the directory each command runs in: XDGMixin.user_config_dir in src/pip/_vendor/platformdirs/_xdg.py at 26.2.2 returns the stripped value with no absolute-path check, _append_app_name_and_version (api.py) only joins the app name, and utils/appdirs.py and configuration.py (os.path.join, then os.path.exists and parser.read) make nothing absolute; 26.1.1 (platformdirs 4.5.1, Unix.user_config_dir in unix.py) does the same without stripping the value. From 26.3 ("Upgrade platformdirs to 4.12.4", NEWS.rst at 26.3) _xdg_dir in src/pip/_vendor/platformdirs/_xdg.py returns the stripped value only when posixpath.isabs, so a relative XDG_CONFIG_HOME is ignored and pip reads ~/.config/pip/pip.conf. macOS: ~/Library/Application Support/pip when that directory exists, else ~/.config/pip, where XDG_CONFIG_HOME is not used (utils/appdirs.py: _macos_user_config_dir takes platformdirs user_data_dir when os.path.isdir); since 26.2 that user_data_dir is $XDG_DATA_HOME/pip when XDG_DATA_HOME is not empty after stripping spaces, so with XDG_DATA_HOME set the Library directory is skipped and ~/.config/pip is used unless $XDG_DATA_HOME/pip exists (XDGMixin in src/pip/_vendor/platformdirs/_xdg.py at 26.2.2; src/pip/_vendor/vendor.txt names platformdirs 4.10.0 in 26.2 and 4.5.1 in 26.1.1, whose macos.py has no XDG handling); from 26.3 only an absolute XDG_DATA_HOME counts, so a relative one leaves the Library directory in use (XDGMixin.user_data_dir with _xdg_dir at 26.3). Windows: %APPDATA%\pip\pip.ini; platformdirs asks Windows for the Roaming AppData known folder, which APPDATA normally names. The legacy ~/.pip/pip.conf (%HOME%\pip\pip.ini) is loaded as well, below this file. Same path code in 25.0; earlier versions are not tracked. A command reads [global] and the section named after itself, which wins key by key (override_order ["global", self.name, ":env:"] in cli/parser.py); the options doctor --user checks (index_group and package_selection_group in cli/cmdoptions.py) belong to install, download, wheel, lock, index and list (src/pip/_internal/commands at 26.2.2). Keys are read without regard to case, with underscores as dashes and without a leading -- (_normalize_name in src/pip/_internal/configuration.py at 26.2.2 and 26.3: name.lower().replace("_", "-") and removeprefix("--"), the same in 25.0), so only_binary and --only-binary in a file are the setting only-binary. pip parses each file with configparser.RawConfigParser, whose strict mode (strict=True by default, Lib/configparser.py of CPython 3.9 to 3.14) raises DuplicateSectionError for a section given twice and DuplicateOptionError for a key given twice in one section; pip turns that into ConfigurationFileCouldNotBeLoaded and stops (_construct_parser). Before 26.3 the parser compares keys in lower case only (the default optionxform), so only_binary next to only-binary in one section is read as one setting and the later line wins (_normalized_keys); from 26.3 the parser normalizes the names itself (_RawConfigParser.optionxform calls _normalize_name), so such a file stops pip. ↗
  • user.settings: depcurfew writes them in [global], which reaches every command that has the option (install, download, wheel, lock, index, list) and the resolver of pipenv lock; [install] reaches only pip install. "Accept --no-binary and --only-binary via pip.conf" (7.1.0); uploaded-prior-to is read from pip.conf like every long option ("To override a duration set in configuration, pass P0D on the command line", user_guide.rst). 26.1.0 because depcurfew writes a PnD duration: pip 26.0 takes dates only and aborts on P7D, and 25.x ignores the key. uv does not read pip.conf. ↗
  • user.unknownKeys: "Ignore options not present in this parser": a key that is not an option of the command is skipped without a word (same code in 25.0), so pip before 26.0 ignores uploaded-prior-to. ↗
  • user.invalidValueFails: A pip.conf that is not valid INI stops pip (ConfigurationFileCouldNotBeLoaded, configuration.py), and a value an option rejects ends the command with a usage error: pip 26.0 aborts on uploaded-prior-to = P7D in every command that has the option, as it rejected PIP_UPLOADED_PRIOR_TO=P100000D in a test on 2026-10-30 (configuration values and PIP_* variables go through the same parsing). Commands without the option ignore the key. ↗
  • user.weakening: In any section of any pip.conf: [install] beats [global], and a later file (a virtual environment pip.conf, PIP_CONFIG_FILE) beats the user file per key, an empty value removing it (cli/parser.py). :all: in one of the lists clears the other and :none: clears its own (handle_mutual_excludes). P0D overrides a configured duration, and "Local package files are allowed regardless of the --uploaded-prior-to setting", find-links directories included (user_guide.rst). A requirements file can also pass --no-binary or --only-binary, but not --uploaded-prior-to. ↗
  • user.variables: "Note that if a file exists at the location that this is set to, the user config file will not be loaded." PIP_<NAME> variables are applied after the [global] and command sections of all files, and the command line beats them (cli/parser.py, override_order). --isolated, a flag, ignores environment variables and user configuration. XDG_CONFIG_HOME (Linux) and XDG_DATA_HOME (macOS, 26.2) move the user directory, from 26.3 only when they are absolute paths (see files). ↗
  • extra.machineSettings: iter_config_files: the global files, then the user files unless PIP_CONFIG_FILE names a file that exists ("per-user config is not loaded when env_config_file exists"), the legacy ~/.pip/pip.conf (~/pip/pip.ini on Windows, get_configuration_files) before the user file of user.files, the site file of the environment, and the file PIP_CONFIG_FILE names; each is read with configparser.RawConfigParser (= or : between key and value, full-line comments with # or ;, indented lines continue a value, keys in lower case) and _normalize_name writes _ as -. ConfigOptionParser (src/pip/_internal/cli/parser.py) takes the sections global, the name of the command (install for pip install) and :env: (the PIP_ variables, which win), matches a key to the long option of that name, so pypi-url sets --index-url too (-i, --index-url and --pypi-url are one option in cli/cmdoptions.py), and splits the value of an append option (--extra-index-url, --find-links) at whitespace. --index-url replaces the index, --extra-index-url adds indexes and --find-links adds pages or directories of archives (cmdoptions.py). ↗
  • extra.environmentNames: get_environ_vars takes the variables of os.environ whose names start with PIP_ (key.startswith("PIP_"), the prefix in upper case) and lowercases the rest (key[4:].lower()), so PIP_index_url sets index-url and pip_index_url sets nothing (decision D-143). ↗
  • extra.configCommand: pip config: "Manage local and global configuration"; "set: Set the command.option=value", "unset: Unset the value associated with command.option", "edit: Edit the configuration file in an editor". Without --user, --global or --site it changes the configuration file of the active virtual environment when that file exists, otherwise the user file. So a CI step or RUN with pip config set can give the later pip installs a release-age delay that no environment variable shows (decision D-115). ↗
  • extra.configSectionNames: pip reads pip.conf with configparser.RawConfigParser (_construct_parser in src/pip/_internal/configuration.py at 26.2.2). configparser takes the name of a section from the header as written between [ and ] (SECTCRE, group "header", not stripped or lowercased; the same in Lib/configparser.py at v3.9.0 and v3.13.0), and pip keeps the keys of a section under that name (_normalized_keys: section + "." + key) and uses only the sections named exactly "global", the command and ":env:" (section in override_order in src/pip/_internal/cli/parser.py). So [Global] and [ global ] are other sections, which pip ignores. ↗
  • extra.configSections: "Each subcommand can be configured optionally in its own section. This overrides the global setting with the same name", and "A command specific section in the config file `[<command>] host = bar` overrides the option with same name in the `[global]` config file section" (Precedence / Override order). pip reads only [global], the section of the running command and :env: (override_order = ["global", self.name, ":env:"] in cli/parser.py), so a managed key in [install] wins over [global] for pip install; depcurfew comments such keys out in every section other than [global]. ↗
  • extra.pylockCreatedBy: pip lock writes created-by = "pip". ↗
  • extra.requirementsOptions: SUPPORTED_OPTIONS in pip 26.2.2 (--pypi-url is a second name of --index-url in cmdoptions.py); per requirement also --hash and -C/--config-settings (extra.requirementsParser). Any other option, --uploaded-prior-to included, makes the file fail to parse. ↗
  • extra.requirementsParser: build_parser reads each line with optparse.OptionParser(add_help_option=False) holding SUPPORTED_OPTIONS and SUPPORTED_OPTIONS_REQ (--hash, -C/--config-settings), with the names from cmdoptions.py in pip 26.2.2. optparse takes a long option shortened to a prefix that names exactly one of them (_match_abbrev; an exact name wins), so --no-bin :all: is --no-binary :all:, and an ambiguous prefix such as --no is an error. --hash and --config-settings belong to the requirement on their line; on a line of their own they are accepted and ignored. ↗
  • extra.formatControl: One FormatControl holds no_binary and only_binary for the whole install. handle_mutual_excludes splits a value at commas: :all: clears both sets and puts :all: in its own, :none: clears its own set, and a name moves from the other set into its own; get_allowed_formats checks the name in only_binary, then in no_binary, then :all: in only_binary, then in no_binary. So after --only-binary=:all:, --no-binary <name> builds that package from source and --no-binary=:all: or --only-binary=:none: (or :none: after the last :all: of its value) builds every package again. req_file.py parses every line, requirement lines too, with the options of SUPPORTED_OPTIONS into the finder's FormatControl (get_line_parser: defaults.format_control = finder.format_control; break_args_options passes what follows the requirement to the option parser), in the order of the lines, with the lines of an included -r or -c file at the line that includes it (RequirementsFileParser._parse_and_recurse). ↗
  • extra.configFileNames: CONFIG_BASENAME is pip.ini on Windows and pip.conf elsewhere; pip looks for it only in the global, user and site locations, never in the project. ↗
  • extra.configFileVariable: Names a configuration file pip loads last; set to os.devnull it turns all configuration files off. ↗
  • extra.environmentVariable: Every long option has a PIP_<UPPER_LONG_NAME> variable with dashes replaced by underscores. Tested on 2026-10-30: pip 25.3 ignored PIP_UPLOADED_PRIOR_TO=P100000D without a word, 26.0 rejected the duration (dates only), 26.1 and 26.2.2 found no version. ↗
  • extra.durationStrings: Only whole days, written PnD, are accepted. ↗
  • extra.missingUploadTime: Upload times exist only in the JSON form of the simple repository API (PEP 700); indexes that serve only HTML have none. ↗
  • extra.lockfileFormat: Each [[packages]] entry has exactly one of vcs (always built), directory (always built), archive (a source tree or wheel at a URL or path) or sdist and wheels from an index. A package with an sdist and no wheels is built when installed. A relative directory path is relative to the lock file. The required top-level created-by records the name of the tool that wrote the file, preferably its normalized Python package name. ↗
  • extra.requirementsFormat: VCS requirements start with git+, hg+, svn+ or bzr+, alone or after "name @"; a direct reference is "name @ URL" (PEP 508); -e installs a project path or VCS URL in editable mode. The legacy #egg= fragment names the project of a VCS URL. Lines ending with a backslash continue on the next line, and # starts a comment (requirements-file-format.md). ↗
  • extra.requirementsIncludes: Option names from cli/cmdoptions.py. A relative path is relative to the directory of the file that includes it, and a file given as an http, https or file URL is downloaded (req_file.py, _parse_and_recurse); a file that includes itself is an error. ↗
  • extra.requirementsPaths: A requirement that contains a path separator (/, and \ on Windows) or starts with . looks like a path (_looks_like_path): a directory there is a project built from source. A name with an archive extension (utils/filetypes.py) is a local archive, even when the file does not exist. http, https, ftp and file URLs are links (utils/urls.py, is_url). ↗
  • extra.lockfilePattern: A named lock file, next to or instead of pylock.toml; pip lock -o writes any name. ↗
  • extra.commandLine: pip and pip3 are the console scripts of the package (pyproject.toml). The options of pip install (install.py) and the general options of every command (cmdoptions.py, general_group), which may also come before install. pip reads them with optparse: --opt value and --opt=value, -rFILE and -r FILE, grouped short flags, and a long option shortened to any prefix that names one option (cli/parser.py keeps optparse's matching), so --extra means --extra-index-url. -e takes a local project path or a VCS URL to install in editable mode. -r, -c, --requirements-from-script and --group read requirements from files of the project. ↗
  • extra.registryOverrides: index_group: --index-url (alias -i, --pypi-url) is the base URL of the package index, --extra-index-url adds indexes, --find-links (-f) adds an HTML page or a directory of archives. Every long option can be set as PIP_<UPPER_LONG_NAME>, dashes replaced by underscores (docs/html/topics/configuration.md); PIP_CONFIG_FILE names a configuration file loaded last, which may set any index. Requirements files may set --index-url, --extra-index-url and --find-links too (req/req_file.py). ↗
  • extra.selection: --pre includes pre-release and development versions (pip only finds stable versions by default) and stands for --all-releases :all:; --all-releases and --only-final take :all:, :none: or package names separated by commas and allow or forbid pre-releases of those packages (models/release_control.py, allows_prereleases: a named package first, then :all:). --no-binary and --only-binary take the same lists: --no-binary keeps pip from using wheels, so the package is built from source, --only-binary from using source distributions (models/format_control.py, handle_mutual_excludes and get_allowed_formats). Each long option can also be set as PIP_<NAME> (docs/html/topics/configuration.md), which the command line overrides. ↗
  • extra.pipxSelection: pipx forwards the standard PIP_* variables to pip (except PIP_USER, PIP_DISABLE_PIP_VERSION_CHECK, PIP_TARGET and PIP_KEYRING_PROVIDER); the uv backend ignores them (docs/how-to/use-private-index.rst). pipx has no option of its own for pre-releases or source builds; --pip-args may carry them. ↗
  • extra.pipxCommandLine: pipx installs applications from PyPI with pip (or uv) in environments of their own. pipx install takes one or more package specs, a VCS URL, a local path or archive, or a script (--preinstall adds packages to the environment; -f is --force, not find-links). pipx run takes the app first (argparse REMAINDER, so its options come before it), --spec names the package to install and run, --with adds packages; a first argument ending in .py is a local script, or a script to download when it is a URL (docs/how-to/run-scripts.rst). argparse accepts abbreviated long options. pipx inject ENVIRONMENT takes the packages to install into an existing environment as further operands (any spec pip installs, installed as pipx install installs them, commands/inject.py) and with -r/--requirement a file of them, one per line; --include-apps and --with-suffix are flags. pipx runpip ENVIRONMENT takes every later word (argparse REMAINDER) as the arguments of pip in that environment, python -m pip under the pip backend and uv pip under the uv backend (backends/pip.py and backends/uv.py, run_raw_pip), and splits a lone argument that holds whitespace with shlex.split (_split_runpip_args). pipx install-all installs the environments of a spec metadata file that pipx list writes (commands/install.py, install_all), and pipx manifest sync the tools of a tool manifest (commands/manifest.py, sync_manifest). The same main.py as in 1.18.10. ↗
  • extra.pipxRegistryOverrides: --index-url is the base URL of the index; --pip-args is split and handed to pip, so it may carry --extra-index-url, --find-links or --no-index. With the pip backend pipx passes the PIP_* variables on to pip; with the uv backend it ignores them and uv reads its own (docs/how-to/use-uv-backend.rst); both kinds are registry variables of pip and uv. ↗
  • extra.latestVersion: Released on 2026-10-20. ↗
  • extra.configCommands: pip config list, edit, get, set, unset and debug: set and unset change a value and save the file, edit opens it in an editor, list, get and debug only read. Without --user, --global or --site the site file is used if one exists, else the user file. ↗
  • extra.installOverrides: --uploaded-prior-to (metavar datetime_or_duration): "Only consider packages uploaded prior to the given value", an ISO 8601 datetime or a duration of whole days P<n>D. PIP_UPLOADED_PRIOR_TO is its environment variable (environmentVariable). A datetime is not compared with the policy, so it is asked about. ↗

Poetry

  • cooldown.setting: A version is ignored while any of its files was uploaded less than the given number of days ago. Applies when dependencies are resolved (poetry lock, add, update); poetry install installs the locked versions without checking. ↗
  • cooldown.configFiles: The local configuration next to pyproject.toml (poetry config --local), not pyproject.toml itself. Environment variables (POETRY_SOLVER_MIN_RELEASE_AGE) win over poetry.toml, which wins over the user config.toml. ↗
  • cooldown.unit: An integer; 0 (the default) turns it off. ↗
  • cooldown.availableSince: "Introduced in 2.4.0"; announced as dependency cooldowns. Tested on 2026-10-30: Poetry 2.3.4 locked with min-release-age = 100000 in poetry.toml without a word, while 2.4.0 and 2.5.1 found no version. ↗
  • cooldown.default: Default 0: all versions are considered. ↗
  • installScripts.defaultPolicy: Without installer.only-binary, packages are built from source distributions when no wheel fits, which runs their build backend. Git and directory dependencies are always built. Installing a wheel runs no package code. ↗
  • installScripts.allowList.setting: With installer.only-binary = [":all:"], the packages named in installer.no-binary are the only ones built from source; explicit names take precedence over :all: since 2.2.0. Their wheels are rejected, so they are always built. ↗
  • installScripts.allowList.file: The docs recommend configuring it with --local for a project. ↗
  • installScripts.allowList.availableSince: "explicit package names will take precedence over :all:" (#10278). Before 2.2.0 a package listed in both settings has no file left to install. ↗
  • installScripts.allowList.format: poetry config stores the value as a list; written by hand, a boolean is not normalized. ↗
  • installScripts.disableAll: Since 2.0.0; the value [":all:"] forbids source distributions for every package. Applied only when installing: resolving dependencies may still build source distributions without static metadata, and git, path and url dependencies are built regardless. ↗
  • project.lockfiles: Next to pyproject.toml. ↗
  • user.files: "Linux: $XDG_CONFIG_HOME/pypoetry or ~/.config/pypoetry - Windows: %APPDATA%\pypoetry - macOS: ~/Library/Application Support/pypoetry". The code agrees on Linux and Windows: CONFIG_DIR = POETRY_CONFIG_DIR or user_config_path("pypoetry", appauthor=False, roaming=True) from platformdirs, without an override (src/poetry/locations.py; on Windows platformdirs asks for the Roaming AppData known folder, which APPDATA normally names). On macOS the directory depends on the installed platformdirs (libraryDirectories); the docs' directory is used when its version cannot be read. config.toml holds the settings as nested tables ([solver] min-release-age = 7); auth.toml next to it holds credentials. POETRY_CONFIG_DIR replaces the directory. Checked at 2.4.0 and 2.5.1; 2.0.0 removed the special handling of the platformdirs 2 macOS directory (#8916, CHANGELOG.md), and older versions are not tracked. ↗
  • user.libraryDirectories: Poetry 2.5.1 allows platformdirs >=3.0.0,<5 (pyproject.toml; its own lock has 4.11.8), and the official installer runs pip install without constraints in Poetry's virtual environment (python-poetry/install.python-poetry.org, install-poetry.py), so a new install gets the latest 4.x. The macOS user_config_dir by platformdirs version, read from the code at the tags: before 4.6.0 always ~/Library/Application Support/<app> (4.5.1 macos.py has no XDG support); 4.6.0 "Honor XDG environment variables on macOS" (#375): a non-empty XDG_CONFIG_HOME wins, a relative one too (os.environ.get("XDG_CONFIG_HOME", "").strip() in _xdg.py), and otherwise the config directory is user_data_dir, so a non-empty XDG_DATA_HOME gives $XDG_DATA_HOME/<app>; 4.9.6 "Fix macOS XDG variables leaking across user_config_dir, user_data_dir, and user_state_dir" (#473; 4.9.4 still returns user_data_dir); 4.11.8 "Ignore relative paths in XDG Base Directory environment variables and use the existing platform fallback" (#540, _xdg_dir with posixpath.isabs); the same in 4.14.2. A relative value is used as it is, so the tool reads it from the directory each command runs in. ↗
  • user.settings: Every setting of Config.default_config is read from the user config.toml ("As with all configurations described here, this is a user specific configuration", docs/configuration.md); dotted names are nested tables. A project poetry.toml replaces a user value, lists included (merge_dicts in src/poetry/utils/helpers.py), and POETRY_* variables beat both. Names in installer.no-binary win over installer.only-binary = :all: only since 2.2.0. solver.min-release-age-exclude is written as a TOML array (see extra.excludeFormat). ↗
  • user.weakening: Precedence: environment variables, then the local poetry.toml, then the global config.toml, then the default; a poetry.toml key replaces the user value, lists included. solver.min-release-age-exclude-source (2.4.0) takes source names from pyproject.toml or URLs. A source that gives no upload times is not filtered at all. ↗
  • user.variables: Any setting can be set as POETRY_ plus its name in capitals with dots and dashes replaced by underscores, and environment variables come first in the precedence ("Configuration sources"). POETRY_CONFIG_DIR replaces the platform directory (src/poetry/locations.py). ↗
  • extra.environmentNames: Config.get builds the name "POETRY_" + the keys of the setting in upper case with _ for - and reads it with os.getenv(env), and _get_environment_repositories matches POETRY_REPOSITORIES_(?P<name>[A-Z_]+)_URL, so only the names in upper case count (decision D-143). ↗
  • extra.installedPackage: The installation page installs a given version with "pipx install poetry==1.8.4", in CI with "$POETRY_HOME/bin/pip install poetry==2.0.0", and manually with pip in a virtual environment ("$VENV_PATH/bin/pip install poetry"). So poetry==<version> in such a command of a CI job or a Dockerfile is the Poetry the later commands run (decision D-115). ↗
  • extra.pylockCreatedBy: Poetry exports pylock.toml with its export plugin (poetry export --format pylock.toml), which writes created-by = "poetry-plugin-export". ↗
  • extra.configTable: poetry config writes dotted settings as nested tables, e.g. [solver] min-release-age = 7. ↗
  • extra.pyprojectTable: A [tool.poetry] table marks a Poetry project; Poetry also accepts a [project] table with a static name and version, which other tools use as well. ↗
  • extra.buildSwitch: installer.only-binary was added in 2.0.0; [":all:"] forbids source distributions of index packages when installing. Git and directory dependencies, and source archives from a URL or path, are built regardless (src/poetry/installation/executor.py at 2.5.1). ↗
  • extra.excludeWildcards: Package names only. ↗
  • extra.requiredVersion: A version constraint in pyproject.toml; a Poetry version outside it raises an error. Poetry 1.x does not know the key. ↗
  • extra.commandLine: poetry add takes package specs: a name, name@constraint, a PEP 508 requirement, a git URL, a path or an archive URL. Options with a value: --group (-G), --extras (-E), --optional, --python, --platform, --markers and --source of add, and the global --directory (-C) and --project (-P); -e/--editable, -D/--dev, --allow-prereleases, --dry-run and --lock are flags (src/poetry/console/commands/add.py). cleo reads -Gdocs and -G docs; long options cannot be shortened. poetry install takes no package specs. ↗
  • extra.registryOverrides: --source names a package source of [[tool.poetry.source]] in pyproject.toml (or pypi) to take the package from. The POETRY_REPOSITORIES_<NAME>_URL variables are for publishing only; no variable sets a package source. ↗
  • extra.versionConstraints: poetry add name@constraint takes any constraint valid in pyproject.toml, and name@latest the newest release; extras go before the @ (name[extra]@^4.0.0). ^ keeps the left-most non-zero part of major.minor.patch: ^1.2.3 is >=1.2.3 <2.0.0, ^1.2 is >=1.2.0 <2.0.0, ^1 is >=1.0.0 <2.0.0, ^0.2.3 is >=0.2.3 <0.3.0, ^0.0.3 is >=0.0.3 <0.0.4, ^0.0 is >=0.0.0 <0.1.0, ^0 is >=0.0.0 <1.0.0. ~ allows patch changes, or minor changes when only a major version is given: ~1.2.3 is >=1.2.3 <1.3.0, ~1.2 is >=1.2.0 <1.3.0, ~1 is >=1.0.0 <2.0.0. * is any version, 1.* is >=1.0.0 <2.0.0, 1.2.* is >=1.2.0 <1.3.0. ~=, inequalities and == as in PEP 440, several separated by commas; a bare version (1.2.3) is that version only. Poetry prefers stable releases and takes a pre-release only when no stable release satisfies the constraint. ↗
  • extra.selection: installer.no-binary (POETRY_INSTALLER_NO_BINARY) disallows wheels for :all: or true, none for :none: or false, or the named packages separated by commas; installer.only-binary (POETRY_INSTALLER_ONLY_BINARY, since 2.0.0) takes the same values; explicit package names win over :all:. poetry add --allow-prereleases accepts pre-releases (src/poetry/console/commands/add.py). ↗
  • extra.latestVersion: Released on 2026-09-20. ↗
  • extra.directoryOptions: Global options: --directory=DIRECTORY (-C) "The working directory for the Poetry command (defaults to the current working directory). All command-line arguments will be resolved relative to the given directory."; --project=PROJECT (-P) "Specify another path as the project root. All command-line arguments will be resolved relative to the current working directory or directory specified using --directory option if used." The page names no environment variable for either. ↗
  • extra.registrySettings: [[tool.poetry.source]] has name, url and priority. "If priority is undefined, the source is considered a primary source"; "All primary package sources are searched for each dependency without a source constraint" and "If you configure at least one primary source, the implicit PyPI source is disabled", so a primary source replaces PyPI. Supplemental sources "are only searched if no other (higher-priority) source yields a compatible package distribution": depcurfew does not know whether PyPI has a version the constraint takes, so such a source counts as one that adds. Explicit sources "are only searched when a package configuration explicitly indicates" them: a dependency with source = "name" in [tool.poetry.dependencies] or [tool.poetry.group.<group>.dependencies], also in a list of constraint tables (docs/dependency-specification.md, docs/managing-dependencies.md). create_pool in src/poetry/factory.py reads Priority[source.get("priority", "primary").upper()], so the value is compared without regard to case; the schema (src/poetry/json/schemas/poetry.json) allows primary, supplemental and explicit, and another value (default or secondary of Poetry 1.x) fails in 2.5.1 and counts as primary here. A source whose name is pypi in any case is PyPI itself (PyPiRepository), which "cannot be configured with a custom url" (create_package_source). ↗
  • extra.configCommands: poetry config [options] [setting-key] [setting-value1] ... [setting-valueN] sets a key to a value (--local in poetry.toml of the project); --unset removes the key, --migrate migrates outdated settings and --list only shows them. "The source namespace groups subcommands to manage repository sources for a Poetry project": source add adds a source to pyproject.toml (also the priority of PyPI, with --priority), source remove removes one from it, and source show only shows them (docs/cli.md; src/poetry/console/commands/source/add.py and remove.py write pyproject.poetry_config["source"], and src/poetry/console/application.py lists source add, source remove and source show). The sources of pyproject.toml are where poetry add and poetry install take packages from (registrySettings). ↗
  • extra.installOverrides: Settings can be set with environment variables prefixed by POETRY_, the upper-case setting name with dots and dashes replaced by underscores; solver.min-release-age (int, days) is POETRY_SOLVER_MIN_RELEASE_AGE. poetry add has no option for it. ↗

PDM

  • cooldown.setting: In the [tool.pdm.resolution] table of pyproject.toml: distributions uploaded after the cutoff are left out when dependencies are resolved (pdm lock, add, update). The --exclude-newer option of pdm lock wins over it, and it wins over strategy.exclude-newer in the PDM configuration. ↗
  • cooldown.configFiles: The [tool.pdm.resolution] table. ↗
  • cooldown.cliFlag: pdm lock --exclude-newer, since 2.13.0. ↗
  • cooldown.unit: An RFC 3339 timestamp, a UTC date or a relative duration N{d|h|w} such as 7d, 12h or 3w, counted from the current UTC time. ↗
  • cooldown.availableSince: "Support exclude-newer in pyproject.toml in the [tool.pdm.resolution] table" (#3776); the pdm lock option exists since 2.13.0. ↗
  • cooldown.default: No default: without a value every upload time is accepted. ↗
  • cooldown.exclude.setting: A table [tool.pdm.resolution.exclude-newer-override] of package = false (no cutoff) or package = another date or duration; package-specific values win over the global cutoff. ↗
  • cooldown.exclude.availableSince: "Allow package-specific overrides for exclude-newer resolution limits" (#3809). ↗
  • installScripts.defaultPolicy: Without only-binary, PDM locks and installs source distributions when they fit, which builds them and runs their build backend. Installing a wheel runs no package code. ↗
  • installScripts.allowList.setting: The packages in no-binary are locked and installed from source distributions only. A name in no-binary wins over only-binary = ":all:" (FormatControl of unearth, which PDM uses), so with both the named packages are the only ones built, and always from source. ↗
  • installScripts.allowList.file: The [tool.pdm.resolution] table. ↗
  • installScripts.allowList.availableSince: no-binary, only-binary and prefer-binary keys in [tool.pdm.resolution] (#2656). ↗
  • installScripts.disableAll: only-binary = ":all:" locks and installs only wheels. The variables PDM_ONLY_BINARY and PDM_NO_BINARY win over pyproject.toml. ↗
  • project.lockfiles: pdm.lock next to pyproject.toml; pdm lock --lockfile writes another name. ↗
  • user.files: <CONFIG_ROOT> is "$XDG_CONFIG_HOME/pdm (~/.config/pdm in most cases) on Linux", "~/Library/Application Support/pdm on macOS" and "%USERPROFILE%\AppData\Local\pdm\pdm on Windows". The code agrees on Linux and Windows: global_config = platformdirs.user_config_path("pdm") / "config.toml", without an override (src/pdm/project/core.py; on Windows the default appauthor repeats the name and roaming is off, so platformdirs asks for the Local AppData known folder). On macOS the directory depends on the installed platformdirs (libraryDirectories); the docs' directory is used when its version cannot be read. The home configuration is TOML whose nested tables are read as dotted keys ([strategy] exclude-newer is strategy.exclude-newer, load_config in src/pdm/project/config.py). -c/--config and PDM_CONFIG_FILE replace it; the site configuration is merged below it. Checked at 2.29.5; earlier versions are not tracked. ↗
  • user.libraryDirectories: PDM 2.29.5 does not pin platformdirs (pyproject.toml; its own lock has 4.9.6). The macOS user_config_dir by platformdirs version, read from the code at the tags: before 4.6.0 always ~/Library/Application Support/<app> (4.5.1 macos.py has no XDG support); 4.6.0 "Honor XDG environment variables on macOS" (#375): a non-empty XDG_CONFIG_HOME wins, a relative one too (os.environ.get("XDG_CONFIG_HOME", "").strip() in _xdg.py), and otherwise the config directory is user_data_dir, so a non-empty XDG_DATA_HOME gives $XDG_DATA_HOME/<app>; 4.9.6 "Fix macOS XDG variables leaking across user_config_dir, user_data_dir, and user_state_dir" (#473; 4.9.4 still returns user_data_dir); 4.11.8 "Ignore relative paths in XDG Base Directory environment variables and use the existing platform fallback" (#540, _xdg_dir with posixpath.isabs); the same in 4.14.2. A relative value is used as it is, so the tool reads it from the directory each command runs in. ↗
  • user.settings: "Allow configuring the default lock --exclude-newer value with strategy.exclude-newer" (2.27.0, #3795): a TOML string such as "7d", a date or an RFC 3339 time. It applies where neither [tool.pdm.resolution] exclude-newer in pyproject.toml nor a project pdm.toml sets it (docs/usage/lockfile.md), and with it in effect pdm lock resolves every package again (src/pdm/cli/commands/lock.py). only-binary, no-binary and exclude-newer-override cannot be set in any PDM configuration file: PDM reads them from [tool.pdm.resolution] in pyproject.toml, only-binary and no-binary also from PDM_ONLY_BINARY and PDM_NO_BINARY (environments/base.py, Project.env_or_setting), so at user level they can be set only through those variables. ↗
  • user.weakening: use_uv (experimental since 2.19.0, PDM_USE_UV) can be set in config.toml and in a project pdm.toml, which wins. PDM passes the cutoff and the build settings to uv lock but not to uv sync --frozen (src/pdm/installers/uv.py), and passes no --no-config, so uv also reads the user uv.toml. A home strategy.exclude-newer cannot weaken a project that sets [tool.pdm.resolution] exclude-newer. use_uv is a switch that turns a protection off and is read with ensure_boolean (src/pdm/project/config.py at 2.29.5): a TOML boolean or number is kept, and a string is false only when empty or false, no or 0 in any case; depcurfew counts every other value as on (other spellings of false too, which errs towards a warning). ↗
  • user.variables: env_or_setting returns os.getenv(var) or the pyproject.toml setting, so a non-empty PDM_ONLY_BINARY or PDM_NO_BINARY wins (environments/base.py). -c/--config and PDM_CONFIG_FILE name the home config file (src/pdm/core.py). PDM_USE_UV is the variable of use_uv, and variables beat pdm.toml and config.toml (src/pdm/project/config.py). ↗
  • extra.installedPackage: The installation page lists uv tool install pdm, pipx install pdm and pip install --user pdm among the other installation methods. Each takes a version with the package: uv tool install "package versions can be included without --from" (uv tool install 'httpie>0.1.0', https://github.com/astral-sh/uv/blob/0.13.6/docs/guides/tools.md), as pipx and pip install do (pipx install poetry==1.8.4 on the installation page of Poetry). So pdm==<version> in such a command of a CI job or a Dockerfile is the PDM the later commands run (decision D-173). ↗
  • extra.environmentNames: A configuration item takes its value from its env_var (PDM_PYPI_URL and the others) with os.environ[item.env_var], and the options read PDM_PROJECT and the other variables with os.getenv("PDM_PROJECT") (src/pdm/cli/options.py), so only those spellings count (decision D-143). ↗
  • extra.pylockCreatedBy: PDM's pylock.toml export writes created-by = "pdm". ↗
  • extra.configTables: exclude-newer, its overrides, only-binary and no-binary share the table. ↗
  • extra.pyprojectTable: PDM keeps its settings in [tool.pdm] of pyproject.toml. ↗
  • extra.buildSwitch: only-binary in [tool.pdm.resolution] since 2.15.0 (#2656). It covers packages from an index: git, URL and path requirements already name their source and are built regardless (candidates.py). ↗
  • extra.durationStrings: "pdm lock --exclude-newer now accepts relative durations in the format N{d|h|w}" (#3760). ↗
  • extra.durationUnits: Written as Nh, Nd and Nw. ↗
  • extra.cutoffDates: convert_to_datetime: N{d|h|w} is a duration from the current UTC time; a value with T is read with datetime.fromisoformat ("A timestamp without an offset is read as UTC, like a bare date"); anything else as %Y-%m-%d at midnight UTC. docs/usage/lockfile.md lists "A RFC 3339 timestamp", "A UTC date" and "A relative duration in the format N{d|h|w}". A timestamp or a date is a fixed cutoff, which holds back more every day. ↗
  • extra.excludeWildcards: Override keys are package names. ↗
  • extra.excludeValue: package = false disables the cutoff for that package. ↗
  • extra.missingUploadTime: The index must give upload-time (PEP 700); an override of false lifts it for the package. ↗
  • extra.lockedSettings: pdm.lock keeps a content_hash of the whole [tool.pdm.resolution] table (PyProject.content_hash), or with canonical lock inputs (lock_inputs = true, since 2.28.1) the table itself (src/pdm/project/lockfile/freshness.py), so a change to any key in it, exclude-newer and only-binary included, makes the lockfile out of date. pdm lock --check and pdm install --check then exit with 1 ("Lockfile doesn't satisfy the project requirements"), pdm install without --check locks again first and pdm sync only warns (check_lockfile in src/pdm/cli/actions.py) until pdm lock runs again; with exclude-newer set, pdm lock resolves every package again (src/pdm/cli/commands/lock.py). ↗
  • extra.lockHash: PyProject.content_hash: json.dumps(dump_data, sort_keys=True) of sources (tool.pdm.source, default []), dependencies, dev-dependencies, optional-dependencies (default {}), requires-python (default "") and resolution (tool.pdm.resolution, default {}), encoded as UTF-8 and hashed with hashlib (sha256). dev-dependencies are the [dependency-groups] tables, each name normalized (normalize_name in src/pdm/utils.py: re.sub(r"[^A-Za-z0-9]+", "-", name).lower(); a name twice is an error), then the lists of tool.pdm.dev-dependencies appended under their normalized names. pdm.lock keeps it as [metadata] content_hash = "sha256:<hex>" (src/pdm/project/lockfile/pdmlock.py). Project.is_lockfile_fresh (src/pdm/project/core.py) compares it only while pdm.lock has no metadata.lock_inputs and resolution.lock_inputs is not true; a workspace root (tool.pdm.workspace set, WorkspaceManager.is_root in src/pdm/project/workspace.py) hashes the members too. PDM reads pyproject.toml with tomllib (src/pdm/project/toml_file.py), and without a [project] table it converts a Poetry or Flit project first (_convert_pyproject). ↗
  • extra.directoryOptions: project_option: "-p", "--project", dest="project_path", help "Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__ [env var: PDM_PROJECT]", default=os.getenv("PDM_PROJECT"). ↗
  • extra.commandLine: pdm add takes requirements as arguments and editable ones with -e; its options come from cli/options.py and the global ones (-c/--config, --pep582, -I, -n, --no-cache) from core.py. --venv and --pep582 take an optional value, so argparse takes the next word for it. PDM parses with argparse, which accepts abbreviated long options. ↗
  • extra.registrySettings: [[tool.pdm.source]] has name, url, verify_ssl, type ("index or find_links, default to index") and include_packages and exclude_packages. "If you want to omit the default PyPI index, just set the source name to pypi and that source will replace it"; the source list is pypi.url (when no source is named pypi), then the sources of pyproject.toml, then pypi.<name>.url of the configuration, and by default "all sources are treated as equal" and the best matching version across them is taken, so any other source adds an index. Project.get_sources (src/pdm/project/core.py) keys the sources by name and fills a source named pypi from pypi.url, so one without a URL is PyPI (or the pypi.url of the user's configuration, which depcurfew does not read); PDM compares the name pypi exactly, depcurfew without regard to case, which only compares more URLs. Variables in url (${PROJECT_ROOT}) are expanded by PDM, so depcurfew cannot read such a URL. include_packages and exclude_packages are not read: a source counts for every package. ↗
  • extra.registryOverrides: pypi.url, the index PDM uses when pyproject.toml names no source called pypi, can be set with PDM_PYPI_URL (docs/usage/config.md); -c/--config and PDM_CONFIG_FILE name another configuration file, which may set any index. ↗
  • extra.configCommands: pdm config [-l|--local] [-d|--delete] [-e|--edit] [key] [value]: with a key and a value it sets the key (_set_config, in the home config.toml, with -l in the pdm.toml of the project), with -d it deletes the key, with -e it opens the file in an editor; a key alone shows its value, and without a key it lists the configuration. docs/usage/config.md sets the index this way: pdm config pypi.url "https://test.pypi.org/simple", pdm config --local pypi.url …, pdm config pypi.extra.url … for an extra index. PDM parses with argparse, which takes abbreviated long options and grouped short ones (commandLine). ↗
  • extra.selection: pdm add --pre/--prerelease allows pre-releases of the added packages to be pinned and --stable only stable versions (prerelease_option; commands/add.py sets req.prerelease). PDM_NO_BINARY and PDM_ONLY_BINARY are lists of packages separated by commas, :all: for every package, of which no wheel, or only wheels, are locked and installed (docs/usage/lockfile.md; environments/base.py, _setting_list). ↗
  • extra.latestVersion: Released on 2026-10-30. ↗

Pipenv

  • cooldown.setting: In the [pipenv] section of the Pipfile: the resolver considers only versions uploaded at least that many days ago. Pipenv computes a cutoff (now minus N days, UTC) and hands it to pip as uploaded-prior-to. ↗
  • cooldown.configFiles: The [pipenv] section. ↗
  • cooldown.unit: A string in <int>d format, e.g. "30d"; any other form is rejected (pipenv/vendor/plette/models/sections.py). ↗
  • cooldown.availableSince: "Added support for cool-down-period in the [pipenv] section of the Pipfile" under 2026.6.2 (repeated under 2026.7.0 and 2026.7.1). Checked against the wheels on 2026-10-30: missing in 2026.6.1, present in 2026.6.2. ↗
  • cooldown.default: Off unless set. ↗
  • installScripts.defaultPolicy: Pipenv installs with pip, which builds source distributions when no wheel fits. Pipenv honors pip configuration and PIP_* variables, which may forbid building (PIP_ONLY_BINARY=:all:), but the Pipfile has no setting for it. ↗
  • project.lockfiles: JSON, generated next to the Pipfile. ↗
  • project.manifests: TOML. ↗
  • user.files: Pipenv has no user configuration file of its own: it reads environment variables (set in a shell profile), the project .env file and pip configuration; pipenv/environments.py looks up no file. Since 2026.3.0 the pip install step runs with PIP_CONFIG_FILE=/dev/null (pipenv/utils/pip.py; CHANGELOG.md, #6066), so a user pip.conf no longer protects pipenv install and sync. The lock resolver still reads pip.conf, but only [global], because its pip command is named InstallCommand (pipenv/utils/resolver.py), and a Pipfile cool-down-period replaces its uploaded-prior-to. ↗
  • user.settings: No user file to write to; at user level only PIP_* variables reach the pip install step (see variables). ↗
  • user.unknownKeys: No user file. ↗
  • user.invalidValueFails: No user file. ↗
  • user.weakening: No user file; see variables. ↗
  • extra.installedPackage: The installation page installs Pipenv with pipx install pipenv and pip install pipenv (pip install --user pipenv), and a given version with pip install --user pipenv==2022.1.8. So pipenv==<version> in such a command of a CI job or a Dockerfile is the Pipenv the later commands run (decision D-173). ↗
  • extra.environmentNames: get_from_env looks up f"{prefix}_{arg}" with the prefix PIPENV (PIPENV_PYPI_MIRROR, PIPENV_PIPFILE, PIPENV_DOTENV_LOCATION) through "positive_lookup in os.environ", that spelling only. PIP_NO_BINARY and PIP_ONLY_BINARY reach the pip Pipenv runs, which reads PIP_ variables with the prefix in upper case and the rest in any case (pip extra.environmentNames). Decision D-143. ↗
  • extra.pylockCreatedBy: Pipenv writes created-by = "pipenv" in the pylock.toml it generates (docs/pylock.md). pipenv install -e . writes the project itself as { path = ".", editable = true } (docs/pipfile.md), and Pipfile.lock keeps it as "path": ".". ↗
  • extra.configTables: Directives such as cool-down-period and allow_prereleases live in [pipenv]. ↗
  • extra.durationStrings: Only whole days (<int>d) are accepted. ↗
  • extra.durationUnits: Whole days only. ↗
  • extra.missingUploadTime: "When the index does not provide upload-time metadata (e.g. most private mirrors) the setting is accepted but has no filtering effect." ↗
  • extra.lockfileFormat: Every key but _meta is a category (default, develop and custom ones) mapping names to entries: index packages have version, hashes and index; git entries git and ref; remote archives file; local projects path, and editable = true for editable installs (Pipfile "Packages Section"). The version is written as a specifier ("version": "==1.2.3"). The hashes of wheels and source distributions are listed together, so the lockfile does not show which packages are built. ↗
  • extra.commandLine: pipenv install takes packages as arguments (without any it installs the Pipfile) and editable ones with -e; -r imports a requirements file. The options of install and the global flags of pipenv, read with argparse, which accepts abbreviated long options. ↗
  • extra.registryOverrides: --index names a package index by URL or by a source name of the Pipfile; --pypi-mirror and PIPENV_PYPI_MIRROR replace PyPI. --extra-pip-args hands arguments to pip, which may name another index, and Pipenv loads PIP_* variables from the .env file that PIPENV_DOTENV_LOCATION names (options.py). ↗
  • extra.directoryOptions: Pipfile.location returns project.s.PIPENV_PIPFILE when it is set, and only otherwise searches the working directory and its parents (find_pipfile, PIPENV_MAX_DEPTH); project_directory is str(Path(self.location).parent.absolute()), and Project.__init__ (pipenv/project.py) changes to it for every command but run. pipenv/environments.py: "If set, this specifies a custom Pipfile location. When running pipenv from a location other than the same directory where the Pipfile is located, instruct pipenv to find the Pipfile in the location specified by this environment variable"; the path is taken relative to the working directory and made absolute. pipenv/cli/options.py has no option that moves the project (--where only prints it). ↗
  • extra.registrySettings: Each [[source]] has name, url and verify_ssl. "all packages are mapped to a single package index for security reasons"; "To install a package from a specific index, you must match the name of the index" (torch = {version = "*", index = "pytorch"} in [packages]); to use another index as the default, "simply omit PyPI from your sources". A package without index comes from the default index, the first source: Resolver.create in pipenv/utils/resolver.py takes project.sources.get_default_index()["name"], which is pipfile_sources()[0] (pipenv/utils/sources.py), and without [[source]] the default is https://pypi.org/simple (pipenv/project.py). With install_search_all_sources = true in [pipenv], "pipenv install and pipenv sync will search all configured sources for packages, but only during installation", so every source adds. Names are compared exactly (get_index_by_name), depcurfew without regard to case; package categories are any top-level table ([packages], [dev-packages] and custom ones). Variables in url are expanded by Pipenv (expand_url_credentials), so depcurfew cannot read such a URL. ↗
  • extra.selection: pipenv install --pre allows pre-releases (and records allow_prereleases in the Pipfile, routines/install.py). Pipenv installs with pip, which reads PIP_NO_BINARY and PIP_ONLY_BINARY like --no-binary and --only-binary (see buildSwitch). ↗
  • extra.latestVersion: Released on 2026-10-28. ↗

Composer

  • cooldown.setting: Withholds versions published within the period when composer update or require resolves dependencies (also init and create-project when they pick a constraint). Measured from the publication time the repository reports (published-time, which Packagist.org provides and package authors cannot influence); a Composer repository that lacks it makes the command fail unless require-published-time is false on it, and packages from VCS, path or artifact repositories use the author-set time of their composer.json. Never withheld: dev versions, locked packages a partial update keeps, platform packages and versions without any date. ↗
  • cooldown.configFiles: config is root-only: "It is only used for projects." COMPOSER_HOME/config.json is merged under it (only its config and repositories keys), and "the local configuration in the project's composer.json always wins" (03-cli.md#composer-home-config-json). ↗
  • cooldown.unit: "A duration string in the form "<number> <unit>" where the unit is one of second, minute, hour, day or week (lowercase, singular or plural - e.g. "7 days", "24 hours", "30 minutes", "1 week"), an integer number of seconds, or null to disable." ↗
  • cooldown.availableSince: "Added a cooldown policy to withhold newly released package versions for a configurable period" under 2.11.0-RC1 (2026-10-22); 2.11.0 was released on 2026-10-29. ↗
  • cooldown.default: "Defaults to null (no cooldown period). The policy only takes effect once a period is set." ↗
  • cooldown.exclude.setting: "Packages listed under ignore bypass the cooldown policy." The ignore format of the other policies: a list of names, or an object of names to a reason, to { constraint, reason, on-block, on-audit } or to a list of such rules. ↗
  • cooldown.exclude.availableSince: Part of the cooldown policy added in 2.11.0-RC1. ↗
  • cooldown.exclude.patternSyntax: "package names support wildcards (e.g. vendor/*)". ↗
  • installScripts.defaultPolicy: Only the root package's scripts run (articles/scripts.md: "If a dependency of the root package specifies its own scripts, Composer does not execute those additional scripts"); dependency code runs during Composer commands through plugins, packages of type composer-plugin. allow-plugins (2.2.0) "Defaults to {} which does not allow any plugins to be loaded": a plugin it does not list makes Composer ask in an interactive run and fail in a non-interactive one, or skips it when the plugin declares plugin-optional (PluginManager::isPluginAllowed, articles/plugins.md). ↗
  • installScripts.allowList.setting: "Use this setting to allow only packages you trust to execute code." ↗
  • installScripts.allowList.file: Root-only, like every config option. ↗
  • installScripts.allowList.availableSince: "As of Composer 2.2.0, the allow-plugins option adds a layer of security". ↗
  • installScripts.allowList.format: parseAllowedPlugins turns each key into a pattern; isPluginAllowed returns the value of the first pattern that matches, in the order written. Config::merge puts the keys of COMPOSER_HOME/config.json after the project's, the project's values winning. ↗
  • installScripts.disableAll: "You can also set the config option itself to false to disallow all plugins"; --no-plugins does the same for one command (03-cli.md#global-options). ↗
  • project.lockfiles: JSON next to composer.json. With COMPOSER=<name>.json Composer reads another manifest and writes <name>.lock (03-cli.md#composer); depcurfew reads composer.json and composer.lock only. ↗
  • project.manifests: The root package; repositories, config and scripts are read only from it. ↗
  • extra.environmentNames: Platform::getEnv looks the name up with array_key_exists($name, $_SERVER), then in $_ENV, then with getenv($name), so outside Windows only that spelling counts: COMPOSER and COMPOSER_HOME, not Composer or composer (decision D-143). ↗
  • extra.latestVersion: Released on 2026-10-30. ↗
  • extra.durationStrings: parseDuration: an integer, or a string of digits (/^\d+$/D), is a number of seconds; otherwise only /^(\d+)\s*(second|minute|hour|day|week)s?$/D is accepted (lowercase, one unit). The string is matched as it is, so a space before or after the value (" 14 days") is not accepted. null, "", 0 and "0" mean no cooldown; any other value makes the command fail with "Invalid policy.cooldown.period format", and so does such a COMPOSER_POLICY_COOLDOWN_PERIOD. ↗
  • extra.durationUnits: The documented examples are "7 days", "24 hours", "30 minutes" and "1 week"; depcurfew writes whole days, rounded up. ↗
  • extra.excludeWildcards: "package names support wildcards (e.g. vendor/*)" in ignore. ↗
  • extra.denyList: "The values are true to allow and false to disallow while suppressing further warnings and prompts." ↗
  • extra.cooldownTime: getEffectiveDate returns the published date, else the release date (time). A Composer repository must give published-time while a cooldown is configured, unless require-published-time is false on it (05-repositories.md#require-published-time: "That field is set by the package author, so the protection is weaker"); ArtifactRepository drops a published-time from the archive's composer.json. ↗
  • extra.lockedVersions: "The cooldown policy applies when resolving dependencies during composer update/require"; "Locked packages that are not being updated" are never withheld. ↗
  • extra.contentHash: getContentHash hashes name, version, require, require-dev, conflict, replace, provide, minimum-stability, prefer-stable, repositories, extra, config.platform and config.policy ("policy changes which versions an update may pick, so changing it should flag the lock as outdated"; CHANGELOG 2.11.0-RC1, #13149). With another hash composer install warns that "The lock file is not up to date with the latest changes in composer.json" (Installer.php) and composer validate fails (03-cli.md#validate); composer update --lock "Overwrites the lock file hash to suppress warning about the lock file being out of date without updating package versions" (03-cli.md#update-u-upgrade). allow-plugins is not hashed. Locker::getContentHash at 2.10.3 hashes config.platform but not config.policy, so a hash written by Composer 2.10 or older differs from what 2.11 computes for a composer.json with config.policy (https://github.com/composer/composer/blob/2.10.3/src/Composer/Package/Locker.php). ↗
  • extra.pluginApiVersion: Locker writes PluginInterface::PLUGIN_API_VERSION of the Composer that writes composer.lock into plugin-api-version (Locker.php; CHANGELOG 1.10.0: "so third-party tools can know which Composer version was used to generate a lock file"). It is 2.11.0 at 2.11.1 ("Bumped composer-plugin-api to 2.11.0" under 2.11.0-RC1) and 2.9.0 at 2.10.3, so a lower value was written by a Composer older than 2.11.0. It names the Composer that last wrote the lock, not every Composer that installs it. ↗
  • extra.lockfileFormat: Each entry of packages and packages-dev has name, version, type and the source { type, url, reference } and dist { type, url, reference, shasum } it installs from, time and, from a repository that gives it, published-time. A package of a path repository has dist type path with the path as url (PathRepository.php); one of an artifact repository has the archive type and its file path as url (ArtifactRepository.php). Composer reads name and type in lower case (BasePackage::__construct and ArrayLoader::configureObject: strtolower), so "Composer-Plugin" is a plugin too. Plugins are packages of type composer-plugin (04-schema.md#type), and Composer also loads the legacy type composer-installer as a plugin, under the same allow-plugins check (PluginInstaller::supports, PluginManager::registerPackage). A plugin whose extra.plugin-optional is true is skipped without a question when Composer runs without a terminal and it is not allowed (PluginManager::isPluginAllowed: elseif ($optional) return false). ↗
  • extra.legacyLockPlugins: parseAllowedPlugins returns no rules when allow-plugins is empty ({} or missing) and composer.lock has a plugin-api-version below 2.2.0, or none (Locker::getPluginApi returns 1.1.0 then). In that mode Composer 2.2 to 2.9 load every plugin without asking when run without a terminal ("if no config is defined we allow all plugins for BC", PluginManager.php at 2.9.8); since 2.10.0-RC1 Composer stops with an error there instead ("Enforce allow-plugins even in non-interactive mode for very old pre-2.2 lock files", #12764 in CHANGELOG.md) and asks in a terminal. ↗
  • extra.manifestSyntax: JsonFile::parseJson at 2.11.1 reads composer.json with PHP's json_decode($json, true) and, when it fails, reports the error with JsonFile::validateSyntax (seld/jsonlint), so a comment or a trailing comma in composer.json stops every Composer command; json_decode takes strict JSON (RFC 8259), which has neither. ↗
  • extra.sourceInstall: getAvailableSources offers source when the package has a source type and dist when it has a dist type; a locked package without a dist is installed from its source, a checkout of the VCS repository the entry names, whatever repository composer.json declares. ↗
  • extra.registryDistHosts: The archives Composer's VCS drivers give a package of the hosts Composer knows by default (github-domains github.com, gitlab-domains gitlab.com, forgejo-domains codeberg.org in Config.php, and Bitbucket): GitHubDriver::getDist https://api.github.com/repos/<owner>/<repo>/zipball/<ref>, GitLabDriver::getDist <scheme>://gitlab.com/api/v4/projects/<id>/repository/archive.zip, GitBitbucketDriver::getDist https://bitbucket.org/<owner>/<repo>/get/<ref>.zip, ForgejoDriver::getDist <host>/api/v1/repos/<owner>/<repo>/archive/<ref>.zip; GitDriver::getDist gives none. ↗
  • extra.repositoryArchiveHosts: The hosts the archives of a Composer repository other than Packagist.org come from, by the host of the repository URL. WPackagist (the Composer repository https://wpackagist.org that its README tells composer.json to declare) gives each plugin version the dist https://downloads.wordpress.org/plugin/<name>.<version>.zip (Plugin::getDownloadUrl) and each theme version https://downloads.wordpress.org/theme/<name>.<version>.zip (Theme::getDownloadUrl in src/Entity/Theme.php), with a dist of type zip and a source of type svn on plugins.svn.wordpress.org or themes.svn.wordpress.org (Package::getPackageVersion in src/Entity/Package.php), all at commit 9b5db4a of the develop branch (the repository has no tags). The archive host of packages.drupal.org could not be read at its source (drupal.org is not reachable from where this was checked), so it is not listed. ↗
  • extra.branchVersions: A locked version names a branch, not a release, when it starts with dev- or ends with -dev: "Composer automatically adds a -dev suffix to all numeric branches and prefixes all other branches imported from a VCS repository with dev-" (versions.md, Stabilities); a tag gives its own version (v7.3.4 or 3.9.0, as the tag is written). ↗
  • extra.repositoryTypes: The repository classes of createRepositoryManager; 05-repositories.md describes composer, vcs (with the drivers bitbucket, github, gitlab, perforce, fossil, git, svn and hg; git-bitbucket is deprecated), path, package and artifact, and { "packagist.org": false } to disable Packagist.org. repositories is root-only. ↗
  • extra.weakeningSettings: "Set to false to disable all dependency policy enforcement"; malware "block: Defaults to true", "block-scope: Defaults to all", update blocks "only during update/require/remove"; cooldown block "Set to false to skip blocking for a cooldown period entirely". policy, cooldown and malware are compared with false exactly; block is read with PHP's (bool) cast after ?? true, so false, 0, "", "0" and [] turn blocking off, while a missing or null block keeps the default and "false" is true (Config.php, MalwarePolicyConfig.php, CooldownPolicyConfig.php). ↗
  • extra.transportSettings: secure-http "Defaults to true. If set to true only HTTPS URLs are allowed to be downloaded via Composer"; disable-tls "Defaults to false. If set to true all HTTPS URLs will be tried with HTTP instead" and "will implicitly disable the secure-http option". Config::get reads both as $value !== "false" && (bool) $value (Config.php), so "false", false, 0, "", "0" and null are false. ↗
  • extra.allowAllPlugins: "or true to allow all plugins to run (NOT recommended)". BasePackage::packageNameToRegexp turns a key into {^...$}i with * as .*, so keys match without regard to case and * matches / too: a key made only of * with at most one / between them ("*", "*/*") with true allows every vendor/name plugin that no earlier key names. ↗
  • extra.repositoryWeakening: require-published-time "Defaults to true"; false falls "back to the time field of each package's composer.json. That field is set by the package author, so the protection is weaker." Only false counts (ComposerRepository.php). "Set filter: false to opt out of every list this repository advertises", or an object that sets a list name to false to skip that list (#filter); Packagist.org advertises the list malware (repo.packagist.org/packages.json). ↗
  • extra.environmentOverrides: COMPOSER_POLICY: "Set to 0 to disable all dependency policy enforcement" (read with Platform::getBoolEnv: 0, false and off are false). COMPOSER_NO_BLOCKING and COMPOSER_NO_SECURITY_BLOCKING: BaseCommand::createPolicyConfig reads both with Platform::getBoolEnv(..., false), which takes only 0, 1, false, true, off and on and makes update, require, install, remove and create-project stop with "Invalid value for COMPOSER_NO_BLOCKING" for any other value but ""; 1, true and on turn blocking off there (PolicyConfig::withBlockingDisabled: advisories, malware, abandoned packages, the cooldown and custom lists). BaseCommand::initialize also sets --no-blocking and --no-security-blocking when (bool) getenv() is true, so false and off turn blocking off as well for the commands that have the option (update, require, install, remove, create-project). COMPOSER_POLICY_COOLDOWN_PERIOD "overrides the configured period", 0 disabling it; COMPOSER_POLICY_COOLDOWN_BLOCK and COMPOSER_POLICY_MALWARE_BLOCK set 0 to disable blocking (PolicyConfig.php). ↗
  • extra.packagistApi: "Using the Composer v2 metadata": GET https://repo.packagist.org/p2/[vendor]/[package].json gives {"packages": {"[vendor]/[package]": [versions]}, "minified": "composer/2.0"}, each version with version, "time": [release datetime, as set by the package author] and "published-time": [datetime the version was published on packagist.org, not influenced by the package author]; the list "requires you to use Composer\MetadataMinifier\MetadataMinifier::expand"; "The p2/$vendor/$package.json file contains only tagged releases", branches are in p2/$vendor/$package~dev.json; package pages are https://packagist.org/packages/[vendor]/[package]. https://repo.packagist.org is the url of the packagist.org repository Composer adds by default (Config::$defaultRepositories at 2.11.1). Composer reads a 404 as a package the repository does not have (ComposerRepository.php), expands a list marked composer/2.0 and loads each version with ArrayLoader.php: version_normalized (else the version normalized), type (lowercased, library when missing), time, published-time (an integer or a non-empty string) and abandoned (true or the name of a replacement). ↗
  • extra.metadataMinifier: MetadataMinifier::expand: the first entry is a whole version; each later entry holds only the keys that changed since the previous version, a key with the value "__unset" being removed; while the version built so far is empty (PHP: !$expandedVersion), the next entry is taken whole again. Composer 2.11.1 locks composer/metadata-minifier 1.0.1. ↗
  • extra.versionConstraints: Exact version (1.0.2); ranges with >, >=, <, <=, != separated by a space or comma (logical AND) or || (logical OR, and | for backwards compatibility), AND binding tighter; the hyphenated range 1.0 - 2.0 (>=1.0.0 <2.1, a partial right end completed with a wildcard); wildcard 1.0.* (>=1.0 <1.1); ~1.2 (>=1.2 <2.0.0), ~1.2.3 (>=1.2.3 <1.3.0), ~1 like ~1.0; ^1.2.3 (>=1.2.3 <2.0.0), ^0.3 (>=0.3.0 <0.4.0), ^0.0.3 (>=0.0.3 <0.0.4); stability flags @<stability>; a branch as dev-<branch>, or <version>.x-dev for a branch named like a version (versions.md). composer/semver 3.6.0 (src/VersionParser.php, which Composer 2.11.1 locks, https://github.com/composer/semver/blob/3.6.0/src/VersionParser.php) also reads = and == as exact, <> as !=, x, X and * as wildcards, "<version> as <alias>", #<commit> after a branch, and appends -dev to the bound of < and >= without an explicit stability, so that pre-releases of the bound are below it. ↗
  • extra.stabilities: minimum-stability "defaults to stable"; the options in order of stability are dev, alpha, beta, RC and stable, and stability flags allow another stability per package. BasePackage::STABILITIES at 2.11.1 gives the priorities (stable 0 to dev 20); StabilityFilter::isPackageAcceptable accepts a version whose stability priority is at most the flag of its package, else at most the minimum stability. RootPackageLoader::extractStabilityFlags takes the least stable @<stability> of a requirement as its flag, else the stability of an explicit unstable version in it (2.0.0-beta1) when that is less stable than the minimum stability. VersionParser::parseStability (composer/semver 3.6.0): a version starting with dev- or ending with -dev is dev; a modifier beta or b is beta, alpha or a is alpha, RC is RC (in any case), anything else (patch, pl, p, none) is stable. Versions without a stability suffix are stable (articles/versions.md#stabilities). ↗
  • extra.versionComparison: Composer orders normalized versions with PHP's version_compare (VersionSelector.php at 2.11.1; Constraint::versionCompare in composer/semver 3.6.0, where a dev- branch only equals itself). php_canonicalize_version replaces -, _ and + with a dot and puts a dot between a digit and a non-digit; the parts are compared one by one, numbers as numbers, words by the first special form they start with (dev < alpha = a < beta = b < RC = rc < # < pl = p; a word that starts with none is lowest), a number against a word as the form # (#N#); when one version has parts left, a number makes it the greater and a word is compared with #N#. ↗
  • extra.commandLine: composer require (alias r) takes packages as "vendor/package:2.*" or vendor/package2:dev-master, and picks a constraint itself for a package without one; composer global <command> runs the command "as if you were running them from the COMPOSER_HOME directory"; composer create-project <package> [<directory>] [<version>]; composer update (u, upgrade) takes packages, wildcards and constraints vendor/package:2.0.1, and --with foo/bar:1.0.0. "As Composer uses symfony/console you can call commands by short name if it's not ambiguous" (commandNames). The options with a value of require, update, create-project, install, config and repository (InputOption VALUE_REQUIRED or VALUE_OPTIONAL in src/Composer/Command/*Command.php at 2.11.1) and the global --working-dir (-d) of src/Composer/Console/Application.php; symfony/console v5.4.55 (Input/ArgvInput.php) groups short options (-nd dir), takes a value attached (-ddir, --working-dir=dir) or the next word when it does not start with -, accepts options before and after the command, reads every word after -- as an argument and does not shorten long options. ↗
  • extra.commandNames: Application::find: an exact command name or alias; otherwise every name and alias that starts with the word (for each part between colons, a name with more parts too), first with case and then without (ASCII letters only, PCRE without u), of which one must match the word whole; an alias is left out when the name of its command is in the list, a hidden command (_complete) when others remain; one name is run, more are ambiguous (an error) and none is not defined. The names and aliases are those of Composer's getDefaultCommands (src/Composer/Console/Application.php at 2.11.1, setName and setAliases in each src/Composer/Command/*Command.php) and of symfony/console (help, list, completion and the hidden _complete). Scripts of composer.json (extra.scriptCommands) and commands of plugins are added as commands too, unless a command of that name exists. ↗
  • extra.commandArguments: parseNameVersionPairs: an argument is split at the first =, : or space after the name; an argument without one takes the next argument as its constraint when that has no /, no * next to a letter, digit, _, / or - and is no platform package. require and create-project read their packages so (RequireCommand via PackageDiscoveryTrait, CreateProjectCommand::installRootPackage); update moves an argument with a constraint (\S+[ =:]\S+) to the temporary constraints of --with and takes lock, nothing and mirrors as --lock (UpdateCommand.php). create-project takes its stability from --stability (-s), else from the @<stability> of its version, else from the version itself. Platform packages are PlatformRepository::PLATFORM_PACKAGE_REGEX (case-insensitive). The name pattern is the one 04-schema.md#name gives (ValidatingArrayLoader::hasPackageNamingError checks the same with possessive quantifiers); Composer lowercases the names it looks up. Both are written here as patterns of the same names whose repeated group starts with its separator (X+(?:[sep]X+)*, decision D-136), so that a long name that fails at its end is read in linear time: X(?:[sep]?X+)* can split a run of letters in exponentially many ways. ↗
  • extra.registryOverrides: create-project --repository "Provide a custom repository to search for the package, which will be used instead of packagist" (and --repository-url, CreateProjectCommand.php at 2.11.1). COMPOSER sets the file name of composer.json, whose repositories then apply (#composer). COMPOSER_HOME sets the home directory (Factory::getHomeDir: "if ($home = Platform::getEnv('COMPOSER_HOME')) return $home"), whose config.json Factory::createConfig merges under the configuration of every project, its repositories included (03-cli.md#composer-home-config-json), and in which composer global runs, with the composer.json there (GlobalCommand::prepareSubcommandInput changes to the home directory of the configuration). Other commands take their repositories from composer.json only. ↗
  • extra.installOverrides: createPolicyConfig: --no-blocking, --no-security-blocking (deprecated), COMPOSER_NO_BLOCKING and COMPOSER_NO_SECURITY_BLOCKING "disable ALL blocking (advisories + malware + abandoned + cooldown + custom)" (PolicyConfig::withBlockingDisabled); --no-cooldown disables only the cooldown blocking. initialize sets --no-blocking and --no-security-blocking on each command that has them when (bool) getenv() is true, so for every value but "" and "0" ("false" and "off" too); createPolicyConfig also reads both with Platform::getBoolEnv, which makes the command fail for a value other than 0, 1, false, true, off and on (src/Composer/Util/Platform.php), so such a value installs nothing. COMPOSER_POLICY (Config::get), COMPOSER_POLICY_COOLDOWN_BLOCK and COMPOSER_POLICY_MALWARE_BLOCK (PolicyConfig::fromConfig) are read with getBoolEnv: 0, false and off turn them off. COMPOSER_POLICY_COOLDOWN_PERIOD replaces the period (CooldownPolicyConfig::getEnvPeriod, in the syntax of durationStrings). create-project --no-secure-http "Disable the secure-http config option temporarily while installing the root package" (03-cli.md#create-project): CreateProjectCommand::installRootPackage merges secure-http false into the configuration it installs the project package with, and secure-http "Defaults to true. If set to true only HTTPS URLs are allowed to be downloaded via Composer" (06-config.md#secure-http). The options are on require, update, install, create-project and remove (03-cli.md). ↗
  • extra.configCommands: composer config [options] [setting-key] [setting-value1] ... changes a setting of composer.json (with --global, -g, of COMPOSER_HOME/config.json; with --file, -f, of that file), --unset removes one and --editor (-e) opens the file; with a key alone it shows the value (src/Composer/Command/ConfigCommand.php at 2.11.1). composer repository (repo) add, remove (rm, delete), set-url (seturl), enable and disable change the repositories, list (ls, show) and get-url (geturl) only read them (RepositoryCommand.php). composer policy add-source changes config.policy (PolicyCommand.php). config, repository and policy all take --global (-g, "Apply command to the global config file") and --file (-f, "If you want to choose a different composer.json or config.json"). The same commands after composer global change the files of COMPOSER_HOME: GlobalCommand runs them in the home directory, where composer.json is the one of composer global and config.json the configuration that Factory::createConfig merges under that of every project. depcurfew reads neither file (decision D-133), so a change there counts also without an install next to it (unread). ↗
  • extra.configCommandValues: composer config KEY VALUE writes the setting into config of composer.json (JsonConfigSource::addConfigSetting at 2.11.1; --global, -g, --file and -f write another file, configCommands). ConfigCommand::execute at 2.11.1 takes a key of the form policy.<list> (policy.cooldown, policy.malware) and the block keys (policy.cooldown.block, policy.malware.block), secure-http, disable-tls and allow-plugins only with true, false, 1 or 0 ($booleanValidator) and stores $val !== 'false' && (bool) $val ($booleanNormalizer), so false and 0 are false; policy.cooldown.period takes a duration CooldownPolicyConfig::parseDuration reads, or null or the empty text for none, a number as an integer; policy.malware.block-scope one of all, update and install, as written. addConfigSetting nests a key that starts with policy. at its dots under config (policy.cooldown false gives "config": {"policy": {"cooldown": false}}), replacing the object that was there. So composer config policy.cooldown false in CI turns the cooldown off in the composer.json the later commands read. ↗
  • extra.applicationOptions: Composer finds the command name before it knows the command (getCommandNameBeforeBinding: "This ensures we can find the correct command name even if a global input option is present before it"): it binds the words to the input definition of the application, ignoring the error that stops the binding (an option it does not define, a missing value, a second argument), and takes $input->getFirstArgument(). The definition is that of symfony/console (Application::getDefaultInputDefinition at v5.4.55: the command argument, --help -h, --quiet -q, --verbose -v|vv|vvv, --version -V, --ansi|--no-ansi, --no-interaction -n) with the --profile, --no-plugins, --no-scripts, --working-dir -d (with a value) and --no-cache of Composer. ArgvInput::getFirstArgument (v5.4.55) passes over each word that starts with -, and also over the next word when the option is one the binding set (a long name, or the last letter of a short one) and that word equals its bound value; the first other word is the command. So only -d and --working-dir take the word after them before the command, an option of a command (--ignore-platform-req) does not, and that command later binds the word after it as its value (Input/ArgvInput.php: parse, addLongOption, parseShortOptionSet). ↗
  • extra.scriptCommands: doRunComposer registers the scripts of the composer.json it runs with (Factory::getComposerFile, after -d) as commands when the command word is not the exact name of a command Composer found before (mayNeedScriptCommand: "$rawCommandName !== $commandName", so also for an alias, an abbreviation, another case or a word that names no command) or the command is run-script. Each key of scripts that is no event (the constants of src/Composer/Script/ScriptEvents.php, compared in upper case with - as _) and not already a command or alias ($this->has($script): "A script named ... would override a Composer command and has been skipped") becomes a ScriptAliasCommand with the aliases that scripts-aliases gives it. Application::add of symfony/console (v5.4.55) maps the name and each alias to it, over an alias or name of another command; Command::setName and setAliases reject a name that is not parts without a colon separated by single colons (validateName), and ScriptAliasCommand an alias that is not a string, which stops Composer. find() then resolves the word among all of them: the exact name or alias, else the names that start with it. ScriptAliasCommand runs the script as composer run-script does (src/Composer/Command/ScriptAliasCommand.php). ↗
  • extra.scriptAliases: 2.7.0: "Added `scripts-aliases` top level key in composer.json to define aliases for custom scripts you defined" (#11666). Application::doRunComposer at 2.6.6 and 2.2.25 (src/Composer/Console/Application.php) registers each script of composer.json as a ScriptAliasCommand without aliases ($this->add(new Command\ScriptAliasCommand($script, $description))), and from 2.7.0 with $composer['scripts-aliases'][$script]. So on Composer 2.2 LTS to 2.6 a word that scripts-aliases gives a script is still the Composer command or alias of that name (r is require). ↗
  • extra.rootStability: RootPackageLoader reads minimum-stability of the root composer.json through VersionParser::normalizeStability (composer/semver 3.6.0: lower case, one of stable, RC, beta, alpha and dev, else an exception) and prefer-stable as (bool) $config['prefer-stable']. composer require without a constraint takes the minimum stability of composer.json (PackageDiscoveryTrait::getMinimumStability) for the versions it considers and asks VersionSelector::findBestCandidate for a version with the preferred stability "stable" under prefer-stable, else the minimum stability (RequireCommand.php): versions at least that stable come first, the highest of them, else the most stable of the others. The solver orders the versions a constraint allows with DefaultPolicy::versionCompare: with prefer-stable the more stable one first, else the higher version, which a branch (dev-main aliased 3.x-dev) is. All at 2.11.1 (src/Composer/Package/Version/VersionSelector.php, src/Composer/DependencyResolver/DefaultPolicy.php, src/Composer/Command/PackageDiscoveryTrait.php). ↗
  • extra.installPreference: DownloadManager::getAvailableSources offers source before dist (each only with a type) and reverses them "in case dist is the preferred source for this package": unless preferSource, when preferDist or resolvePackageInstallPreference says dist. BaseCommand::getPreferredInstallOptions sets preferSource for config.preferred-install "source" and preferDist for "dist" (Config::$defaultConfig has "dist"), and neither for "auto", another string or an object; Factory::createDownloadManager hands an object to setPreferences. resolvePackageInstallPreference takes the first key that matches the package name ({^pattern$}i with * as .*): "dist", or "auto" for a version that is not dev, gives dist, any other value source; with no match, source for a dev version (a branch) and dist for others. Config::merge turns the default "dist" into {"*": "dist"} under an object of composer.json and moves the "*" key to the end. --prefer-source, --prefer-dist and --prefer-install override it for one command. All at 2.11.1 (src/Composer/Command/BaseCommand.php, src/Composer/Factory.php, src/Composer/Config.php). ↗
  • extra.sourceFallback: 2.10.0: "Disabled automatic fallback to source checkout if dist/zip install fails, we have introduced a new source-fallback config option as a temporary way to restore the old behavior" (#12885); 2.11.0-RC1: "Removed the source-fallback config option which was added in 2.10 as a temporary measure, dist installs no longer fall back to source" (#13050). DownloadManager::download at 2.11.1 only falls back from source to dist ("Only fallback from dist to source is risky as it can silently switch to less-trusted code"). Composer before 2.10.0 installs a package from its source when the download of its archive fails. ↗
  • extra.registrySourceHosts: The host of the source that the VCS driver gives a package whose archive comes from a host of registryDistHosts: GitHubDriver::getSource https://github.com/<owner>/<repo>.git (git@github.com:<owner>/<repo>.git for a private repository) beside its archive on api.github.com; GitLabDriver::getSource the http_url_to_repo or ssh_url_to_repo of the project on gitlab.com; GitBitbucketDriver::getSource the URL of the repository on bitbucket.org; ForgejoDriver::getSource its clone URL on codeberg.org (src/Composer/Repository/Vcs/*Driver.php at 2.11.1). ↗
  • extra.sourceHostAliases: GitHubDriver::initialize at 2.11.1 reads the host of the repository URL in lower case and takes www.github.com for github.com ("if ($this->originUrl === 'www.github.com') { $this->originUrl = 'github.com'; }"), and GitHubDriver::supports compares the host without www. with github-domains. GitLabDriver::determineOrigin compares the host (with its port) with gitlab-domains as written, GitBitbucketDriver::supports takes only https://bitbucket.org/…, and ForgejoDriver compares the host with forgejo-domains as written (src/Composer/Repository/Vcs/*Driver.php at 2.11.1), so only GitHub has such a host. ↗
  • extra.directoryOptions: "--working-dir (-d): If specified, use the given directory as working directory." Application::doRunComposer changes to it before it reads composer.json (src/Composer/Console/Application.php at 2.11.1). Without it and without composer.json in the current directory (and for a command other than list, init, about, help, diagnose, self-update, global, create-project and outdated), Composer looks for the nearest parent with one, stopping before the home directory and the root of the file system: an interactive run asks whether to use it, use-parent-dir true uses it without asking, and a run without a terminal (stdin not a TTY, or COMPOSER_NO_INTERACTION) with the default use-parent-dir "prompt" (Config::$defaultConfig in src/Composer/Config.php) stays in the current directory and only says so; with --working-dir it never looks at a parent. It then registers the scripts (Application.php) and reads minimum-stability (PackageDiscoveryTrait::getMinimumStability) of Factory::getComposerFile() in the directory it is in. getNewWorkingDir reads the directory with $input->getParameterOption(['--working-dir', '-d'], null, true), which in symfony/console v5.4.55 (Input/ArgvInput.php) takes the first word, up to --, that is --working-dir or -d (then the next word) or starts with --working-dir= or -d (then the rest of the word); a grouped -nd dir does not start with -d, so Composer stays where it is, although the command later binds -n and -d dir as options. ↗

Bundler

  • cooldown.setting: The cooldown: keyword of a source call in the Gemfile (source "https://rubygems.org", cooldown: 7): Dsl#source raises InvalidOption unless it is an Integer of 0 or more. It applies to the versions that come from that source (Source::Rubygems::Remote#effective_cooldown), cooldown: 0 exempts the source. The cooldown setting (bundle config set cooldown N, BUNDLE_COOLDOWN) and --cooldown N take its place for every source, also one with cooldown: 0 (extra.cooldownSetting). ↗
  • cooldown.configFiles: The keyword is written in the Gemfile, or in gems.rb, which Bundler reads in its place (extra.gemfileNames). ↗
  • cooldown.cliFlag: bundle install, update, add and outdated take --cooldown N since 4.0.13, bundle lock and bundle cache since 4.0.18 ("Add --cooldown flag to bundle lock and bundle cache", #9725); method_option "cooldown" of these commands in lib/bundler/cli.rb. N is a whole number of days of 0 or more (CLI::Common.validate_cooldown!); it overrides the cooldown setting and the keyword of every source for that run, and 0 turns the cooldown off (bundle-install(1)). ↗
  • cooldown.unit: Resolver#cooldown_excluded? holds back a version while (now - created_at) < days * 86_400. The keyword and the flag take whole days only; the setting is read with to_i (extra.cooldownSetting). ↗
  • cooldown.availableSince: "Add `cooldown` to delay newly published gem" (#9576) under 4.0.13 / 2026-06-03. Bundler 4.0.12 and 2.7.2 ignore an option of source they do not know without a word (extra.olderVersions). Until 4.0.14 the keyword of a Gemfile source was lost once Gemfile.lock existed (extra.cooldownWithLockfile). ↗
  • cooldown.default: "Defaults to unset (no cooldown)"; the blog post calls the feature opt-in. ↗
  • cooldown.securityUpdates: The resolver holds back every version younger than the cooldown, a fix included (Resolver#cooldown_excluded? has no exception); the post names --cooldown 0 as the way to take "the freshest release" when "a fix lands for an actively exploited 0-day". ↗
  • installScripts.defaultPolicy: Bundler::RubyGemsGemInstaller#install builds the native extensions of a gem whose gemspec lists any (build_extensions if spec.extensions.any?); Gem::Ext::Builder runs the extconf.rb, configure, Rakefile or mkrf_conf, CMakeLists.txt or Cargo.toml of the gem (lib/rubygems/ext/builder.rb at the same tag), code of the gem that runs when it is installed. ↗
  • project.lockfiles: SharedHelpers#default_lockfile: gems.locked for gems.rb, else the name of the Gemfile with .lock; BUNDLE_LOCKFILE names another file. ↗
  • project.manifests: SharedHelpers#gemfile_names; BUNDLE_GEMFILE names another file. ↗
  • extra.latestVersion: {"version":"4.0.23"} on 2026-11-03; 4.0.23 / 2026-10-14 in bundler/CHANGELOG.md. 4.1.0.beta3 (2026-10-28) is a pre-release. ↗
  • extra.gemfileNames: SharedHelpers#find_gemfile looks for gems.rb, then Gemfile, from the current directory up; with both in one directory Bundler warns ("Multiple gemfiles (gems.rb and Gemfile) detected") and reads gems.rb. find_file takes a name only when File.file? is true, so a directory (or another entry that is not a file) of that name is skipped; a symlink to a file counts. ↗
  • extra.lockfileExists: Definition#lockfile_exists? is lockfile && File.exist?(lockfile): any entry of that name counts, and a symlink is followed. Bundler reads the lockfile from there; depcurfew only tests whether it is there and never reads or edits it for the cooldown. ↗
  • extra.gemfileEvaluation: Dsl#eval_gemfile reads the Gemfile with Bundler.read_file (File.open(file, "r:UTF-8"), lib/bundler.rb) and runs it with instance_eval(contents, gemfile, 1), so Ruby's parser decides what in it is code (extra.rubySyntax). ↗
  • extra.rubySyntax: How Ruby's lexer (parse.y) reads what decides where code ends. nextc reads \r\n as one newline everywhere (parser_cr), also inside a literal delimited by \r, which only a \r alone ends; a \r alone between tokens is a space. parser_yylex ends the script at NUL, ^D (\004) or ^Z (\032) where a token starts, and at a line that is exactly __END__ (whole_match_p, with \r\n allowed); =begin at the start of a line starts a comment that ends with a line starting with =end (word_match_p: followed by whitespace, the end of the line, NUL, ^D or ^Z); # starts a comment to the end of the line. parse_percent: % starts a literal where an expression begins (IS_BEG), or after a method name with a space before % and none after it (IS_SPCARG), otherwise it is an operator; its type letter is one of Q, q, W, w, I, i, x, r, s (none means Q), the delimiter is any ASCII character that is no letter or digit, and ( [ { < pair with ) ] } > and nest (tokadd_string). heredoc_identifier: << with - or ~ and an identifier of letters, digits, _ or non-ASCII characters, or any text in ', " or ` quotes on that line; not after a value (IS_END), after . or class, or after a method name without a space; here_document: the body starts on the line after the one with <<, after the bodies of earlier heredocs of that line, and ends at a line that is exactly the identifier (with - and ~ after leading whitespace, never with trailing spaces); in a heredoc with escapes a line after one that ends with a backslash is no terminator. Strings in double quotes, `, %Q, %W, %I, %x, %r, /, :" and heredocs without ' interpolate #{...}, #@var and #$var (parser_peek_variable_name, is_global_name_punct). parse_qmark: ? starts a character literal unless a value comes before it, a space follows or two identifier characters follow; \u{...} holds hex digits and spaces. The keywords set the lexer state as defs/keywords lists them (EXPR_END, EXPR_BEG, EXPR_VALUE, EXPR_MID, EXPR_ARG, EXPR_FNAME, EXPR_CLASS); if, unless, while, until and rescue are modifiers unless an expression begins there (EXPR_BEG, after a label or after class: parse_ident), so also after return, break, next and rescue (EXPR_MID). The grammar closes with end what begin, case, class, def, do, for, if, module, unless, until and while open when they are no modifiers, except a method defined with = after its name or its parameters (endless def); the do after the condition of while, until and for belongs to the loop (keyword_do_cond, COND_P, which ( [ { reset); ( [ { are closed by ) ] }. parse_ident: a lower-case name lexes as a local variable (EXPR_END) when one of that name was assigned before (lvar_defined) and as a method call otherwise, so %, /, <<, ? and : after such a name and a space can be read two ways. parse_numeric: 0x, 0b, 0o and 0d prefixes, a leading 0 alone means octal (010 is 8), single underscores between digits, a fraction and an exponent only before a digit, and the suffixes r and i only when no letter, digit or _ follows (number_literal_suffix), so the number of 1end and 1do ends before the keyword. Prism, the default parser of Ruby 3.4, ends the script, reads __END__, \r\n, numbers, keywords and heredoc identifiers and terminators the same way (prism/prism.c at the same tag); where it reads otherwise, extra.rubyParsers says. ↗
  • extra.rubyParsers: NEWS for Ruby 3.4.0: "The default parser is now Prism. To use the conventional parser, use the command-line argument `--parser=parse.y`" [Feature #20564]; Ruby 3.3 has parse.y as the default and --parser=prism "for debugging only" (NEWS.md at v3_3_0), and Ruby 4.0 still sets RB_DEFAULT_PARSER_PRISM (iseq.c at v4.0.9). eval_make_iseq in vm_eval.c compiles a string to eval with Prism when it is the default (rb_ruby_prism_p), so the instance_eval that runs the Gemfile uses it too. Where the two read the same text differently (prism/prism.c and parse.y at v3_4_7; prism.c at v4.0.9 the same): lex_question_mark reads ? before a character that is not a letter or digit of Unicode (alnum_char) as a character literal even when an identifier character follows, where parse_qmark reads a ternary for any character beyond ASCII before an identifier character (?€or is a ternary for parse.y, ?€ and the name or for Prism), and with an encoding magic comment the two count the bytes of such a character differently; =begin starts a comment for Prism only before whitespace or NUL, for parse.y also before ^D and ^Z (word_match_p); $0 followed by identifier characters is one global name for parse.y and an error for Prism 3.4 (lex_global_variable). ↗
  • extra.lineContinuation: NEWS for Ruby 4.0.0: "Logical binary operators (`||`, `&&`, `and` and `or`) at the beginning of a line continue the previous line, like fluent dot" [Feature #20925]. parse.y (leading_logical; and and or only as whole words, peek_word_at) and prism/prism.c (PM_OPTIONS_VERSION_CRUBY_4_0) at v4.0.9 look for them where they look for a leading . or &.: after the newline that ends a statement, past spaces and comment lines, not past a blank line; .. there is a range, no call. So in Ruby 4.0 source "https://rubygems.org", cooldown: 7 followed by a line && 0 gives the source cooldown: 0; Ruby 3.4 reports a syntax error for such a line. ↗
  • extra.stringToInteger: String#to_i (rb_str_to_inum, base 10) calls rb_int_parse_cstr with RB_INT_PARSE_DEFAULT: it skips leading whitespace (ISSPACE), takes one + or -, skips a 0d or 0D prefix, then reads decimal digits with single underscores between them and stops at anything else (a second underscore, a letter, a dot, a quote); with no digit the result is 0. So "0x10", "0o14", "true", "~" and "[0]" read as 0, "1e3" and "1e400" as 1, "0d14" and "1_4" as 14. ↗
  • extra.configFormat: Settings#load_config reads .bundle/config with Gem::YAMLSerializer.load (Settings#serializer_class in lib/bundler/settings.rb; Bundler's own lib/bundler/yaml_serializer.rb is the same), a line reader, not YAML. HASH_REGEX takes as the key the text before the last colon that is followed by whitespace or the end of the line and comes before the first #, and as the value the rest after one optional space, without its quotes only when it starts and ends with the same quote; strip_comment then cuts the value at its first # and strips it, unless the value starts with #. A key with an empty value starts a nested map, the number of leading spaces / 2 is the depth, a later line of a key replaces an earlier one, and [] is an empty list. load_config replaces . in keys with __, so only a key spelled exactly BUNDLE_COOLDOWN at the top level is the setting; Settings#converted_value reads its text with to_i (extra.stringToInteger), and a map or a list there makes Bundler stop with an error. ↗
  • extra.cliCommands: The commands of Bundler::CLI (desc) and Thor's help, with COMMAND_ALIASES (map aliases_for: i for install, package and pack for cache) and Thor's HELP_MAPPINGS. Thor (lib/bundler/vendor/thor/lib/thor.rb) reads the first argument as the command: normalize_command_name takes a command or alias, or an unambiguous prefix of one (find_command_possibilities: bundle inst, bundle upd); a first argument that starts with - and is no alias is no command name (retrieve_command_name), and with no command name normalize_command_name runs default_command, which is the default_cli_command setting or install, with every argument parsed as its options: a bare bundle installs, and so does bundle --cooldown 0. The commands desc declares with hide: true (cli_help, install_or_cli_help, viz, inject) are Thor::HiddenCommand, which find_command_possibilities leaves out, so no prefix names them; a name that matches no command, alias or prefix is read with - as _ (normalize_command_name: meth.to_s.tr("-", "_")) and runs the command of exactly that name, a hidden one too: bundle install_or_cli_help and bundle install-or-cli-help run install ("Deprecated alias of install", invoke_other_command("install")). ↗
  • extra.versionSelector: The executables RubyGems writes for a gem (Gem::Installer#app_script_text) take a first argument _VERSION_ when Gem::Version.correct? accepts VERSION (ANCHORED_VERSION_PATTERN in lib/rubygems/version.rb), activate that version and drop the argument; for bundler they also set ENV["BUNDLER_VERSION"] to it, so bundle _4.0.12_ install runs Bundler 4.0.12 and does not switch to the version of BUNDLED WITH. ↗
  • extra.rubygemsSource: "At the top of the Gemfile, add a single line for the RubyGems source": source "https://rubygems.org" ("GLOBAL SOURCE"); bundle init writes the same line (lib/bundler/templates/Gemfile). A source call with a block (source "…" do … end) declares a source for the gems in the block only. ↗
  • extra.cooldownWithLockfile: "Preserve per-source cooldown when converging sources from the lockfile" (#9601) under 4.0.14 / 2026-06-10. The test "applies per-source Gemfile cooldown on bundle update when a lockfile exists" (spec/install/cooldown_spec.rb) says: "Converging the Gemfile sources with the lockfile sources used to drop the per-source cooldown, so it only ever worked on a first resolve without a lockfile." SourceList#replace_rubygems_source carries remote_cooldowns over since then (lib/bundler/source_list.rb, missing at bundler-v4.0.13). The cooldown setting and --cooldown work from 4.0.13. ↗
  • extra.cooldownSetting: cooldown (BUNDLE_COOLDOWN): "Number of days a published gem version must age before bundler will resolve to it"; "The CLI flag and this setting apply uniformly to every source, including ones declared with their own cooldown: value." Bundler reads settings from the local config (<project_root>/.bundle/config or $BUNDLE_APP_CONFIG/config), then the environment, then the global config (~/.bundle/config); BUNDLE_IGNORE_CONFIG ignores the files. Remote#effective_cooldown takes the setting when it is set and the keyword of the source otherwise (lib/bundler/source/rubygems/remote.rb). ↗
  • extra.cooldownSettingValues: cooldown is one of NUMBER_KEYS, so Settings#converted_value reads its value with String#to_i: "7 days" is 7, and a value that does not start with a digit, the empty one included, is 0, which turns the cooldown off (the resolver skips 0 and less); "false" is read as false, which counts as unset, so the keyword of the source applies. Values are not checked when they are set (lib/bundler/settings/validator.rb has no rule for cooldown). ↗
  • extra.lockedVersions: Resolver#locked_by_lockfile?: "A version already written to the lockfile has been adopted, and cooldown only governs the adoption of new versions", except for the gems named on bundle update GEM or bundle lock --update GEM. bundle install with an existing Gemfile.lock installs the locked versions, a gem added to the Gemfile since then is resolved with the cooldown, and a frozen install reads the lockfile without resolving (the tests "bypasses cooldown when bundle install uses an existing lockfile", "applies per-source Gemfile cooldown to gems added after the lockfile was written" and "ignores cooldown and installs the locked version when frozen" in spec/install/cooldown_spec.rb). The blog post: "an existing Gemfile.lock is always honored as-is". ↗
  • extra.missingTimestamp: The cooldown "depends on the gem server providing a per-version created_at timestamp in the v2 compact-index format. Versions without that metadata - older gem servers, historical entries that predate the v2 cutover on rubygems.org, or private registries that still emit the v1 format - are treated as outside the cooldown window and remain resolvable." The test "cannot apply cooldown and installs the latest version" (spec/install/cooldown_spec.rb) shows the same for the dependency API. ↗
  • extra.allTooNew: Resolver#cooldown_hint adds "N versions excluded by the cooldown setting; pass `--cooldown 0` to bypass" to the error when the cooldown leaves no version that fits; Bundler stops instead of taking a newer version (test "surfaces a cooldown hint when bundle update filters every candidate"). ↗
  • extra.olderVersions: Dsl#source of 4.0.12 reads only the type option of source and drops the others without a word, as does that of 2.7.2 (https://github.com/ruby/rubygems/blob/bundler-v2.7.2/bundler/lib/bundler/dsl.rb), so a Gemfile with cooldown: works there and has no delay. ↗
  • extra.lockfileVersion: Gemfile.lock ends with BUNDLED WITH and the version of the Bundler that wrote it (LockfileGenerator, LockfileParser::BUNDLED). bundle install installs that version and restarts with it, and the other commands restart with it when it is installed (SelfManager#install_locked_bundler_and_restart_with_it_if_needed and #restart_with_locked_bundler_if_needed), unless BUNDLER_VERSION is set or the version setting is system (its default is lockfile, bundle-config(1)). bundle update --bundler[=VERSION] changes the locked version ("With no argument, update to the latest released version", bundle-update(1)). ↗
  • extra.resolveCommands: The gem installs the executables bundle and bundler (s.executables in bundler.gemspec). bundle install, update, lock (bundle-lock(1)), add (which runs bundle install) and cache resolve the Gemfile and take --cooldown (cli.rb); bundle outdated only reads versions. Aliases, prefixes and a bare bundle are read as Bundler reads them (extra.cliCommands), and so is a first argument _VERSION_ (extra.versionSelector). ↗
  • extra.gemInstall: gem install bundler -v 4.0.23 (or --version, Gem::VersionOption#add_version_option in lib/rubygems/version_option.rb) and gem install bundler:4.0.23 (Gem::Command#extract_gem_name_and_version) install that Bundler. The options are read with Gem::OptionParser, so the value may also be attached: -v4.0.23 and --version=4.0.23. ↗
  • extra.configLocal: bundle config set --local writes <project_root>/.bundle/config, which also holds machine paths such as path (bundle-config(1)); the .gitignore that bundle gem writes for a new gem ignores /.bundle/. ↗
  • extra.configCommand: bundle config set [--local|--global] NAME VALUE (bundle-config(1)): set "defaults to setting local configuration if executing from within a local application, otherwise it will set global configuration"; --local writes <project_root>/.bundle/config (or $BUNDLE_APP_CONFIG/config), --global ~/.bundle/config. CLI::Config#set joins the value words with spaces (value_.unshift(value), then join(" ")), and the hidden base command still runs bundle config NAME VALUE (two arguments, or one with --local or --global) as set, with a deprecation warning. Settings#set_key stores the key as key_for gives it (lib/bundler/settings.rb: dots to __, dashes to ___, upper case, BUNDLE_ in front), so cooldown in any case is BUNDLE_COOLDOWN. Both files replace the cooldown: of every Gemfile source (extra.cooldownSetting), so a 0 written there turns the delay off for the later bundle commands on that machine. ↗
  • extra.updateCommand: --cooldown 0 disables the cooldown "for this run, overriding any per-source or global configuration. Combine with --conservative to minimize transitive churn when bypassing cooldown for an urgent update." ↗
  • extra.dependencySources: Of the kinds of sources a policy names, a Gemfile can declare git sources (GIT, GITHUB and the other git sources) and path sources (PATH), with no setting that forbids them; it has no source for an archive URL or a local archive. ↗

Renovate

  • cooldown.setting: Formerly stabilityDays; old configs are migrated to "N days". Can be scoped with packageRules, vulnerabilityAlerts and update types. ↗
  • cooldown.configFiles: Searched in this order, and the first file that exists is the configuration (configFileNames in lib/config/app-strings.ts). The list is the same on every platform: detectConfigFile calls getConfigFileNames() without a platform, so a .gitlab/renovate.json counts in a GitHub repository and a .github/renovate.json on GitLab; only the validation of onboardingConfigFileName filters the names by platform (getPossibleConfigFileNames in lib/config/validation.ts). The "renovate" key in package.json still works but is deprecated. Shared presets (extends) can also set it. ↗
  • cooldown.cliFlag: Self-hosted CLI only; environment variable RENOVATE_MINIMUM_RELEASE_AGE. ↗
  • cooldown.unit: For example "3 days" or "14 days". Since 42.19.5 "0 days" is treated like null. ↗
  • cooldown.availableSince: Earlier versions had the same feature as stabilityDays (first version not tracked). ↗
  • cooldown.default: Off unless configured; the docs table shows no default. config:best-practices adds "3 days" for npm (see presets). Since 44.96.0 minimumReleaseAgeBuffer adds 30 minutes once a delay is set. ↗
  • cooldown.exclude.setting: No dedicated exclusion list. ↗
  • cooldown.exclude.patternSyntax: Glob and regex patterns since 38.0.0. ↗
  • cooldown.securityUpdates: The vulnerabilityAlerts defaults set minimumReleaseAge to null; a delay can still be set inside vulnerabilityAlerts. ↗
  • installScripts.defaultPolicy: Renovate disables package manager scripts when it updates lockfiles; the Mend-hosted app never runs them. ↗
  • installScripts.disableAll: The default; the self-hosted global allowScripts also defaults to false. ↗
  • extra.configLocation: detectConfigFile looks for each name in configFiles (lib/config/app-strings.ts) in the file list of the repository, whose paths start at the repository root, so a renovate.json in a subdirectory is never read. The configuration options page (docs/usage/configuration-options.md at 44.198.2): "Any config you define applies to the whole repository (e.g. if you have a monorepo)" and "Renovate always uses the config from the repository's default branch". ↗
  • extra.durationStrings: Values such as "3 days" or "1 hour", parsed by toMs (lib/util/pretty-time.ts). ↗
  • extra.minimumReleaseAgePresets: security:minimumReleaseAgeNpm is built by buildMinimumReleaseAgePreset: a packageRules entry { internalChecksFilter: "strict", matchDatasources: ["npm"], minimumReleaseAge: "3 days" }, then entries with the same matchDatasources that set minimumReleaseAge: null for the update types without release timestamps (lockFileMaintenance, replacement, pin, and bump, lockfileUpdate and rollback). config:best-practices extends it (config.preset.ts in the same directory). ↗
  • extra.excludeRule: The documented opt-out: a packageRules entry with matchPackageNames and minimumReleaseAge: null. ↗
  • extra.securityUpdatesSetting: The vulnerabilityAlerts default sets minimumReleaseAge to null, so security updates skip the delay unless a value is set there. ↗
  • extra.excludeWildcards: matchPackageNames accepts globs (and regex) since 38.0.0. ↗
  • extra.ruleDescription: A human-readable description allowed inside any configuration object; depcurfew uses it to recognize the packageRules entry it manages. ↗
  • extra.packageJsonConfig: Deprecated: the configuration options page warns that support may be removed, and Renovate logs that using package.json is deprecated. ↗
  • extra.durationUnits: Units shown in the docs: minimumReleaseAge=1 hour on this page and "3 days" in the configuration options. The value is parsed by toMs (lib/util/pretty-time.ts), whose tests also accept 1 day, 1 week and combined values. ↗
  • extra.datasources: Datasource ids for matchDatasources: npm packages come from the npm datasource and Python packages from pypi, whose release timestamp is the earliest upload_time of the version's files. Composer packages come from packagist, the datasource of the composer manager (static readonly id = 'packagist' in lib/modules/datasource/packagist/index.ts and supportedDatasources in lib/modules/manager/composer/index.ts at 44.199.2, read 2026-11-02). Ruby gems come from rubygems (static readonly id = 'rubygems' in lib/modules/datasource/rubygems/index.ts at 44.198.2, one of the supportedDatasources of the bundler manager), which has releaseTimestampSupport: "The release timestamp is determined from the `created_at` field in the results" (read 2026-11-03). ↗
  • extra.packagistReleaseTime: The release timestamp of a Composer version is composerRelease['published-time'] ?? composerRelease.time: Packagist's publication date, the author-set time only when it is missing. The releaseTimestampNote of lib/modules/datasource/packagist/index.ts at the same tag still says "determined from the time field". ↗
  • extra.negativeMatch: Patterns starting with ! are negative matches, and none of them may match; matchDatasources is matched this way (matchRegexOrGlobList in lib/util/package-rules/datasources.ts at 44.198.0), so ["!pypi"] covers every datasource but PyPI. ↗
  • extra.packageRuleMatching: A packageRules entry applies to a dependency when all of its matchers match. Within one matcher, at least one positive pattern must match when there are any, and no negative pattern (starting with !) may match, so a list of only negative patterns matches every name it does not exclude (docs/usage/string-pattern-matching.md and matchRegexOrGlobList in lib/util/string-match.ts). matchPackageNames, matchDepNames, matchDatasources and matchUpdateTypes all match this way; "*" alone matches everything. ↗
  • extra.packageRulesOrder: resolveConfigPresets merges the presets of extends from left to right and then the configuration itself on top with mergeChildConfig, which for packageRules (mergeable, type array in lib/config/options/index.ts) concatenates the parent's list with the child's (lib/config/utils.ts): the rules of presets come first and the repository's rules after them. applyPackageRules (lib/util/package-rules/index.ts) goes through the list in order and merges every matching rule over the configuration so far ("Package rule config overrides any existing config"), so a later rule wins, and a matching rule wins over the top-level configuration. A top-level option of the repository replaces the same option of a preset (mergeChildConfig takes the child's value for an option that is not mergeable). Read at 44.209.0. ↗
  • extra.delayedUpdateTypes: The update types that take minimumReleaseAge into account; digest and pinDigest only for some datasources, and pin, lockFileMaintenance, lockfileUpdate, rollback, bump and replacement not at all. The table is kept in sync with the null rules of the security:minimumReleaseAge* presets (security.preset.ts), so a rule with matchUpdateTypes of these three leaves those rules as they are. ↗
  • extra.internalPresets: The built-in preset groups; a default preset is written :name or default:name. Other presets (github>, gitlab>, local>, npm packages and so on) are fetched from elsewhere. Among the built-in presets only the security:minimumReleaseAge* presets set minimumReleaseAge, each in a packageRules entry with matchDatasources for its datasource, and config:best-practices extends security:minimumReleaseAgeNpm (security.preset.ts and config.preset.ts in the same directory). ↗
  • extra.pypiPresets: Added in 44.8.0; the same rules as security:minimumReleaseAgeNpm with matchDatasources ["pypi"] (buildMinimumReleaseAgePreset). config:best-practices does not include it (it includes only security:minimumReleaseAgeNpm, config.preset.ts). ↗
  • extra.pythonManagers: pep621 updates pyproject.toml with uv.lock (there is no uv manager) or pdm.lock; poetry updates pyproject.toml with poetry.lock; pipenv updates the Pipfile with Pipfile.lock; pip_requirements updates requirements files. pip-compile is off by default (lib/modules/manager/pep621/readme.md and pipenv/index.ts at 44.198.1). ↗
  • extra.managers: The Renovate manager that updates the packages of each tool, by its id in api.ts; github-actions updates the actions the workflows run. The npm manager reads package.json with package-lock.json, pnpm-lock.yaml or yarn.lock (lockFileNames in npm/index.ts). bun and deno have managers of their own that take a package.json over from npm (supersedesManagers in bun/index.ts and deno/index.ts, applied by lib/workers/repository/extract/supersedes.ts), and poetry takes pyproject.toml over from pep621, which updates it for uv and PDM. composer updates composer.json (composer/index.ts), and bundler the Gemfile with Gemfile.lock (managerFilePatterns /(^|/)Gemfile$/ and lockFileNames in bundler/index.ts, so not gems.rb); bundler was read on 2026-11-03. ↗
  • extra.managerCategories: getManagerConfig gives each dependency the categories its manager exports (categories in lib/modules/manager/<id>/index.ts; the list of categories is lib/constants/category.ts), and matchCategories matches them. bundler exports the category ruby (read 2026-11-03). ↗
  • extra.botOnlyEcosystems: The Renovate manager of each ecosystem depcurfew delays only through the bots (decision D-151), by its id in api.ts, with the datasource it gives the packages and its categories (categories in lib/modules/manager/<id>/index.ts, all in lib/constants/category.ts): cargo updates Cargo.toml (managerFilePatterns, lockFileNames Cargo.lock) from the crate datasource (lib/modules/manager/cargo/schema.ts) in the rust category; gomod updates go.mod from the go datasource (line-parser.ts) in golang; maven updates pom.xml and gradle the .gradle(.kts) files, gradle.properties and the version catalogs in gradle/, both from the maven datasource, in java; nuget updates .csproj, .fsproj, .vbproj, .props and .targets files, dotnet-tools.json and global.json from the nuget datasource in dotnet. getManagerConfig (lib/config/index.ts) starts every manager from the whole configuration, so the top-level minimumReleaseAge applies to them as to the other managers. All four datasources have releaseTimestampSupport: crate takes pubtime of the crates.io index or created_at of the crates.io API, go the Time of the module proxy (or a later GitHub release or tag of a module on GitHub), maven the Last-Modified header, nuget the published date (index.ts of each datasource). ↗
  • extra.cratePresets: security:minimumReleaseAgeCrate sets minimumReleaseAge "3 days" (with internalChecksFilter "strict") in a packageRules entry with matchDatasources ["crate"], and turns it off for lockFileMaintenance, replacement, pin, bump, lockfileUpdate and rollback updates of that datasource. Added in 44.5.0 ("presets: add security:minimumReleaseAgeCrate preset", https://github.com/renovatebot/renovate/releases/tag/44.5.0); config:best-practices does not include it. ↗
  • extra.managerMatching: matchManagers matches the manager id of a dependency like matchRegexOrGlobList (case-insensitive globs, /regex/ and ! for "not"), a custom manager as custom.<name>; matchCategories matches when any category of the dependency matches (anyMatchRegexOrGlobList in lib/util/package-rules/categories.ts). The configuration options page says matchCategories uses "any" logic and is applied after extraction (docs/usage/configuration-options.md). These two, matchPackageNames, matchDepNames, matchDatasources and matchUpdateTypes all have allowString in lib/config/options/index.ts, and massageConfig (lib/config/massage.ts) turns such a string into a list of one. ↗
  • extra.githubActions: An action pinned to a ref that looks like a version (v4, v4.2.0, also as a comment after a commit SHA) is looked up in the github-tags datasource, which gives major, minor and patch updates; another ref (main, a feature tag) goes to github-digest, which gives digest updates only (readme.md in the same directory). getManagerConfig (lib/config/index.ts) starts every manager from the whole configuration, so the top-level minimumReleaseAge applies to github-actions as to the other managers; no built-in preset sets a delay for it (lib/config/presets/internal/security.preset.ts). ↗
  • extra.actionsMatching: matchFileNames matches the packageFile of a dependency, the path of the file from the repository root (and its lockFiles, which the github-actions manager does not set: "Deliberately no lockFiles" in lib/modules/manager/github-actions/extract.ts), like matchRegexOrGlobList; a glob goes to minimatch with { dot: true, nocase: true } (getRegexOrGlobPredicate in lib/util/string-match.ts), so * stays within one directory and ** spans directories. matchFileNames takes no string for a list (no allowString in lib/config/options/index.ts); matchDepTypes does (allowString) and matches the depType like matchRegexOrGlobList (lib/util/package-rules/dep-types.ts). The github-actions manager gives the depType action to a repository action in a uses: field (actions/checkout@v4), and workflow, docker, container, service, github-runner and uses-with to the other things it updates (lib/modules/manager/github-actions/dep-types.ts, extract.ts). ↗
  • extra.actionsTimestamps: github-tags reads committedDate of the commit a lightweight tag points to, or tagger.date of an annotated tag, and takes the publishedAt of a GitHub release of the same version when it is newer (lib/modules/datasource/github-tags/index.ts); github-digest takes the commit date (lib/modules/datasource/github-digest/index.ts). Both are dates from git that the person who makes the commit or the tag sets: the minimum release age page (docs/usage/key-concepts/minimum-release-age.md) says github-tags "uses the committedDate, which is separate from when it was pushed", and that a digest update of a tag moved to new commits ages against the original release date, so it may pass at once. Since 42.0.0 an update without a timestamp waits (missingTimestamp). ↗
  • extra.passesDelayToManager: Since 44.34.0 Renovate passes POETRY_SOLVER_MIN_RELEASE_AGE (rounded up to whole days) to Poetry 2.4.0 and later. It does not pass the delay to uv or read exclude-newer. ↗
  • extra.missingTimestamp: minimumReleaseAgeBehaviour was added in 41.150.0; timestamp-optional still fails open. ↗
  • extra.independentOfPackageManager: Source code passes --before to npm only; pnpm, Yarn and Bun gates are not read. ↗

Dependabot

  • cooldown.setting: Per updates entry: default-days, semver-major-days, semver-minor-days, semver-patch-days, include, exclude. The semver-* keys apply only to SemVer ecosystems. ↗
  • cooldown.configFiles: On the default branch. ↗
  • cooldown.unit: Integer days; the allowed range is disputed (see dayRange). ↗
  • cooldown.availableSince: GA date on github.com; NuGet and Helm since 2025-07-29. ↗
  • cooldown.default: Version updates wait 3 days even without a cooldown block (GHES from 3.23); default-days is also 3 when cooldown is set without it. ↗
  • cooldown.securityUpdates: Cooldown exists only for version updates. dependabot-core also passes a zero age to npm, pnpm and Yarn for security updates, overriding repository gates. ↗
  • installScripts.allowList.setting: insecure-external-code-execution: allow exists only for bundler, mix and pip; nothing allows npm, pnpm, Yarn or Bun scripts. ↗
  • extra.configLocation: "You must store this file in the .github directory of your repository in the default branch (typically main), at .github/dependabot.yml or .github/dependabot.yaml" (github/docs, content/code-security/concepts/supply-chain-security/about-the-dependabot-yml-file.md, read 2026-11-01), so a .github/dependabot.yml in a subdirectory is not read. ↗
  • extra.directories: Required in each updates entry: directory for one directory of manifests, directories for a list; "Define directories relative to the root of the repository for most package managers"; "The directories key supports globbing and the wildcard character *. These features are not supported by the directory key." How a glob matches is not described further (github/docs, content/code-security/reference/supply-chain-security/dependabot-options-reference.md, read 2026-11-01). ↗
  • extra.cooldownKeys: Keys inside the cooldown block of an updates entry; the semver-* keys override default-days for that kind of update. ↗
  • extra.excludeWildcards: cooldown.exclude accepts * wildcards. ↗
  • extra.excludeMatching: ReleaseCooldownOptions#excluded? at v0.402.0 skips the cooldown for a dependency when any exclude pattern matches its name with File.fnmatch?(pattern, dependency_name), and included? matches include the same way, both without flags. Without File::FNM_PATHNAME a * matches / as well ("File.fnmatch('c*t', 'c/a/b/t') #=> true" in the documentation of File.fnmatch, dir.rb of Ruby 3.4.7, https://github.com/ruby/ruby/blob/v3_4_7/dir.rb), and without File::FNM_CASEFOLD case counts, so "*/*" matches every Composer package (vendor/name) and every scoped npm package. ↗
  • extra.cooldownInclude: An include list in the cooldown block limits the cooldown to the dependencies it names (* wildcards, up to 150 entries): the example applies the cooldown to requests, numpy and names starting with pandas or django, and to cover all dependencies one omits include or uses "*". The other dependencies get no cooldown at all, not even the default 3 days: dependabot-core skips the cooldown for a dependency that the include list does not match (ReleaseCooldownOptions#included? with File.fnmatch? and CooldownCalculation.skip_cooldown? in common/lib/dependabot, commit 03892a3e8ee26d43eb96f31c5136c98a85d63b14). exclude wins over include. ↗
  • extra.ecosystems: The npm ecosystem covers npm, pnpm and Yarn; bun needs Bun 1.1.39 or later and deno needs Deno 2. pip covers pip, pip-compile, pipenv and Poetry (v2); uv has its own ecosystem (the table lists uv v0.11). composer covers Composer v2, bundler Bundler (the table lists v2; dependabot-core v0.403.0 also builds a helper with Bundler ~> 4.0, bundler/helpers/v4/build). Cooldown, including the semver-* keys, is supported for all of them (the cooldown table of the same page lists Composer and Bundler with default and SemVer-bump days, read 2026-11-02 and, for Bundler, 2026-11-03). PDM is not listed: dependabot-core skips the dependencies of pyproject.toml when pdm.lock exists (python/lib/dependabot/python/file_parser/pyproject_files_parser.rb at v0.402.0). ↗
  • extra.yamlAliases: Dependabot::Config::File.parse loads dependabot.yml with YAML.safe_load(config, symbolize_names: true); Psych.safe_load takes aliases: false unless told otherwise and raises Psych::AliasesNotEnabled on an alias (*name), so a file with one is not read. The issue that asks for aliases (https://github.com/dependabot/dependabot-core/issues/1582, "YAML aliases", open and labelled Keep on 2026-11-02) quotes the error users get, "YAML aliases are not supported"; the pull request that would allow them (#9653) is open and not merged. The reference of dependabot.yml (dependabot-options-reference.md in github/docs) does not mention anchors or aliases. An anchor (&name) that no alias refers to changes nothing. ↗
  • extra.yamlScalars: Dependabot::Config::File.parse loads dependabot.yml with YAML.safe_load (dependabot-core v0.402.0, common/lib/dependabot/config/file.rb), which is Psych: Ruby 4.0.5 (.ruby-version) with psych 5.5.0 (Gemfile.lock of dependabot-core at v0.402.0). ScalarScanner#tokenize reads a plain scalar in this order: words, where a word of up to five characters is null when it is ~ or null and a boolean when it is yes, true or on (true) or no, false or off (false), all in any case (BOOLEAN_TRUE and BOOLEAN_FALSE of the default libyaml backend, the YAML 1.1 set; only the experimental libfyaml backend takes true and false alone), and the empty scalar is nil; times and dates; .inf and .nan; :symbols; base 60 integers [-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}, summed as part * 60 ** (index - 2).abs, so 1:30 is 5400; floats with a dot; then INTEGER_LEGACY, the default without strict_integer: 0b binary, 0 followed by octal digits, decimal without a leading zero, 0x hex, each with _ and , allowed, read with Integer(string.delete(',_')), so 010 is 8, 1_0 and 1,0 are 10; anything else, 0o12 and 08 too, is a string. ↗
  • extra.githubActions: package-ecosystem github-actions updates the actions the workflows run: with directory / Dependabot "will search the /.github/workflows directory, as well as the action.yml/action.yaml file from the root directory". The cooldown table lists GitHub Actions with default-days supported and the semver-major-days, semver-minor-days and semver-patch-days keys not supported, and the default cooldown of 3 days covers version updates without a cooldown block (github/docs, content/code-security/reference/supply-chain-security/dependabot-options-reference.md, main on 2026-11-02). ↗
  • extra.botOnlyEcosystems: The package-ecosystem values of the ecosystems depcurfew delays only through the bots (decision D-151): cargo (Cargo v1), gomod (Go modules v1), maven, gradle and nuget (NuGet <=6.12.0), from the package-ecosystem table of the same page. The cooldown table lists Cargo, Gomod (Go Modules), Gradle, Maven and NuGet with default-days and the SemVer-bump days (semver-major-days, semver-minor-days, semver-patch-days) supported, and the default cooldown of 3 days covers their version updates without a cooldown block (github/docs, content/code-security/reference/supply-chain-security/dependabot-options-reference.md, main on 2026-11-03). ↗
  • extra.maximumDays: The page says the number of cooldown days must be between 1 and 90; whether 0 is accepted is disputed (see dayRange). ↗
  • extra.composerReleaseTime: For composer, the cooldown compares the release date with released_at, which parse_release takes from the time field of each version in the Packagist metadata: the date the package author sets, not published-time, the date Packagist received the version. Seen on 2026-11-02: intercom/intercom-php 5.0.2 has time 2026-01-30 and published-time 2026-04-30 (repo.packagist.org/p2/intercom/intercom-php.json). The updater runs Composer 2.10.3 (ARG COMPOSER_V2_VERSION in composer/Dockerfile at v0.402.0), which has no cooldown policy of its own. ↗
  • extra.composerContentHash: post_process_lockfile calls replace_content_hash, which writes the hash get_content_hash returns: composer/helpers/v2/src/Hasher.php calls Locker::getContentHash of the composer/composer library the helper installs from its composer.lock (2.10.3 at v0.402.0). That method at 2.10.3 does not hash config.policy (src/Composer/Package/Locker.php at 2.10.3), while Composer 2.11 does, so with config.policy in composer.json every composer.lock Dependabot writes has a content-hash Composer 2.11 reads as out of date: composer install warns and composer validate fails until composer update --lock. ↗

Environment

  • botOnlyEcosystems.cargo.project: "Cargo.toml is about describing your dependencies in a broad sense" (the manifest) and "Cargo.lock contains exact information about your dependencies" (the Cargo book of Cargo 1.99, guide/cargo-toml-vs-cargo-lock.md). ↗
  • botOnlyEcosystems.gomod.project: The Go Modules Reference (go.dev/ref/mod): "A module is defined by a UTF-8 encoded text file named go.mod in its root directory" and "A module may have a text file named go.sum in its root directory, alongside its go.mod file" with the hashes of its dependencies (read on 2026-11-03). ↗
  • botOnlyEcosystems.maven.project: Introduction to the POM: "A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project", with the project dependencies; "When executing a task or goal, Maven looks for the POM in the current directory", and the examples name it pom.xml, also in modules (my-module/pom.xml). ↗
  • botOnlyEcosystems.gradle.project: The Gradle 9.8.2 user guide shows a project with settings.gradle(.kts) in the root directory ("lets Gradle know about the structure of the build") and build.gradle(.kts) in each project, "declaring dependencies and applying plugins"; dependencies_intermediate.adoc in the same directory recommends a version catalog in gradle/libs.versions.toml for the dependency versions. ↗
  • botOnlyEcosystems.nuget.project: PackageReference items "specify NuGet package dependencies directly within project files, as opposed to having a separate packages.config file" (packages.config: reference/packages-config.md); Central Package Management keeps the versions in a Directory.Packages.props "at the root of your repository" (consume-packages/Central-Package-Management.md). Project files have extensions "like .csproj for C# projects and .fsproj for F# projects", and dependencies are referenced in "the project file (.csproj or .vbproj)" (docs/core/project-sdk/overview.md and docs/core/tools/dotnet-restore.md in dotnet/docs). NuGet reads nuget.config, NuGet.config and NuGet.Config, in this order (OrderedSettingsFileNames in src/nuget-client/src/NuGet.Core/NuGet.Configuration/Settings/Settings.cs at the v10.0.403 tag of dotnet/dotnet). ↗
  • corepack.packageManagerField: Format name@x.y.z, optionally followed by +<hash algorithm>.<hash>; a URL to a .js or .tgz file is also allowed. setup-bun also reads bun@x from this key. ↗
  • corepack.devEnginesSince: Limited support at first; since 0.36.0 Corepack uses the devEngines.packageManager range when packageManager is missing. ↗
  • corepack.envFileSince: Corepack reads COREPACK_* keys from .corepack.env; since 0.36.0 only the closest file. COREPACK_ENV_FILE=0 turns it off. ↗
  • corepack.bundledWithNode: Node.js 25.0.0 stopped distributing Corepack; the Corepack README says it ships with Node.js from 14.19.0 up to (but not including) 25.0.0. ↗
  • corepack.package: Its published bin field (publishConfig.bin) declares yarn (./dist/yarn.js), yarnpkg, pnpm and pnpx next to corepack. corepack enable links them from the folder of the corepack executable (a relative symlink to dist/<name>.js on Linux and macOS, a cmd-shim on Windows; sources/commands/Enable.ts), so the package.json behind a yarn or pnpm shim is Corepack's, which says nothing about the version the shim runs. ↗
  • corepack.toolPackages: The npm packages Corepack installs each package manager from: npm; pnpm; yarn below 2.0.0 (Yarn Classic) and, with COREPACK_NPM_REGISTRY, @yarnpkg/cli-dist for Yarn 2 and later ("npmRegistry": { "package": "@yarnpkg/cli-dist", "bin": "bin/yarn.js" }). npm i -g @yarnpkg/cli-dist installs the same package, whose package.json declares bin yarn and carries the Yarn version (observed for 4.18.1). ↗
  • corepack.enableNpm: corepack enable [... name] creates shims for the package managers it is given, or for all of them without parameters: "Note that the npm shims will not be installed unless explicitly requested, as npm is currently distributed with Node.js through other means". So corepack enable npm makes npm the version Corepack picks (packageManager), while a bare corepack enable leaves the bundled npm. ↗
  • corepack.manualInstall: How to Install: "Corepack is distributed with Node.js from version 14.19.0 up to (but not including) 25.0.0. Run `corepack enable` to install the required Yarn and pnpm binaries on your path." Manual Installs, "Install Corepack using npm": "npm install -g corepack". The Node.js 25.0.0 changelog lists "build: stop distributing Corepack" (#57617) among its semver-major commits (https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V25.md), and the node images of 25 and later extract the release tarball unchanged (docker.nodeImage), so they have no Corepack either. ↗
  • installScriptPackages.esbuild: npm/esbuild/package.json at v0.28.2 declares "postinstall": "node install.js" and one optionalDependencies entry per platform (@esbuild/linux-x64 and the others, version 0.28.2). generateBinPath in lib/npm/node-platform.ts, which the JavaScript API and bin/esbuild run, first resolves the binary from that optional package ("First check for the binary package from our optionalDependencies"), so esbuild works without its install script. lib/npm/node-install.ts (the install script) only replaces bin/esbuild with the binary ("This optimization also doesn't apply when npm's --ignore-scripts flag is used since in that case this install script will not be run"; not on Windows, with Yarn or WASM), checks the version of the binary, and downloads the platform package when it is missing ("This can happen if you use the --no-optional flag"). Without both, esbuild fails: "maybe someone installed esbuild with both the --no-optional and the --ignore-scripts flags. The fix for this is to just not do that", with the error "make sure that you don't specify the --no-optional or --omit=optional flags". ↗
  • installScriptPackages.fsevents: The package.json of fsevents 2.3.3 declares no install script and lists "files": ["fsevents.d.ts", "fsevents.js", "fsevents.node"], so the published package contains the built module that fsevents.js loads (require("./fsevents.node")); the published tarball holds exactly LICENSE, README.md, package.json, fsevents.js, fsevents.d.ts and fsevents.node (listed on 2026-11-02, nothing run). The repository has a binding.gyp at that tag, and npm adds an install script to such a package when it is published: "If there is a binding.gyp file in the root of your package and you haven't defined your own install or preinstall scripts, npm will default the install command to compile using node-gyp via node-gyp rebuild" (https://github.com/npm/cli/blob/v12.2.1/docs/lib/content/using-npm/scripts.md). That is the install: node-gyp rebuild of the registry metadata and the hasInstallScript of lockfiles; the tarball has no binding.gyp to build from. ↗
  • installScriptPackages.lefthook: postinstall.js runs the lefthook executable with install in INIT_CWD (the directory the install was started in), and does nothing when CI is set and LEFTHOOK is not ("if (isEnabled(process.env.CI) && !isEnabled(process.env.LEFTHOOK)) return"). get-exe.js resolves the executable from lefthook-<os>-<arch>/bin/lefthook, one of the optionalDependencies of packaging/registries/npm/lefthook/package.json (version 2.2.2), whose only script is "postinstall": "node postinstall.js". docs/usage/commands/install.md: lefthook install "Installs configured hooks to Git hooks"; "NPM package lefthook installs the hooks in a postinstall script automatically. For projects not using NPM package run lefthook install after cloning the repo." and "Reinstall is not required when you modify lefthook.yml, the configuration file is read every time a git hook is run." docs/usage/envs/LEFTHOOK.md: "When using NPM package lefthook in CI, and your CI sets CI=true automatically, use LEFTHOOK=1 or LEFTHOOK=true to install hooks in the postinstall script", so by default no hooks are installed in CI. postinstall.js catches every error and does not look at the exit code of lefthook install, so it never fails the install. The legacy package @evilmartians/lefthook-installer fetches the executable when it is installed (docs/installation/node.md), so its script is needed; it is not this entry. ↗
  • node.bundledNpm: The npm field of every release in index.json (fetched on 2026-11-01, sha256 6b27fe5766e87929d16ccdde05c516cbdd12200eab62b28d4b2f31d34e21481a), as the first release of each line that bundles each npm version; latest is the newest release of the line that day. Lines are the major version from 4 on and the minor version before (0.6 to 0.12, as Node.js numbered them then). The bundled npm never goes down within a line. Releases before 0.6.3 (0.1.14 to 0.5.10 and 0.6.0 to 0.6.2) have no npm field: they came without npm. Every release before 18.0.0 bundles npm 8.19.4 or earlier (16.20.2 has npm 8.19.4), so none of them has min-release-age, allowScripts or strict-allow-scripts. 27.0.0-alpha.0.0.0 (npm 12.1.0) is a prerelease and left out: no release bundles npm 12 yet, Node.js 22 stays on npm 10.9.x, 24 reaches npm 11.10 or later only from 24.14.1 (npm 11.10.x was skipped) and 25 ends at npm 11.12.1. ↗
  • node.releaseSchedule: start, lts and end of each line from 4 on, codenames in lower case as nvm and the node image tags write them. After end a line gets no more releases, security fixes included; the README says "Production applications should only use Active LTS or Maintenance LTS releases". From Node.js 27 every line first goes through an alpha phase (27 has "alpha": "2026-10-28" and no codename yet) and every line becomes LTS. ↗
  • node.nvmrc: The file must contain precisely one version followed by a newline; # starts a comment, and comments, blank lines and leading and trailing white space are ignored. node is the latest version and stable an alias for it; lts/* is the latest LTS and lts/<codename> the LTS releases of that line; the file may hold "any other string that nvm understands". nvm use looks for the file from the current directory upwards. lts/-n is not in the README but in nvm.sh at the same commit (https://github.com/nvm-sh/nvm/blob/5e38bc0caed342356ffd26eb21e0e9b995ac228b/nvm.sh, read 2026-11-01): nvm_normalize_lts, which nvm_alias calls for every alias (so also for the version of .nvmrc), matches "lts/-[123456789] | lts/-[123456789][0123456789]*", takes N from after the -, adds 1 and picks the N-th last entry of the lts alias directory, whose entries are the LTS codenames (alphabetical, which is release order) after *; so lts/-1 is the LTS line before the newest one, as in setup-node. When nothing matches it says "That many LTS releases do not exist yet." ↗
  • node.nodeVersionFile: nodenv uses the version in .node-version of the project directory. fnm reads .node-version and .nvmrc and writes the file with node --version, so a leading v occurs (github.com/Schniz/fnm/blob/07f13237ae208f531f8ea88d4cfde3160c22f99a/README.md); setup-node reads it through node-version-file. ↗
  • node.engines: engines.node is the range of Node.js versions the package works on. Unless engine-strict is set, it is advisory and only produces warnings when the package is installed as a dependency; it does not choose the Node.js that runs. setup-node reads it from package.json through node-version-file when volta.node and devEngines.runtime are missing, and picks the newest version that matches. ↗
  • node.inheritedVersionFiles: nvm: "nvm use et. al. will traverse directory structure upwards from the current directory looking for the .nvmrc file". nodenv: find_local_version_file in libexec/nodenv-version-file checks the directory for .node-version and then each parent up to the root (https://github.com/nodenv/nodenv/blob/5083e9819756c1a127a626a874703349f4ddb2e4/libexec/nodenv-version-file). asdf: the tool versions a .tool-versions file declares "will be used in that directory and any subdirectories" (https://github.com/asdf-vm/asdf/blob/master/docs/manage/configuration.md). Volta is not one of them: for_dir in crates/volta-core/src/project/mod.rs "will search ancestors to find a package.json and use that as the root of the project" and reads a parent package.json only through extends (https://github.com/volta-cli/volta/blob/main/crates/volta-core/src/project/mod.rs), so the volta key of the root package.json does not reach a project with a package.json of its own. ↗
  • node.environmentProxy: NODE_USE_ENV_PROXY=1 (added in v24.0.0 and v22.21.0, "Stability: 1.1 - Active Development"): "When enabled, Node.js parses the HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables during startup, and routes requests through the specified proxy"; --use-env-proxy does the same and wins over it. doc/api/http.md at the same tag (Built-in Proxy Support, http.setGlobalProxyFromEnv) names fetch() among the requests it covers, and the lower-case spellings win over the upper-case ones. Without it, fetch connects directly, whatever the proxy variables say; Node.js before 22.21.0 has no such switch. ↗
  • docker.imageReference: splitDockerDomain canonicalizes ubuntu and docker.io/ubuntu as docker.io/library/ubuntu, and the legacy domain index.docker.io as docker.io. A reference without a tag means latest (docs/reference/commandline/image_tag.md in github.com/docker/cli at 8c8a77521af82b08bf3499cafb4c0e2e7b024936: "If the namespace is omitted, Docker defaults to library, the namespace reserved for Docker Official Images"). registry-1.docker.io is Docker Hub's registry itself: "DefaultRegistryHost is the hostname for the default (Docker Hub) registry used for pushing and pulling images", DefaultRegistryHost = "registry-1.docker.io" (https://github.com/moby/moby/blob/9aa9edfa787e08bb2da31694cd8a402876f32232/daemon/pkg/registry/config.go), so registry-1.docker.io/library/node is the same official image. ↗
  • docker.syntax: Instructions are not case-sensitive. A line that begins with # is a comment unless it is a parser directive; comment lines are removed also inside a continued instruction. Parser directives (syntax, escape, check; keys not case-sensitive) must come first: after a comment, an empty line or an instruction none is read. The escape character (\ by default, or `) at the end of a line continues the instruction; escaping is not performed in RUN except at the end of a line. ARG is the only instruction allowed before FROM, and FROM reads ARGs declared before the first FROM ($VAR, ${VAR}, ${VAR:-word}, ${VAR-word}, ${VAR:+word}, ${VAR+word}); --build-arg can change them. FROM [--platform=<platform>] <image>[:<tag>][@<digest>] [AS <name>]; a later FROM <name> starts from that stage. A here-document (RUN <<EOF) makes the following lines part of the instruction, up to the line with only the delimiter. Only RUN, COPY and ADD in shell form take here-documents, and only a whole word starts one: the parser splits the line into words with quotes kept (shlex.RawQuotes) and matches each word against ^(\d*)<<(-?)\s*([^<]*)$, so a quoted "a <<b" starts none (heredocsFromLine and reHeredoc in frontend/dockerfile/parser/parser.go at the same commit). ↗
  • docker.copySources: COPY and ADD without --from: "When copying source files from the build context, paths are interpreted as relative to the root of the context. Specifying a source path with a leading slash or one that navigates outside the build context, such as COPY ../something /something, automatically removes any parent directory navigation (../). Trailing slashes in the source path are also disregarded, making COPY something/ /something equivalent to COPY something /something." The ADD section says the same about ADD ../something. So /frontend/x, ../frontend/x and frontend/x are the same file, and frontend/.. is the root of the context. ↗
  • docker.environment: ENV <key>=<value> [<key>=<value>...]: "This value will be in the environment for all subsequent instructions in the build stage", and "A stage inherits any environment variables that were set using ENV by its parent stage or any ancestor". "Like command line parsing, quotes and backslashes can be used to include spaces within values". The alternative "ENV <key> <value>, omitting the =" sets one variable, and is discouraged. RUN commands see these variables, and ENV wins over an ARG of the same name. ↗
  • docker.buildArguments: ARG <name>[=<default value>]: the variable "is also passed to all subsequent RUN instructions as a build-time environment variable"; "If an ARG instruction has a default value and if there is no value passed at build-time, the builder uses the default" (--build-arg can give another). "An ARG variable declared within a build stage is automatically inherited by other stages based on that stage. Unrelated build stages do not have access to the variable." "An ARG declared before a FROM is outside of a build stage, so it can't be used in any instruction after a FROM. To use the default value of an ARG declared before the first FROM use an ARG instruction without a value inside of a build stage." "Environment variables defined using the ENV instruction always override an ARG instruction of the same name." (Using ARG variables; Impact on build caching: "all RUN instructions following an ARG instruction use the ARG variable implicitly (as an environment variable)".) ↗
  • docker.dockerfileNames: "The default filename to use for a Dockerfile is Dockerfile, without a file extension." "A common convention is to name these <something>.Dockerfile", passed with --file. ↗
  • docker.containerfile: "A Containerfile uses the same syntax as a Dockerfile internally"; Buildah and Podman read Containerfile or Dockerfile. Docker does not read Containerfile by default. ↗
  • docker.nodeImage: The image downloads the official tarball of the release and extracts it unchanged; its only npm command is npm --version, and docs/BestPractices.md tells users to add RUN npm install --global npm@<version> to change npm. So node:<version> has exactly the npm that release bundles. The Alpine images extract the -musl tarball or build from source. Tags (stackbrew.js): X.Y.Z, X.Y, X and <codename>, each also with -<variant>, and -alpine and -slim for the default variants; the variants are those of versions.json, plus alpine and slim. Yarn 1 is in the images up to Node.js 25. ↗
  • docker.pythonImage: "our policy is now to use the pip version that is installed during the Python build (which is the version bundled in ensurepip), and to not support overriding it": Dockerfile-linux.template configures CPython --with-ensurepip and installs no other pip (only setuptools and wheel for 3.11). So python:<version> has the pip that CPython release bundles. Images built before 2024-09-07 installed pip with get-pip.py, at the version ensurepip had. Tags (generate-stackbrew-library.sh): X.Y.Z and X.Y, each with -<variant>; -slim and -alpine mean the default suite. ↗
  • devEngines: Each entry is an object or a list of objects with name (required), version and onFail (warn, error by default, or ignore). Corepack and the setup actions read it too. ↗
  • devEnginesSince: npm version that introduced devEngines. ↗
  • volta.manifest: Also extends: a path to another JSON file with a volta key. pnpm support is experimental and needs VOLTA_FEATURE_PNPM=1. ↗
  • volta.maintained: The README says Volta is unmaintained and recommends migrating to mise. ↗
  • asdf.toolVersionsFile: One tool per line followed by one or more versions separated by spaces (fallbacks); # starts a comment. ↗
  • asdf.plugins: Short names in the asdf plugin index; there is no plugin named node. python, uv and poetry checked on 2026-10-30 (danhper/asdf-python, asdf-community/asdf-uv, asdf-community/asdf-poetry). ↗
  • mise.config: Config file locations: in each directory "a file higher in the table overrides one lower down": mise.local.toml (personal overrides, kept out of version control), mise.toml, mise/config.toml, mise/conf.d/*.toml, .mise/config.toml, .config/mise.toml, .config/mise/mise.toml, .config/mise/config.toml, then .tool-versions; ".mise.toml overrides mise.toml". [tools] merges per tool: "The nearest file's entry replaces that tool's whole entry". Requests (dev-tools/versions.md at the same tag): node = "24" is "a 24.x release", python = "3.14.8" exactly that release, a table names the request kind (node = { path = ... }, a version key in the examples of dev-tools/index.md), and python = ["3.14", "3.13"] installs both, "the first one provides the unversioned command". "mise does not accept npm-style ranges such as ^24 or >=20 outside package.json". MISE_NODE_VERSION overrides every file. ↗
  • githubActions.jobId: Read from the page source in github/docs (data/reusables/actions/jobs/section-using-jobs-in-a-workflow-id.md, main on 2026-11-02): "You must replace <job_id> with a string that is unique to the jobs object. The <job_id> must start with a letter or _ and contain only alphanumeric characters, -, or _." The runner checks names the same way with ASCII letters and digits (NameValidation.IsValid in src/Sdk/DTPipelines/Pipelines/Validation/NameValidation.cs of actions/runner, main on 2026-11-02: a-z, A-Z, _ anywhere, digits and, with hyphens allowed, - after the first character). ↗
  • githubActions.setupNode: Current major v7. node-version-file reads package.json, .nvmrc, .node-version, .tool-versions or mise.toml; node-version wins when both are set. ↗
  • githubActions.setupNodeVersions: Tag v7.1.0. node-version takes semver (22, 24.8.0, >=10.15.0, 12.x), the NVM LTS syntax (lts/jod, lts/*, lts/-n) and latest, current, node or * for the latest release. A matching version in the runner's tool cache is used first, so a major version such as 24 may give an older release of the line unless check-latest is set. ↗
  • githubActions.setupNodeVersionFile: node-version-file accepts .nvmrc, .node-version, .tool-versions, mise.toml or package.json, relative to GITHUB_WORKSPACE (docs/advanced-usage.md at the same commit). In package.json it checks volta.node, then the devEngines.runtime entry named node, then engines.node, then volta.extends. getNodeVersionFromFile tries JSON, then parses the file as TOML ("Try parsing the file as a mise `mise.toml` file") and returns tools.node when it is a string, or tools.node.version when it is a table with one, and null for any other tools.node (a list included), then the first line that matches the pattern, then the whole text trimmed. ↗
  • githubActions.jobContainer: Read from the page source in github/docs (data/reusables/actions/jobs/section-running-jobs-in-a-container.md and section-running-jobs-in-a-container-image.md, main on 2026-11-01): "Use jobs.<job_id>.container to create a container to run any steps in a job that don't already specify a container"; "If you do not set a container, all steps will run directly on the host specified by runs-on"; "When you only specify a container image, you can omit the image keyword" (container: node:18); jobs.<job_id>.container.image is "the Docker image to use as the container to run the action", and container.env sets variables in the container. So the run steps of such a job use the Node.js and npm of that image, until a setup step installs another. ↗
  • githubActions.environmentKeys: Read from the page source in github/docs (content/actions/reference/workflows-and-actions/workflow-syntax.md and data/reusables/repositories/actions-env-var-note.md, main on 2026-11-01): env is "A map of variables that are available to the steps of all jobs in the workflow", jobs.<job_id>.env "A map of variables that are available to all steps in the job", and jobs.<job_id>.steps[*].env "Sets variables for steps to use in the runner environment"; for the same name GitHub "uses the most specific variable": the step's over the job's over the workflow's. ↗
  • githubActions.environmentFile: Read from the page source in github/docs (content/actions/reference/workflows-and-actions/workflow-commands.md, commit 9e46fa1 of main on 2026-11-03): echo "{environment_variable_name}={value}" >> "$GITHUB_ENV"; "You can make an environment variable available to any subsequent steps in a workflow job by defining or updating the environment variable and writing this to the GITHUB_ENV environment file. The step that creates or updates the environment variable does not have access to the new value, but all subsequent steps in a job will have access." Multiline values use {name}<<{delimiter}. In actions/runner v2.338.2, SetEnvFileCommand writes each pair into Global.EnvironmentVariables (src/Runner.Worker/FileCommandManager.cs), which holds the env of the workflow and the job, and StepsRunner merges that global env first and the env of the step over it ("Merge global env", then "Evaluate and merge step env" in src/Runner.Worker/StepsRunner.cs), so a value written there replaces the env of the workflow and the job for the later steps, and the env of a step still wins. ↗
  • githubActions.yamlAliases: Read from the page source in github/docs (content/actions/reference/workflows-and-actions/reusing-workflow-configurations.md, commit 23809bf of main on 2026-11-02), for GitHub.com and GitHub Enterprise Cloud: "You can use YAML anchors and aliases to reduce repetition in your workflows. An anchor (marked with &) identifies a piece of content that you want to reuse, while an alias (marked with *) repeats that content in another location." Its examples reuse the env map of a job (env: *env_vars) and a whole job (alt-test: *base_job), and say that this "is equivalent to writing the following YAML without anchors and aliases". The page does not mention merge keys (<<), so depcurfew does not apply them in workflows. ↗
  • githubActions.pnpmActionSetup: Current major v6. Without version the action reads devEngines.packageManager or packageManager from package.json (package_json_file). ↗
  • githubActions.pnpmSetup: For pnpm 11 and later. Without version it reads devEngines.packageManager or packageManager; runtime takes <name>@<version> for node, bun or deno. ↗
  • githubActions.setupBun: Current major v2. Without bun-version it reads packageManager (bun@x), then engines.bun, then installs latest. ↗
  • githubActions.setupDeno: Current major v2. deno-version defaults to 2.x; deno-version-file reads .dvmrc or .tool-versions. ↗
  • githubActions.setupPython: Current version v7.1.0. Without python-version it reads .python-version; python-version wins over python-version-file. pip-version (major[.minor][.patch], CPython only) since v6.0.0. Python comes with pip, but the step alone does not show that pip installs the project. ↗
  • githubActions.setupUv: Current version v10.3.3, with no moving v10 tag. Without version or version-file it reads required-version from uv.toml, then pyproject.toml, in the working directory, and installs the latest uv when neither has one. ↗
  • githubActions.setupPdm: Current version v4.6 (the moving tag v4 is the same commit). version: "The version of PDM to install, or 'head' to install from the main branch"; without it the installer installs the latest PDM. src/setup-pdm.ts passes it as --version to the installer script (cmdArgs.push('--version', pdmVersion)). python-version and python-version-file choose the Python it sets up. ↗
  • githubActions.miseAction: Current version v5.2.6 (the moving tag v5 is the same commit). install (default "true"): "if false, will not run `mise install` or `mise bootstrap`"; mise_toml: "If present, this value will be written to the mise.toml file"; working_directory: "The directory that mise runs in"; add_shims_to_path (default "true") puts the shims of the installed tools on PATH, so the later steps of the job run the Node.js and Python of the mise configuration. ↗
  • githubActions.installPoetry: A third-party action (current v1.4.2); version defaults to latest, so without it the Poetry version is not pinned. ↗
  • githubActions.actionsPoetry: A third-party action (current v4.0.0); poetry-version defaults to latest. ↗
  • githubActions.setupRuby: Current version v1.336.0 (the README uses ruby/setup-ruby@v1). bundler is "The version of Bundler to install. Either 'Gemfile.lock' (the default), 'default', 'latest', 'none', or a version number (e.g., 1, 2, 2.1, 2.1.4)": Gemfile.lock installs the version of BUNDLED WITH (also of gems.locked), default the Bundler the Ruby comes with when it is 2.2 or later, latest the latest compatible one, none nothing. bundler-cache: true runs bundle install and caches the gems, with bundle config --local deployment true when there is a lockfile, and generates the lockfile with bundle lock when there is none (README.md, "Caching bundle install automatically"). ↗
  • githubActions.codeScanningUpload: The example workflow on this page needs security-events: write in every repository and actions: read with contents: read only in private ones. The inputs come from upload-sarif/action.yml in github/codeql-action (current major v4, v4.39.1 checked); category tells analyses of the same tool and commit apart. ↗
  • githubActions.stopCommands: Lines between the two are logged without being processed as workflow commands. The token must be randomly generated and unique for each run. Read from the page source in github/docs. ↗
  • githubActions.annotations: escapeData and escapeProperty in @actions/core: the message and property values replace %, CR and LF; property values also replace : and , because properties are separated by commas. The commands and their file, line and title parameters are on https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-commands (line counts from 1). ↗
  • githubActions.annotationLimits: 10 error, 10 warning and 10 notice annotations per step; 50 annotations per job, summed over all steps. Annotations over the limit are not shown. ↗
  • githubActions.checkRuns: Read from the sources of this page (#create-a-check-run, #update-a-check-run, #list-check-runs-for-a-git-reference), the REST description github/rest-api-description (descriptions/api.github.com/api.github.com.json, commit f9ed74230d54847b5ca00a1343e8e349e858b8fb) and github/docs (commit 33b1f4a6fec2d9b6fd3d374afa56bcd9f0875b57); content/rest/checks/runs.md is generated from the REST description. POST /repos/{owner}/{repo}/check-runs ("Create a check run") needs name and head_sha and takes external_id, "A reference for the run on the integrator's system"; PATCH /repos/{owner}/{repo}/check-runs/{check_run_id} ("Update a check run") takes the same fields but head_sha, with only summary required in output, and "OAuth apps and personal access tokens (classic) cannot use this endpoint"; GET /repos/{owner}/{repo}/commits/{ref}/check-runs ("List check runs for a Git reference", ref a SHA, heads/BRANCH or tags/TAG) takes check_name ("Returns check runs with the specified name"), filter (latest, the default, or all: "latest returns the most recent check runs"), per_page (at most 100) and app_id, and answers {total_count, check_runs}, each with id, name, external_id (nullable), app (with slug, not required) and output.annotations_count. Fine-grained permissions (src/github-apps/data/fpt-2022-11-28/server-to-server-permissions.json in github/docs): the list needs Checks read, update and create need Checks write; "write includes read" (github-token-scope-descriptions.md). output.annotations: "maxItems": 50 per request, "To create more than 50 annotations, you have to make multiple requests to the Update a check run endpoint. Each time you update the check run, annotations are appended"; each annotation requires path, start_line, end_line (lines start at 1), annotation_level (notice, warning or failure) and message ("The maximum size is 64 KB"), with an optional title ("The maximum size is 255 characters"). No total per check run is documented; the same description says "GitHub Actions are limited to 10 warning annotations and 10 error annotations per step" without saying whether that binds check runs created through the API (uncertain). Not documented either: whether only the app that created a run may update it, and the app slug of runs created with the workflow token. A check suite holds the runs of one GitHub App for one commit (using-the-rest-api-to-interact-with-checks.md), and GitHub keeps at most 1000 runs of the same name per suite. status completed needs a conclusion (success, neutral, failure and others); output.title and output.summary (Markdown, maxLength 65535) show in the Checks tab; only GitHub Apps can create check runs, which the workflow token is. checks: write "permits an action to create a check run" (data/reusables/actions/github-token-scope-descriptions.md in github/docs, which links the permissions with apiVersion=2022-11-28); a pull request from a fork gets a read-only token unless the repository sends write tokens to such workflows (workflow-syntax.md, How permissions are calculated). For pull_request, pull_request_review and pull_request_review_comment, GITHUB_SHA is the "Last merge commit on the GITHUB_REF branch" (events-that-trigger-workflows.md), so the check goes on pull_request.head.sha from the payload file GITHUB_EVENT_PATH names; for pull_request_target it is the "Last commit on the PR base branch", which actions/checkout checks out by default, so the check goes on GITHUB_SHA there (GITHUB_EVENT_NAME names the event, variables.md) (webhook-pull-request-opened schema; variables.md for GITHUB_API_URL, GITHUB_REPOSITORY and GITHUB_EVENT_PATH). ↗
  • githubActions.stepSummary: GitHub flavored Markdown appended to the file named by the variable; at most 1 MiB per step (over that the upload fails with an error annotation), and at most 20 step summaries are shown per job. ↗
  • npmRegistry.api: GET /{package} returns the full document by default: dist-tags maps tags to versions (every package has latest), versions maps versions to version objects, time maps every version to its publish time, and a version object carries scripts (from its package.json) and deprecated. The abbreviated document (Accept: application/vnd.npm.install-v1+json) has no time field and adds hasInstallScript. Scoped names are escaped with %2f (escapedName in github.com/npm/npm-package-arg); the registry answered the same document for @types/node and @types%2fnode on 2026-10-29. Install scripts: preinstall, install and postinstall run for a dependency, and npm runs node-gyp rebuild as install when the package has binding.gyp and no install or preinstall script (github.com/npm/cli/blob/v12.2.1/docs/lib/content/using-npm/scripts.md); binding.gyp is not visible in the document. ↗
  • npmRegistry.githubPackagesTarballs: RegistryServerType: "A registry that serves tarballs from a content-derived path (GitHub Packages /download/<scope>/<name>/<version>/<sha256>) has no value: the digest is a fact about the bytes rather than about the package's identity, so its URLs are kept in the lockfile instead"; the test "keeps GitHub Packages /download/ tarball URLs" of pnpm11/lockfile/utils/test/toLockfileResolution.ts at the same tag uses https://npm.pkg.github.com/download/@example/private/1.2.3/<40 hex digits>. npm.pkg.github.com is the npm registry of GitHub Packages on github.com; GitHub Enterprise uses npm.SUBDOMAIN.ghe.com or npm.HOSTNAME (content/packages/working-with-a-github-packages-registry/working-with-the-npm-registry.md in github/docs), which depcurfew recognizes only through the .npmrc of the project (npm extra.registryHostTarballs). ↗
  • npmRegistry.gitlabTarballs: GET projects/:id/packages/npm/:package_name/-/:file_name downloads a package file; the metadata names the tarball https://gitlab.example.com/api/v4/projects/1/packages/npm/@myscope/my-pkg/-/@myscope/my-pkg-1.3.7.tgz, so the file name keeps the scope, and the registry is mounted below /api/v4/projects/<id>/packages/npm (or the group and instance endpoints). ↗
  • npmRegistry.artifactoryTarballs: getNpmTarballUrl: "Artifactory keeps the scope in the filename of a scoped package's tarball (@acme/widget/-/@acme/widget-1.0.0.tgz); the npm layout strips it". npm's versionFromTgz reads no name and version from such a URL (the part after /-/ is not the file name alone), so npm 12 cannot match it in allowScripts by version. ↗
  • pypiIndex.api: GET /simple/<project>/ with Accept: application/vnd.pypi.simple.v1+json returns name, files, meta, versions and project-status; the project is matched case-insensitively with _, - and . considered equal (index-api.md in pypi/warehouse, the source of docs.pypi.org/api/index-api/, which recommends the JSON form for new integrations; the JSON API of /pypi/<project>/json marks its releases key deprecated). A file has filename, url, hashes, size, an optional upload-time (yyyy-mm-ddThh:mm:ss.ffffffZ, UTC) and an optional yanked (true or a reason string). Every file belongs to a version listed in versions, but the response does not say which: the version is part of the file name. On 2026-10-30 pypi.org answered api-version 1.4 for requests and 404 for a name it does not know. ↗
  • pypiIndex.projectStatus: A project has exactly one status, active when none is given. quarantined: considered generally unsafe (for example malware), and the index must not offer any of its files. archived: no new uploads, existing files stay; installers may warn. deprecated: obsolete, perhaps superseded by another project; installers may warn. ↗
  • claudeCode.hooks: A PreToolUse command hook gets the event as JSON on stdin and decides by printing one JSON object and exiting 0: deny prevents the call and shows the reason to Claude, ask prompts the user (also in auto mode), deny wins over ask. The PowerShell tool passes its command in tool_input.command with the same fields as the Bash tool. A matcher of names separated by | matches each of them exactly. With args set, command runs as an executable without a shell; on Windows it must resolve to a real executable such as a .exe, not a .cmd or .bat shim from node_modules/.bin. Without onFailure, a hook that fails to start, crashes or times out lets the call through. The if filter is best-effort; the docs recommend the permission system for hard allow or deny rules. ↗
  • claudeCode.sessionStart: SessionStart runs when a session starts or resumes; its matcher startup fires for a new session (also resume, clear, compact and fork). Hooks run in the background, but "Claude's first response still waits for the hooks to finish", and a prompt sent meanwhile does not reach Claude until they finish. A command hook may be shell form (command with $CLAUDE_PROJECT_DIR, the repository root). With onFailure set to "block" (#block-the-action-when-a-hook-fails), a PreToolUse hook whose script is missing blocks the call ("failed; blocking because onFailure is "block"" followed by node's error output, in the example "PreToolUse:Bash hook error: [node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js]: failed; blocking because onFailure is "block"" and "Error: Cannot find module '/path/to/project/.claude/hooks/check-command.js'", re-read 2026-11-01): node starts, cannot load the script and exits with 1, which counts as a failure; without it, the same missing script is a non-blocking error and the command runs. In cloud sessions (https://code.claude.com/docs/en/cloud-environments#setup-scripts) a setup script is a Bash script that runs as root before Claude Code launches and is skipped when a cached environment exists; SessionStart hooks of the repository's .claude/settings.json run in local and cloud sessions (in a session with one repository, outside a project thread), user-level ~/.claude/settings.json hooks do not reach the cloud. The docs recommend a SessionStart hook for project setup such as npm install. ↗
  • claudeCode.shellTools: Tool names are the exact strings of hook matchers. Bash executes shell commands. PowerShell executes PowerShell commands natively; hooks get its command in tool_input.command with the same fields as Bash, and the docs say to match Bash|PowerShell in hooks that inspect shell commands: on Windows, wherever the PowerShell tool is enabled, Claude treats PowerShell as the primary shell, and without Git Bash it is enabled automatically and the Bash tool is not registered at all (also https://code.claude.com/docs/en/hooks#powershell). On Windows with Git Bash it is on by default for claude.ai and Console accounts, CLAUDE_CODE_USE_POWERSHELL_TOOL=0 turns it off, and Claude Code runs pwsh.exe or else powershell.exe 5.1. Monitor runs a command in the background and feeds its output lines back to Claude, with the same permission rules as Bash; on Windows it is available only with Git Bash; a WebSocket watch takes a ws input in place of command. ↗
  • claudeCode.commandlessInputs: "A WebSocket watch takes a `ws` input in place of `command`, and a single Monitor call can't combine the two"; ws has url (a ws:// or wss:// URL) and optional protocols. Opening a WebSocket has its own approval prompt. ↗
  • mcp.revisions: Modern: revisions that carry version, identity and capabilities on every request (2026-07-28 and later); legacy: revisions that open a session with the initialize handshake (2025-11-25 and earlier). A dual-era server may serve both on one stdio process: a request with the modern per-request _meta is served statelessly, an initialize request selects legacy semantics for the process. docs/docs.json lists 2026-07-28 (latest), 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05; schema/2026-07-28/schema.ts and schema/draft/schema.ts both say LATEST_PROTOCOL_VERSION = "2026-07-28". ↗
  • mcp.lifecycle: If the server supports the requested protocolVersion it must answer with the same one, otherwise with another version it supports, which should be its latest; a client that cannot use it disconnects (the same wording in 2024-11-05). After the result the client sends notifications/initialized. The initialize request must not be cancelled and, in 2025-03-26, must not be part of a batch. ping (basic/utilities/ping.mdx) is answered promptly with an empty result and may be sent before initialization. 2026-07-28 removes initialize, notifications/initialized and ping (docs/specification/2026-07-28/changelog.mdx). ↗
  • mcp.stateless: Every 2026-07-28 request carries params._meta with io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities (required; a request missing either is rejected with -32602) and optionally io.modelcontextprotocol/clientInfo; servers should put io.modelcontextprotocol/serverInfo in the _meta of every result, and every result must carry resultType ("complete" for a finished one; clients read an absent one as complete). Servers must implement server/discover (server/discover.mdx: supportedVersions, capabilities, instructions, serverInfo in _meta). server/utilities/caching.mdx: results of server/discover and tools/list must carry ttlMs (>= 0) and cacheScope ("public" suits lists of tools that are the same for all users). An unsupported version gets -32022 with data { supported, requested } (basic/versioning.mdx). Self-reported identity must not change behavior. ↗
  • mcp.tools: A server with tools declares the tools capability and answers tools/list (tools in a deterministic order that does not vary per connection) and tools/call ({ name, arguments }; result content, optional structuredContent and isError). Errors of the tool itself, including input values the model can correct, belong in the result with isError: true; an unknown tool or a request that does not fit the schema is a protocol error (-32602). A tool that returns structuredContent should also return the same JSON in a text block. Tool names should be 1 to 128 characters of letters, digits, _, - and . . Annotations (readOnlyHint, openWorldHint and others) are hints that clients must treat as untrusted. Annotations arrived in 2025-03-26 (changelog.mdx), title and structured output in 2025-06-18 (changelog.mdx); in 2025-11-25 and earlier structuredContent is an object. ↗
  • mcp.cancellation: The client cancels an in-flight request with the notification notifications/cancelled and params { requestId, reason? }; the server should stop the work as soon as practical and must not send any further message for that request, and may ignore an unknown or finished request (also basic/transports/stdio.mdx). The same notification exists in the legacy revisions (2025-11-25/basic/utilities/cancellation.mdx). ↗
  • mcp.errorCodes: PARSE_ERROR, INVALID_REQUEST, METHOD_NOT_FOUND, INVALID_PARAMS, INTERNAL_ERROR and UNSUPPORTED_PROTOCOL_VERSION. -32601 is for a method the server does not implement. basic/index.mdx: request ids are strings or integers and never null; notifications have no id and get no response; an error response has the id of its request except when it could not be read, and the 2025-11-25 and 2026-07-28 schemas make id optional in an error response; codes from -32000 to -32019 are legacy and other codes from -32020 to -32099 that the specification does not define must not be used. ↗
  • mcp.errorId: JSONRPCErrorResponse has id?: RequestId in the 2025-11-25 schema (also in schema/2026-07-28/schema.ts); the schemas of 2025-06-18 and 2024-11-05 have JSONRPCError with a required id: RequestId (string | number), and basic/index.mdx of 2025-06-18 says responses must include the same id as their request and request ids must not be null. Neither says what an error response for a request whose id cannot be read carries; JSON-RPC 2.0 uses null there (jsonrpc.org was not reachable to verify it). ↗
  • mcp.stdio: The server reads JSON-RPC messages from stdin and writes them to stdout, delimited by newlines and without embedded newlines; it must not write anything to stdout that is not a valid MCP message, may log UTF-8 to stderr and should exit promptly when stdin is closed. Batches: 2025-03-26 (basic/index.mdx) says implementations must support receiving JSON-RPC batches; 2025-06-18 removed batching (changelog.mdx), and later revisions have no batch message. ↗
  • mcp.clients.claudeCode: claude mcp add [options] <name> -- <command> [args...]: everything after -- goes to the server untouched. Scopes: local (the default, ~/.claude.json), project (.mcp.json in the project root, shared through the repository; Claude Code asks before using its servers) and user. .mcp.json has a top-level mcpServers object of entries with command, args and env; an entry without type is a stdio server. Claude Code sets CLAUDE_PROJECT_DIR to the project root in the environment of the server, not in its own, so ${VAR} expansion in command or args of .mcp.json needs a default such as ${CLAUDE_PROJECT_DIR:-.}. To stop a stdio server it sends SIGINT, then SIGTERM after 100 ms and SIGKILL after a further 400 ms (macOS, Linux); on Windows it closes stdin and ends the process tree after 300 ms. ↗
  • mcp.clients.claudeDesktop: The page "Connect to local MCP servers" of modelcontextprotocol.io: Claude Desktop reads mcpServers (entries with command, args and env) from claude_desktop_config.json. It documents no working directory and no variables, and its troubleshooting asks for absolute paths. The stderr of a server goes to mcp-server-<name>.log in ~/Library/Logs/Claude (macOS) or %APPDATA%\Claude\logs (Windows). ↗
  • mcp.clients.vscode: The source of code.visualstudio.com/docs/agents/reference/mcp-configuration. .vscode/mcp.json (in the workspace or the user profile) has a top-level servers object; a stdio server needs type "stdio" and command, and takes args, cwd (defaults to the workspace folder when run in a workspace), env and envFile; predefined variables such as ${workspaceFolder} work in the configuration. VS Code also reads the portable .mcp.json with mcpServers at the workspace root, without cwd. code --add-mcp with a JSON object of a name and the server configuration adds the server to the user profile. ↗
  • git.ignore: git status and git add skip untracked files that match a pattern from a .gitignore in the same directory or a parent (deeper files override higher ones, and within one file the last matching pattern decides), then from $GIT_COMMON_DIR/info/exclude (.git/info/exclude outside linked worktrees), then from core.excludesFile. Files already tracked are not affected. Patterns: # comments, ! negation, a leading or middle / anchors the pattern to the directory of its .gitignore, a trailing / matches directories only, * and ? do not match /, **/, /** and /**/ match any number of directories; a file below an ignored directory cannot be re-included. The tracked files are the entries of $GIT_DIR/index (Documentation/gitformat-index.adoc at v2.56.0: versions 2, 3 and 4). ↗
  • git.ignoreCase: core.ignoreCase turns on workarounds for file systems that are not case sensitive (APFS, HFS+, FAT, NTFS); it defaults to false, but git clone and git init probe the file system and set it to true when appropriate, so a repository cloned on Windows or macOS has it. With it, git matches .gitignore patterns and looks up the index without regard to case: match_basename and match_pathname in dir.c compare with fspathncmp and fnmatch_icase_mem, which fold case (strncasecmp, WM_CASEFOLD) when repo_ignore_case is set, and environment.c reads core.ignorecase (both at v2.56.0). Section and variable names are case-insensitive, true is yes, on, true or 1 in any case, and a variable without = <value> is true (Documentation/config.adoc at v2.56.0). ↗
  • git.repositoryEntry: "A submodule is a repository embedded inside another repository", with its own history; "the repository it is embedded in is called a superproject". Its git directory is "located under the $GIT_DIR/modules/ directory of its superproject", with "a .git file at the root of the submodule's working directory pointing to" it, and the superproject tracks it only "via a gitlink entry in the tree" with the commit it expects. So a directory with a .git entry of its own (a directory, or the file of a submodule) holds the files of another repository. ↗
  • windows.commandShims: cmd-shim is "the cmd-shim used in npm to create executable scripts on Windows" (README): for each program of a package it writes <name>.cmd, which runs the program with %* (so cmd.exe reads the arguments again), <name>.ps1 for PowerShell and a sh script. npm ships the same files for itself: bin/npm.cmd, bin/npm.ps1, bin/npx.cmd and bin/npx.ps1 in github.com/npm/cli at v12.2.1, the .cmd files ending in "%NODE_EXE%" "%NPM_CLI_JS%" %*. ↗
  • windows.batchArguments: about_Parsing (the source of https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_parsing): on Windows, arguments for batch files are passed as raw command-line strings to cmd.exe, and untrusted input should be passed another way. In the Windows mode of $PSNativeCommandArgumentPassing, the default on Windows since PowerShell 7.3, files ending in .bat or .cmd (also cmd.exe, cscript.exe, wscript.exe, .js, .vbs and .wsf) keep the legacy argument passing of Windows PowerShell 5.1. ↗
  • osv.api: POST /v1/querybatch takes {"queries": [...]}, each query as for POST /v1/query: a package by name and ecosystem with a top-level version, or by purl (a version in both places is a 400). It "Returns vulnerability ids and modified field only. The response ordering will be guaranteed to match the input": {"results": [{"vulns": [{"id", "modified"}], "next_page_token"?}]}. A result with more pages has next_page_token; the next request sends page_token only for those queries, and rarely a result holds only a token, so the caller keeps asking until no token comes back. The response is the JSON of v1BatchVulnerabilityList (docs/osv_service_v1.swagger.json), where an empty list is left out. "MaxQueriesPerQueryBatchRequest is a limit set in osv.dev's API, so is not configurable" = 1000 (bindings/go/osvdev/osvdev.go, with DefaultBaseURL https://api.osv.dev). A record's page is https://osv.dev/vulnerability/<ID> (docs/faq.md); GET /v1/vulns/{id} returns the record (docs/api/get-v1-vulns.md). Requests are case-sensitive ("use 'PyPI' instead of 'pypi'"), and PyPI names are matched after PEP 503 normalization (docs/api/post-v1-query.md). api.osv.dev could not be reached from the machine that read these sources. ↗
  • osv.paging: Pagination happens when "An individual query within the queryset returns more than 1,000 vulnerabilities" or "The entire queryset returns more than 3,000 vulnerabilities total"; "These numbers can vary slightly because of threading and the page size may change in the future." ↗
  • osv.ids: Version 1.9.2 (October 13, 2026) of the OSV schema: an id is "<DB>-<ENTRYID>", and it "must strictly use ASCII characters matching the regular expression ^[a-zA-Z0-9:_.-]+$"; "Characters outside this set (such as spaces, slashes /, backslashes \, parentheses, or exclamation marks) are not allowed." The JSON schema of the same release (validation/schema.json) checks only the prefix (MAL- among the home databases). The schema sets no length for an id. ↗
  • osv.service: "Is the API rate limited? No. Currently there is not a limit on the API." The response size limit is 32 MiB over HTTP/1.1 and none over HTTP/2. Data freshness objective: "Data sources no more than 15 minutes stale, 99.5% of the time". Availability objective 99.9% over 7 days; POST /v1/querybatch latency P50 500 ms, P90 4 s, P95 6 s. ↗
  • osv.withdrawn: Records with the withdrawn field (an RFC 3339 time, ossf/osv-schema docs/schema.md) "will be excluded from: the responses to POST API queries"; they stay in the database, are "returned by the /vulns/<ID> GET API" and shown at https://osv.dev/vulnerability/<ID> marked as withdrawn. ↗
  • osv.malicious: The prefix table of the OSV schema lists MAL for the "Malicious Packages Repository" (github.com/ossf/malicious-packages/tree/main/osv/); OSV.dev imports it under Apache 2.0 (google/osv.dev docs/data.md). Its README (github.com/ossf/malicious-packages/blob/main/README.md) says false positives "may be present in our dataset from time-to-time": a report that is wholly a false positive is moved to osv/withdrawn/ with a withdrawn time, and for false-positive versions of a report those versions move into a database_specific array; reports are not removed. Its CONTRIBUTING.md says ids are assigned automatically and the summary is replaced by a standard one ("Malicious code in <name> (<ecosystem>)" in the records). ↗
  • osv.ecosystems: Keys are the ecosystems of depcurfew (npm, pypi and packagist; in package names of the policy no prefix, pypi: and composer:), values the ecosystem names of the OSV schema: "npm" (an NPM package name), "PyPI" (a normalized PyPI package name), "Packagist" (a PHP package name; without a :<REMOTE-REPO-URL> suffix it means https://packagist.org). OSV.dev covers all three (google/osv.dev docs/data.md, Covered Ecosystems). How it compares Packagist versions: versionMatching. ↗
  • osv.versionMatching: The API (go/cmd/api, with the Datastore store of go/internal/database/datastore) answers a query with a version by buildVersionMatcher: for an ecosystem it knows, it parses the version with the ecosystem helper and keeps the AffectedVersions whose coarse range holds Coarse(version), then matches each listed version of a record by parsing it too and comparing the two (versionIsMatchEcosystemVersionsList, cmp == 0), and the events of its ranges the same way. The Packagist helper (go/osv/ecosystem/packagist.go) parses with semantic.ParsePackagistVersion of google/osv-scalibr v0.5.3 (go/go.mod), whose canonicalizePackagistVersion removes one leading v or V before it compares as PHP's version_compare does (semantic/version-packagist.go at v0.5.3), and its Coarse removes them too, so v8.1.9 and 8.1.9 are the same version both in a query and in a record (also the coarse range the importer stores, go/internal/database/datastore/affected_versions.go). The Python helper of the workers (osv/ecosystems/packagist.py, PackagistVersion.php_canonicalize_version) removes a leading v as well. All at google/osv.dev b7449847246af793439d06284d340af40cdae854 (master on 2026-11-02). A version of composer.lock is therefore sent as Composer wrote it. ↗
  • osv.dataExport: The sources "are aggregated and continuously exported to a GCS bucket maintained by OSV: gs://osv-vulnerabilities"; "Individual vulnerability records can be found at gs://osv-vulnerabilities/<ECOSYSTEM>/<ID>.json" and "A zip containing all vulnerabilities for each ecosystem is available at gs://osv-vulnerabilities/<ECOSYSTEM>/all.zip", with the example "download over HTTP via https://storage.googleapis.com/osv-vulnerabilities/PyPI/all.zip"; the zip of all ecosystems holds withdrawn records too. The folder of an ecosystem is its name: gs://osv-vulnerabilities/ecosystems.txt lists npm, PyPI and Packagist, and ecosystems with a :suffix are exported only under the main ecosystem. Read on 2026-11-03 from the bucket itself: npm/all.zip 219,811,588 bytes with 231,076 entries (223,001 MAL- records, 334 of them withdrawn; more than 65,535 entries, so the end of its central directory is in the ZIP64 format), PyPI/all.zip 37,606,501 bytes with 26,779 entries (11,976 MAL-, 25 withdrawn), Packagist/all.zip 11,087,467 bytes with 7,397 entries (1 MAL-); every entry is a file <ID>.json at the top of the zip, deflated, without encryption, data descriptor or extra field; the largest MAL- entry is 1,148,610 bytes. The bucket answers with Last-Modified, the time the zip was written. Every MAL- record of the exports written at 08:33 UTC the same day (npm 219,814,610 bytes with 223,004 MAL- entries, PyPI 11,976, Packagist 1), read in full: at most 1 affected[] entry per record; for one package in one record at most 232 versions (PyPI 86), 2 ranges and 4 events in a range; at most 2 records of one package (PyPI 1); the longest version 74 characters; the data depcurfew writes from them is 17,911,745 bytes for npm with a longest package line of 3,320 bytes (PyPI 794,277 and 789 bytes). ↗
  • osv.affected: OSV schema 1.9.2: "A version is considered affected if it lies within any one of the ranges or is listed in the versions list"; versions holds "a single affected version in whatever version syntax is used by the given package ecosystem". A range has a type: SEMVER (SemVer 2.0.0 versions without a leading v), ECOSYSTEM ("arbitrary, uninterpreted strings specific to the package ecosystem", ordered by the ecosystem) or GIT (full commit hashes, which need the commit graph). Its events each hold one of introduced, fixed, last_affected and limit; introduced "0" is a version that sorts before any other, limit "*" is infinity, and without a limit event an implicit {"limit": "*"} is assumed. The Evaluation section: IncludedInVersions is v == version; IncludedInRanges, for each range that BeforeLimits(v) (no limit events, or some limit with v < limit), sets vulnerable = false and for evt in sorted(range.events): introduced and v >= introduced sets it true, else fixed and v >= fixed sets it false, else last_affected and v > last_affected sets it false; the version is affected when vulnerable is true. Records are matched to a package by affected[].package (name and ecosystem; a PyPI name is the normalized one of PEP 503). ↗
  • python.nameNormalization: Names are lowercased and every run of ., - or _ becomes a single -, before lookups and comparisons (PEP 503): Friendly.Bard and friendly_bard are the same package. Read from the page source in pypa/packaging.python.org. ↗
  • python.namePattern: The specification gives ^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])\Z run with re.IGNORECASE (PEP 508). ↗
  • python.projectFile: The configuration file of a Python project, in the project root; tools keep their own settings in its [tool.<name>] tables. ↗
  • python.wheelExtension: A wheel is a ZIP archive with the .whl extension; installing it unpacks files and runs no build code. Read from the page source in pypa/packaging.python.org. ↗
  • python.sourceDistributionExtensions: ARCHIVE_EXTENSIONS of pip without .whl: the archives pip accepts from an index besides wheels (index/package_finder.py rejects any other extension), all of them built when installed. A standard sdist is named {name}-{version}.tar.gz with the name normalized (PEP 625, source-distribution-format.rst); older uploads use the other extensions and names that are not normalized. ↗
  • python.bundledPip: _PIP_VERSION in Lib/ensurepip/__init__.py at every final tag from v3.9.0 to v3.15.2 (github.com/python/cpython/blob/v<X.Y.Z>/...; the latest tags are v3.9.25 0bbaf5de, v3.10.22 acb4dc12, v3.11.18 26badd80, v3.12.16 2c2462af, v3.13.18 0d4bd512, v3.14.10 b703b2c5 and v3.15.2 5e58eaad), as the first release of each line that bundles each pip version. Two-part values such as 24.0 are written 24.0.0. 3.12 and older never bundle pip 26; pip 26.1 or later comes with 3.13.14, 3.14.5 and 3.15.0. ↗
  • python.hatch: Hatch reads its project configuration from [tool.hatch] of pyproject.toml or from hatch.toml. It has no setting of its own for a release-age delay, building from source or dependency sources; its environments install with uv (installer = "uv", the default of its internal environments) or pip (docs/how-to/environment/select-installer.md), and uv reads [tool.uv] of the project under Hatch too (tested on 2026-10-30 with Hatch 1.18.2 and uv 0.13.6). ↗
  • python.virtualEnvironment: Creating virtual environments: venv "places a pyvenv.cfg file in it with a home key" (in the target directory) and "also creates a bin (or Scripts on Windows) subdirectory". How venvs work: "A virtual environment may be "activated" using a script in its binary directory (bin on POSIX; Scripts on Windows)"; the table of activation commands: POSIX bash/zsh source <venv>/bin/activate, fish source <venv>/bin/activate.fish, csh/tcsh source <venv>/bin/activate.csh, pwsh <venv>/bin/Activate.ps1; Windows cmd.exe <venv>\Scripts\activate.bat, PowerShell <venv>\Scripts\Activate.ps1. Activation prepends the binary directory to PATH and sets VIRTUAL_ENV. Lib/venv/__init__.py at v3.14.0 writes pyvenv.cfg as os.path.join(context.env_dir, "pyvenv.cfg") and installs the scripts of the common directory and of os.name. ↗
  • python.interpreter: python [-bBdEhiIOPqRsSuvVWx?] [-c command | -m module-name | script | - ] [args]: -m and -c end the interpreter options, and what follows goes to the module or the command; -W arg, -X option and --check-hash-based-pycs mode take a value, the other options are flags. One-letter options may be grouped after one dash: _PyOS_GetOpt in Python/getopt.c (v3.14.0, SHORT_OPTS "bBc:dEhiIm:OPqRsStuvVW:xX:?") reads them one by one, and c, m, W and X take the rest of the word or the next word, so python3 -Im pip runs pip. pip documents running itself as python -m pip, and as py -m pip with the Windows launcher (github.com/pypa/pip/blob/26.2.2/docs/html/cli/pip_install.rst). ↗

To review

Uncertain facts rest on incomplete official sources; disputed facts have official sources that disagree.

npm · installScripts.allowList.format ❓ uncertain

The exact entry grammar (no semver ranges) is stated in accepted RFC 0054; the shipped docs describe entries only in prose.

  • Object keyed by name, name@version or name@v1 || v2 with true (allow) or false (deny); npm install-scripts approve writes pinned name@version entries · source, verified 2026-10-28.

npm · sources.git.availableSince ⚠️ disputed

The release notes add --allow-git in 11.9.0; the GitHub changelog says it was introduced in 11.10.0.

  • Variant 1: 11.9.0 · source, verified 2026-10-28.
  • Variant 2: 11.10.0 · source, verified 2026-10-28.

npm · sources.remoteTarball.availableSince ⚠️ disputed

The 11.14.0 release notes add the flag; the GitHub changelog dates it to 11.15.0, which also moved enforcement into the resolver. Treat 11.15.0 as the safe minimum.

  • Variant 1: 11.14.0 · source, verified 2026-10-28.
  • Variant 2: 11.15.0 · source, verified 2026-10-28.

npm · sources.file.availableSince ⚠️ disputed

The 11.14.0 release notes add the flag; the GitHub changelog dates it to 11.15.0, which also moved enforcement into the resolver. Treat 11.15.0 as the safe minimum.

  • Variant 1: 11.14.0 · source, verified 2026-10-28.
  • Variant 2: 11.15.0 · source, verified 2026-10-28.

npm · sources.directory.availableSince ⚠️ disputed

The 11.14.0 release notes add the flag; the GitHub changelog dates it to 11.15.0, which also moved enforcement into the resolver. Treat 11.15.0 as the safe minimum.

  • Variant 1: 11.14.0 · source, verified 2026-10-28.
  • Variant 2: 11.15.0 · source, verified 2026-10-28.

npm · project.workspacesObjectKey ❓ uncertain

Not documented; npm's map-workspaces also accepts { "packages": [...] } and negated patterns.

  • packages · source, verified 2026-11-03.

npm · extra.lockfileInstalls ❓ uncertain

Inferred: npm ci does not list min-release-age or before among its options, and a user report (npm/cli#9277) describes it installing a version younger than the window.

  • npm ci installs versions pinned in package-lock.json without applying min-release-age · source, verified 2026-10-28.

pnpm · cooldown.cliFlag ❓ uncertain

No dedicated flag is documented for install or add; release notes mention "a CLI flag" without syntax. Environment variable: PNPM_CONFIG_MINIMUM_RELEASE_AGE (pnpm 11+), npm_config_minimum_release_age (pnpm 10).

  • null · source, verified 2026-10-28.

pnpm · sources.file.setting ❓ uncertain

No setting restricts file: or link: dependencies (concluded from the full settings list); blockExoticSubdeps treats local paths and workspace links as trusted.

  • null · source, verified 2026-10-28.

pnpm · sources.directory.setting ❓ uncertain

No setting restricts file: or link: dependencies (concluded from the full settings list); blockExoticSubdeps treats local paths and workspace links as trusted.

  • null · source, verified 2026-10-28.

pnpm · project.workspacesObjectKey ❓ uncertain

The docs show packages only as a list; concluded from the absence of an object form.

  • null · source, verified 2026-10-28.

pnpm · user.unknownKeys ❓ uncertain

pnpm 11 drops config.yaml keys it does not accept (unknown, project-only or not camelCase) and prints a warning that names them; pnpm 12 warns about keys its port of isConfigFileKey rejects, but drops blockExoticSubdeps without a word. What pnpm 10 does with an unknown key in rc was not checked.

  • warn · source, verified 2026-10-31.

pnpm · user.invalidValueFails ❓ uncertain

Read from code: pnpm 11.28.10 stops when the global config.yaml cannot be read (readGlobalYamlConfig) or applied (applyGlobalYamlConfig), except in commands that skip unreadable settings. Which values fail, and what pnpm 10 (rc) and pnpm 12 do, was not checked; true is the safe assumption.

  • true · source, verified 2026-10-31.

pnpm · extra.perProjectNpmrc ❓ uncertain

Without a shared lockfile, pnpm 10 installs every workspace project with its own .npmrc layered over the workspace settings, without filtering keys, so a package .npmrc can change minimum-release-age for that project. Read from code; no documentation or test covers it. No official source says this combination turns minimumReleaseAge off.

  • {"sharedWorkspaceLockfile":false,"until":"11.0.0"} · source, verified 2026-10-29.

pnpm · extra.lockfileRecheck ❓ uncertain

Structured form of lockfileVerification: whether a frozen-lockfile install re-checks the age of versions already in the lockfile. trustLockfile: true (11.3.0) turns the check off.

  • 10.16.0+: false
    11.1.3+: true · source, verified 2026-10-28.

pnpm · extra.lockfileVerification ❓ uncertain

The 11.1.3 release notes confirm re-validation (ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION). The pnpm 10 behavior rests on maintainer comments in pnpm/pnpm#12450 (a Dependabot lockfile passed --frozen-lockfile on 10.34.5), not on docs.

  • 10.16.0+: frozen-lockfile installs do not re-check versions already in the lockfile
    11.1.3+: lockfile entries are re-checked; trustLockfile: true (11.3.0) turns this off · source, verified 2026-10-28.

Yarn (Berry) · cooldown.cliFlag ❓ uncertain

No flag sets the gate. --no-time-gate on yarn add and yarn up (4.15.0+) disables it for one command; yarn install has no such flag.

  • null · source, verified 2026-10-28.

Yarn (Berry) · cooldown.default ⚠️ disputed

The code is unambiguous: off until 4.14.x, 1d from 4.15.0. The published settings schema claimed 3d for 4.11.0-4.14.x and 0m in 4.16.0; the live yarnrc page shows "1w", which is an example value. Upgraded projects with an old lockfile get npmMinimalAgeGate: 0 written to .yarnrc.yml (see upgradeMigration).

  • Variant 1: 4.10.0+: 0
    4.15.0+: 1d · source, verified 2026-10-28.
  • Variant 2: 4.10.0+: 0
    4.11.0+: 3d
    4.15.0+: 1d · source, verified 2026-10-28.

Yarn (Berry) · cooldown.securityUpdates ❓ uncertain

No automatic bypass is documented and yarn npm audit only reports. Options: --no-time-gate on yarn add/up, a pinned npmPreapprovedPackages entry, or a per-scope gate of 0.

  • applies · source, verified 2026-10-28.

Yarn (Berry) · installScripts.allowList.availableSince ❓ uncertain

dependenciesMeta is documented in the changelog from the 2.x line; the exact first version was not pinned down.

  • 2.0.0 · source, verified 2026-11-03.

Yarn (Berry) · sources.remoteTarball.setting ❓ uncertain

No setting restricts http(s) tarball dependencies (concluded from the full settings list); the closest are enableNetwork, networkSettings.<host>.enableNetwork and unsafeHttpWhitelist for plain http.

  • null · source, verified 2026-10-28.

Yarn (Berry) · sources.file.setting ❓ uncertain

No setting restricts file:, link: or portal: dependencies (concluded from the settings list and plugin sources); only exec: is gated by enableScripts (4.14.0+).

  • null · source, verified 2026-10-28.

Yarn (Berry) · sources.directory.setting ❓ uncertain

No setting restricts local directory dependencies (file:, link:, portal:), as for local tarballs.

  • null · source, verified 2026-10-28.

Yarn (Berry) · project.workspacesObjectKey ❓ uncertain

Not documented; the manifest parser also accepts { "packages": [...] }.

  • packages · source, verified 2026-11-03.

Yarn (Berry) · user.invalidValueFails ❓ uncertain

Read from code at 4.18.1: parseValue errors are rethrown with the file name while the configuration loads, so a value Yarn cannot parse, such as enableScripts: maybe or a malformed duration, stops every command, also from the home file. On 4.10.x a duration string such as 7d silently had no effect instead (durationStrings). Not tested.

  • true · source, verified 2026-10-31.

Yarn (Berry) · user.weakening ❓ uncertain

Read from code (resolveRcFiles, the same since 4.0.0; not on yarnpkg.com, and no test was read): lists from every .yarnrc.yml are joined, so home entries add to a project's list unless the project uses the undocumented { onConflict: reset } form; objects such as npmScopes merge key by key; for single values the file closest to the project wins. Since 4.17.0 a scope listed in the home npmScopes only for its registry gets the default gate of 1d instead of the project's gate (perScopeGate). A .yarnrc.yml in any folder between the root and the project merges the same way. enableScripts is a switch that turns a protection off: Yarn reads every value as text (FAILSAFE_SCHEMA, see extra.yamlMergeKeys) and parseBoolean of miscUtils.ts takes true and 1 as true and false and 0 as false and stops on any other value, after replacing ${VARIABLE} references; depcurfew counts every value but false and 0 as on.

  • {"key":"approvedGitRepositories","values":"any","effect":"approves these git repositories in every project, on top of the project's own list"}, {"key":"npmPreapprovedPackages","values":"any","effect":"exempts these packages from the age gate in every project, on top of the project's own list"}, {"key":"enableScripts","values":{"except":[false,0,"false","0"]},"effect":"runs dependency build scripts in every project whose .yarnrc.yml does not set enableScripts"}, {"key":"npmMinimalAgeGate","values":[0],"effect":"turns the age gate off in every project whose .yarnrc.yml does not set it"}, {"key":"npmScopes.*.npmMinimalAgeGate","values":[0],"effect":"turns the age gate off for that scope in every project"} · source, verified 2026-10-31.

Yarn (Berry) · user.variables ⚠️ disputed

The yarnrc docs say environment variables cannot set lists, but parseValue splits a string on commas for list settings, so by the code YARN_APPROVED_GIT_REPOSITORIES and YARN_NPM_PREAPPROVED_PACKAGES work. The safe choice is to treat both as effective.

  • Variant 1: {"name":"YARN_ENABLE_SCRIPTS","anyCase":true,"values":{"except":["false","0"]},"effect":"runs dependency build scripts, whatever any .yarnrc.yml says"}, {"name":"YARN_NPM_MINIMAL_AGE_GATE","anyCase":true,"values":"any","effect":"replaces npmMinimalAgeGate from every .yarnrc.yml"}, {"name":"YARN_APPROVED_GIT_REPOSITORIES","anyCase":true,"values":"any","effect":"replaces approvedGitRepositories from every .yarnrc.yml (a comma-separated list)"}, {"name":"YARN_NPM_PREAPPROVED_PACKAGES","anyCase":true,"values":"any","effect":"replaces npmPreapprovedPackages from every .yarnrc.yml (a comma-separated list)"} · source, verified 2026-10-31. A variable starting with yarn_ in any case sets the camel-cased setting before the rc files are read, and they cannot change it (Configuration.find and use; YARN_IGNORE_SCRIPTS is ignored); a list setting takes a comma-separated string (parseValue); enableScripts accepts true or 1 (parseBoolean), false or 0 turn it off, and any other value stops Yarn, so every value but false and 0 counts as on.
  • Variant 2: {"name":"YARN_ENABLE_SCRIPTS","anyCase":true,"values":{"except":["false","0"]},"effect":"runs dependency build scripts, whatever any .yarnrc.yml says"}, {"name":"YARN_NPM_MINIMAL_AGE_GATE","anyCase":true,"values":"any","effect":"replaces npmMinimalAgeGate from every .yarnrc.yml"} · source, verified 2026-10-31. Most settings "can also be defined through environment variables (at least for the simpler ones; arrays and objects aren't supported yet)", and such values "will overwrite any that might have been defined in the RC files".

Yarn (Berry) · extra.yarnPath ❓ uncertain

yarn set version saves the release as .yarn/releases/yarn-<version>.cjs and writes a relative yarnPath to it. Yarn 2 and later read yarnPath (an absolute path setting, resolved against the folder of the .yarnrc.yml that sets it) from every .yarnrc.yml, the home file included, before the project is found (Configuration.find, pickPrimaryCoreFields), and run node <yarnPath> instead of themselves (runYarnPath in packages/yarnpkg-cli/sources/lib.ts); a nearer .yarnrc.yml with its own yarnPath, YARN_YARN_PATH or YARN_IGNORE_PATH changes that. The file name is only a hint: a URL or a file given to yarn set version gives other names (yarn-remote.cjs), a hand-written yarnPath may name any file, and the version inside the bundle is minified, so depcurfew uses the name only when it is yarn-<exact version>.cjs and the file exists.

  • {"key":"yarnPath","releaseFile":"yarn-<version>.cjs","variables":["YARN_YARN_PATH","YARN_IGNORE_PATH"]} · source, verified 2026-11-01.

Yarn (Berry) · extra.berryLockfileMarker ❓ uncertain

Read from code: Yarn 2+ writes a __metadata key into yarn.lock and treats a lockfile without it but with "yarn lockfile v1" as Yarn Classic.

  • __metadata · source, verified 2026-11-03.

Yarn (Berry) · extra.unknownSettings ❓ uncertain

Read from the code at 4.18.1; older releases were not checked.

  • Unknown keys in the project .yarnrc.yml throw (unless enableStrictSettings is false), so settings newer than the pinned Yarn break installs · source, verified 2026-11-03.

Bun · cooldown.default ⚠️ disputed

The bunfig reference says the default is null (off) and an open docs pull request (oven-sh/bun#41545) says the feature is off by default; the install page lists 259200 (3 days) under "These are the default values".

  • Variant 1: 1.3.0+: null · source, verified 2026-10-28.
  • Variant 2: 1.3.0+: 259200 · source, verified 2026-10-28.

Bun · cooldown.securityUpdates ❓ uncertain

No automatic bypass is documented; exempt the fixed release with name@version in minimumReleaseAgeExcludes (1.4.4+). Exact version requests still go through the gate.

  • applies · source, verified 2026-10-28.

Bun · installScripts.allowList.availableSince ❓ uncertain

Upper bound: 1.0.5 already persists trustedDependencies in bun.lockb; the first version was not pinned down. bun pm trust and bun add --trust arrived in 1.0.31.

  • 1.0.5 · source, verified 2026-10-28.

Bun · sources.git.setting ❓ uncertain

Git dependencies are supported with no setting to allow or forbid them (concluded from the full bunfig [install] list); install.blockExoticSubdeps is proposed in oven-sh/bun#30340 but not shipped.

  • null · source, verified 2026-10-28.

Bun · sources.remoteTarball.setting ❓ uncertain

Tarball URL dependencies are supported with no setting to allow or forbid them (concluded from the full bunfig [install] list); install.blockExoticSubdeps is proposed in oven-sh/bun#30340 but not shipped.

  • null · source, verified 2026-10-28.

Bun · sources.file.setting ❓ uncertain

Local tarball dependencies are supported with no setting to allow or forbid them (concluded from the full bunfig [install] list); install.blockExoticSubdeps is proposed in oven-sh/bun#30340 but not shipped.

  • null · source, verified 2026-10-28.

Bun · sources.directory.setting ❓ uncertain

Local directory dependencies are supported with no setting to allow or forbid them (concluded from the full bunfig [install] list); install.blockExoticSubdeps is proposed in oven-sh/bun#30340 but not shipped.

  • null · source, verified 2026-10-28.

Bun · project.lockfiles ❓ uncertain

Bun 1.2 made the text bun.lock the default (verified). That bun.lockb is still read afterwards is inferred from the documented migration command and from saveTextLockfile = false, which writes bun.lockb.

  • earlier: bun.lockb
    1.2.0+: bun.lock, bun.lockb · source, verified 2026-11-03.

Bun · user.variables ❓ uncertain

No environment variable sets minimumReleaseAge or its exclusions: concluded from the install page, which lists registry, token, lockfile and retry variables only. NPM_CONFIG_IGNORE_SCRIPTS only turns scripts off. XDG_CONFIG_HOME moves the user file (user.files).

  • [] · source, verified 2026-10-31.

Deno · cooldown.availableSince ⚠️ disputed

The 2.5.5 release notes ship the flag, the deno.json key and exclude as unstable; the release blog says the feature was introduced in 2.6.

  • Variant 1: 2.5.5 · source, verified 2026-10-28.
  • Variant 2: 2.6.0 · source, verified 2026-10-28.

Deno · cooldown.securityUpdates ❓ uncertain

No security bypass is documented; only per-package exclude or an age of 0.

  • applies · source, verified 2026-10-28.

Deno · installScripts.disableAll ❓ uncertain

Scripts do not run by default. The schema accepts a boolean allowScripts, but no page states that false turns all scripts off. deno x has --ignore-scripts.

  • allowScripts: false · source, verified 2026-10-28.

Deno · user.variables ❓ uncertain

Only these two spellings are read (min_release_age_days_from_env); 0 turns the default 24 hours off. Read from code: every parsed .npmrc starts from the variable and its own key overrides it (test ".npmrc value takes precedence over the environment fallback"), and the project file wins over the home file, so a project .npmrc without the key puts the variable above the home value. The first version is from denoland/deno#35458, which shipped in 2.9.0.

  • {"name":"NPM_CONFIG_MIN_RELEASE_AGE","values":"any","effect":"sets min-release-age where no .npmrc has the key, and hides the home value in projects whose .npmrc lacks it (2.9.0+)"}, {"name":"npm_config_min_release_age","values":"any","effect":"sets min-release-age where no .npmrc has the key, and hides the home value in projects whose .npmrc lacks it (2.9.0+)"} · source, verified 2026-10-31.

Deno · extra.npmrcFormat ⚠️ disputed

The safe choice is an integer number of days, which also matches npm.

  • Variant 1: whole days only, e.g. min-release-age=3 · source, verified 2026-10-28.
  • Variant 2: a duration with a unit, e.g. min-release-age=72h · source, verified 2026-10-28.

Deno · extra.fileLinkSkipped ⚠️ disputed

Official pages disagree on whether the project's own file: and link: dependencies are skipped, or only those in published packages' metadata.

  • Variant 1: file: and link: dependencies in the project package.json are silently skipped · source, verified 2026-10-28.
  • Variant 2: file: and link: specifiers in registry metadata of npm packages are skipped · source, verified 2026-10-28.

uv · cooldown.securityUpdates ❓ uncertain

uv does not know which versions fix vulnerabilities; the delay holds back every new upload unless the package is listed in exclude-newer-package.

  • applies · source, verified 2026-10-30.

uv · sources.git.setting ❓ uncertain

No setting allows or forbids git dependencies (concluded from the list of settings). no-sources only ignores the tool.uv.sources table; a URL dependency introduced by a registry package is rejected during resolution (docs/pip/compatibility.md).

  • null · source, verified 2026-10-30.

uv · sources.remoteTarball.setting ❓ uncertain

No setting allows or forbids URL dependencies (concluded from the list of settings). no-sources only ignores the tool.uv.sources table; a URL dependency introduced by a registry package is rejected during resolution (docs/pip/compatibility.md).

  • null · source, verified 2026-10-30.

uv · sources.file.setting ❓ uncertain

No setting allows or forbids local archive dependencies (concluded from the list of settings). no-sources only ignores the tool.uv.sources table; a URL dependency introduced by a registry package is rejected during resolution (docs/pip/compatibility.md).

  • null · source, verified 2026-10-30.

uv · sources.directory.setting ❓ uncertain

No setting allows or forbids local directory dependencies (concluded from the list of settings). no-sources only ignores the tool.uv.sources table; a URL dependency introduced by a registry package is rejected during resolution (docs/pip/compatibility.md).

  • null · source, verified 2026-10-30.

uv · extra.lockfileFormat ❓ uncertain

uv.lock has no documented format (the docs say only that it is managed by uv). Each [[package]] has source = { registry = URL } for an index, { git = URL?rev#commit }, { url = URL }, { path = archive }, { directory = dir }, { editable = dir } or { virtual = dir } (a directory that is not built). Index packages list sdist and wheels; a package without wheels, or from git, a directory or a source archive, is built when installed.

  • {"sources":{"registry":"registry","git":"git","remoteTarball":"url","file":"path","directory":"directory","editable":"editable","virtual":"virtual"},"sdist":"sdist","wheels":"wheels","packages":"package"} · source, verified 2026-10-30.

pip · cooldown.exclude.setting ❓ uncertain

No per-package exception (concluded from the list of options).

  • null · source, verified 2026-10-30.

pip · cooldown.securityUpdates ❓ uncertain

pip does not know which versions fix vulnerabilities; the cutoff holds back every new upload.

  • applies · source, verified 2026-10-30.

pip · installScripts.allowList.availableSince ❓ uncertain

--no-binary and --only-binary exist since 7.0.0 and are read from pip.conf since 7.1.0; when requirements files started to accept them is not recorded.

  • 7.0.0 · source, verified 2026-10-30.

pip · sources.git.setting ❓ uncertain

No option allows or forbids VCS requirements (concluded from the list of options). Hash-checking mode (--require-hashes, or any --hash) rejects VCS and local directory requirements, unless --no-require-hashes (26.2) turns the automatic mode off.

  • null · source, verified 2026-10-30.

pip · sources.remoteTarball.setting ❓ uncertain

No option allows or forbids direct URL requirements (concluded from the list of options). Hash-checking mode (--require-hashes, or any --hash) rejects VCS and local directory requirements, unless --no-require-hashes (26.2) turns the automatic mode off.

  • null · source, verified 2026-10-30.

pip · sources.file.setting ❓ uncertain

No option allows or forbids local archive requirements (concluded from the list of options). Hash-checking mode (--require-hashes, or any --hash) rejects VCS and local directory requirements, unless --no-require-hashes (26.2) turns the automatic mode off.

  • null · source, verified 2026-10-30.

pip · sources.directory.setting ❓ uncertain

No option allows or forbids local directory requirements (concluded from the list of options). Hash-checking mode (--require-hashes, or any --hash) rejects VCS and local directory requirements, unless --no-require-hashes (26.2) turns the automatic mode off.

  • null · source, verified 2026-10-30.

pip · project.workspaces ❓ uncertain

pip has no workspaces.

  • null · source, verified 2026-10-30.

pip · project.workspacesObjectKey ❓ uncertain

No workspaces.

  • null · source, verified 2026-10-30.

pip · extra.buildSwitch ❓ uncertain

The option exists since 7.0.0; when requirements files started to accept it is not recorded. pip applies it only to packages found on indexes and find-links (format_control is used only by the package finder), so VCS, local directory and direct URL source requirements are still built.

  • {"setting":"--only-binary","value":":all:","since":"7.0.0","covers":["registry"]} · source, verified 2026-10-30.

Poetry · cooldown.cliFlag ❓ uncertain

No command-line option; the environment variable POETRY_SOLVER_MIN_RELEASE_AGE sets it for one command.

  • null · source, verified 2026-10-30.

Poetry · cooldown.securityUpdates ❓ uncertain

Poetry does not know which versions fix vulnerabilities; the delay holds back every new version of a package not listed in solver.min-release-age-exclude.

  • applies · source, verified 2026-10-30.

Poetry · sources.git.setting ❓ uncertain

No setting allows or forbids git dependencies (concluded from the list of settings and Config.default_config); dependencies of dependencies may come from such sources too.

  • null · source, verified 2026-10-30.

Poetry · sources.remoteTarball.setting ❓ uncertain

No setting allows or forbids url dependencies (concluded from the list of settings and Config.default_config); dependencies of dependencies may come from such sources too.

  • null · source, verified 2026-10-30.

Poetry · sources.file.setting ❓ uncertain

No setting allows or forbids local file dependencies (concluded from the list of settings and Config.default_config); dependencies of dependencies may come from such sources too.

  • null · source, verified 2026-10-30.

Poetry · sources.directory.setting ❓ uncertain

No setting allows or forbids local directory dependencies (concluded from the list of settings and Config.default_config); dependencies of dependencies may come from such sources too.

  • null · source, verified 2026-10-30.

Poetry · project.workspaces ❓ uncertain

Poetry has no workspaces: the pyproject.toml reference at 2.5.1 has no workspace or subproject setting, and the request for subprojects (python-poetry/poetry#2270) is open.

  • null · source, verified 2026-11-03.

Poetry · project.workspacesObjectKey ❓ uncertain

No workspaces.

  • null · source, verified 2026-11-03.

Poetry · user.unknownKeys ❓ uncertain

Config.merge keeps every key of config.toml and only known settings are read, so a version that does not know a key ignores it without a word. Read from the code; tested only with poetry.toml, which goes through the same merge (2.3.4 ignored solver.min-release-age there on 2026-10-30).

  • ignore · source, verified 2026-10-31.

Poetry · user.invalidValueFails ❓ uncertain

A config.toml that is not valid TOML stops every command (TOMLError "Invalid TOML file"). Values are not checked when the file is loaded (only POETRY_* variables go through the normalizers of config.py), and a key an older version does not know is never read, so the keys depcurfew writes need no exact version. Read from the code.

  • false · source, verified 2026-10-31.

Poetry · extra.excludeFormat ⚠️ disputed

The 2.5.1 docs give the type string, a comma-separated list; the docs on main (from pull request #11087, not released; read at commit 6ecadf5b) give array and say to use a TOML array in poetry.toml. The 2.5.1 code iterates the value as it is, so a string would be read letter by letter. Tested on 2026-10-30: a TOML array exempted the package in Poetry 2.4.0 and 2.5.1.

  • Variant 1: comma-separated string · source, verified 2026-10-30.
  • Variant 2: TOML array · source, verified 2026-11-03.

Poetry · extra.lockedVersionsKept ❓ uncertain

Read from the solver code, which takes the locked package without asking the repository; the docs do not say it.

  • poetry lock and poetry add keep versions already in poetry.lock even when they are newer than the delay allows; poetry update and poetry lock --regenerate resolve them again · source, verified 2026-10-30.

Poetry · extra.lockfileFormat ❓ uncertain

poetry.lock has no documented format. Each [[package]] from PyPI has no [package.source]; others have type git, url, file, directory or legacy (a named index). files lists {file, hash} for every distribution, empty for git and directory packages; a package from an index without a .whl file is built when installed.

  • {"sources":{"git":"git","remoteTarball":"url","file":"file","directory":"directory","registry":"legacy"},"packages":"package","source":"source","files":"files"} · source, verified 2026-10-30.

PDM · cooldown.securityUpdates ❓ uncertain

PDM does not know which versions fix vulnerabilities; the cutoff holds back every newer distribution of a package without an override.

  • applies · source, verified 2026-10-30.

PDM · sources.git.setting ❓ uncertain

No setting allows or forbids git dependencies (concluded from the documented [tool.pdm] settings); only-binary does not stop them from being built.

  • null · source, verified 2026-10-30.

PDM · sources.remoteTarball.setting ❓ uncertain

No setting allows or forbids URL dependencies (concluded from the documented [tool.pdm] settings); only-binary does not stop them from being built.

  • null · source, verified 2026-10-30.

PDM · sources.file.setting ❓ uncertain

No setting allows or forbids local archive dependencies (concluded from the documented [tool.pdm] settings); only-binary does not stop them from being built.

  • null · source, verified 2026-10-30.

PDM · sources.directory.setting ❓ uncertain

No setting allows or forbids local directory dependencies (concluded from the documented [tool.pdm] settings); only-binary does not stop them from being built.

  • null · source, verified 2026-10-30.

PDM · project.workspaces ❓ uncertain

Workspaces ([tool.pdm.workspace] members) are experimental since 2.28.0 and are locked and installed from the root only, so depcurfew configures the root and reads no members.

  • null · source, verified 2026-10-30.

PDM · project.workspacesObjectKey ❓ uncertain

Not read; see workspaces.

  • null · source, verified 2026-10-30.

PDM · user.unknownKeys ❓ uncertain

load_config keeps every key of config.toml without checking it, and only registered config items are ever read, so PDM before 2.27.0 ignores strategy.exclude-newer. Read from the code.

  • ignore · source, verified 2026-10-31.

PDM · user.invalidValueFails ❓ uncertain

A config.toml that is not valid TOML stops every command (load_config catches only FileNotFoundError). Values are coerced when read, and src/pdm/core.py reads strategy.exclude-newer before every command, so a value convert_to_datetime cannot parse (anything but Nd, Nh, Nw, a date or an RFC 3339 time) fails every command. Read from the code.

  • true · source, verified 2026-10-31.

PDM · extra.lockfileFormat ❓ uncertain

pdm.lock (lock_version 4.5) has no documented format beyond the docs examples. Each [[package]] has name, version and files ({file, hash} for every distribution); a VCS package has its repository under the key of its VCS (git = "…") with ref and revision; a local archive or directory has path, a remote archive url, and editable packages editable = true (as_lockfile_entry). A package from an index without a .whl file is built when installed.

  • {"packages":"package","files":"files","file":"file","vcs":["git","hg","svn","bzr"],"url":"url","path":"path","editable":"editable"} · source, verified 2026-10-30.

PDM · extra.uvMode ❓ uncertain

Experimental since 2.19.0: PDM resolves and installs with uv. It passes the cutoff and the build settings to uv lock, but runs uv sync --frozen without the build settings (src/pdm/installers/uv.py), and pdm.lock then lists source distributions even with only-binary.

  • {"file":"pdm.toml","key":"use_uv"} · source, verified 2026-10-30.

Pipenv · cooldown.cliFlag ❓ uncertain

No command-line option.

  • null · source, verified 2026-10-30.

Pipenv · cooldown.exclude.setting ❓ uncertain

No per-package exception: the cutoff applies to every package.

  • null · source, verified 2026-10-30.

Pipenv · cooldown.securityUpdates ❓ uncertain

The cutoff holds back every newer version, security fixes included.

  • applies · source, verified 2026-10-30.

Pipenv · installScripts.allowList.setting ❓ uncertain

No documented setting; a per-package no_binary = true exists in the code (pipenv/routines/install.py) but forces building rather than allowing it.

  • null · source, verified 2026-10-30.

Pipenv · installScripts.disableAll ❓ uncertain

No Pipfile setting. Only pip configuration or PIP_ONLY_BINARY=:all: in the environment (Pipenv loads the project .env for every command) forbids building.

  • null · source, verified 2026-10-30.

Pipenv · sources.git.setting ❓ uncertain

No Pipfile setting allows or forbids git dependencies (concluded from the documented [pipenv] directives).

  • null · source, verified 2026-10-30.

Pipenv · sources.remoteTarball.setting ❓ uncertain

No Pipfile setting allows or forbids URL dependencies (concluded from the documented [pipenv] directives).

  • null · source, verified 2026-10-30.

Pipenv · sources.file.setting ❓ uncertain

No Pipfile setting allows or forbids local archive dependencies (concluded from the documented [pipenv] directives).

  • null · source, verified 2026-10-30.

Pipenv · sources.directory.setting ❓ uncertain

No Pipfile setting allows or forbids local directory dependencies (concluded from the documented [pipenv] directives).

  • null · source, verified 2026-10-30.

Pipenv · project.workspaces ❓ uncertain

Pipenv has no workspaces.

  • null · source, verified 2026-10-30.

Pipenv · project.workspacesObjectKey ❓ uncertain

No workspaces.

  • null · source, verified 2026-10-30.

Pipenv · user.variables ❓ uncertain

PIPENV_RESOLVER is not documented. The code ranks it above the resolver key of the Pipfile ("CLI/caller > env > current project's Pipfile > default"), and the pure-python backend locked the newest versions despite cool-down-period when chosen in the Pipfile (extra.resolverBypass, tested on 2026-10-30); the variable itself was not tested. PIPENV_PYPI_MIRROR: "When the index does not provide upload-time metadata (e.g. most private mirrors) the setting is accepted but has no filtering effect" (docs/pipfile.md). PIP_* variables are merged over the environment of the pip subprocess (pipenv/utils/processes.py), so they still reach it while pip.conf does not; pipenv/routines/install.py also reads PIP_NO_BINARY.

  • {"name":"PIPENV_RESOLVER","values":["pure-python"],"effect":"selects the pure-python resolver, which ignores cool-down-period"}, {"name":"PIPENV_PYPI_MIRROR","values":"any","effect":"replaces PyPI; on a mirror without upload times cool-down-period has no effect"}, {"name":"PIP_ONLY_BINARY","values":"any","effect":"sets only-binary of the pip Pipenv installs with, which no pip.conf reaches since 2026.3.0"}, {"name":"PIP_NO_BINARY","values":"any","effect":"builds these packages from source when installing, and pipenv install records no_binary for a named package in the Pipfile"} · source, verified 2026-10-31.

Pipenv · extra.resolverBypass ❓ uncertain

Not documented. Tested on 2026-10-30 with 2026.10.4: with resolver_backend = "pure-python" in [pipenv], pipenv lock locked the newest versions despite cool-down-period = "100000d"; resolver is the older name of the key.

  • {"table":"pipenv","keys":["resolver_backend","resolver"],"value":"pure-python"} · source, verified 2026-10-30.

Composer · cooldown.cliFlag ❓ uncertain

No option sets the period (concluded from the command options): --no-cooldown and --no-blocking turn the delay off for one command, show --cooldown-period and outdated --cooldown-period only change what is displayed, and COMPOSER_POLICY_COOLDOWN_PERIOD overrides the period.

  • null · source, verified 2026-11-02.

Composer · cooldown.securityUpdates ❓ uncertain

The cooldown section names no exception for security fixes; its example lists symfony/security-bundle under ignore because "Security fixes need to be applied immediately".

  • applies · source, verified 2026-11-02.

Composer · sources.git.setting ❓ uncertain

No setting allows or forbids VCS dependencies (concluded from the config options in 06-config.md). Such packages come only from repositories declared in the root composer.json: "Repositories are not resolved recursively. You can only add them to your main composer.json. Repository declarations of dependencies' composer.jsons are ignored."

  • null · source, verified 2026-11-02.

Composer · sources.remoteTarball.setting ❓ uncertain

No setting allows or forbids package repository dependencies (concluded from the config options in 06-config.md). Such packages come only from repositories declared in the root composer.json: "Repositories are not resolved recursively. You can only add them to your main composer.json. Repository declarations of dependencies' composer.jsons are ignored."

  • null · source, verified 2026-11-02.

Composer · sources.file.setting ❓ uncertain

No setting allows or forbids artifact dependencies (concluded from the config options in 06-config.md). Such packages come only from repositories declared in the root composer.json: "Repositories are not resolved recursively. You can only add them to your main composer.json. Repository declarations of dependencies' composer.jsons are ignored."

  • null · source, verified 2026-11-02.

Composer · sources.directory.setting ❓ uncertain

No setting allows or forbids path repository dependencies (concluded from the config options in 06-config.md). Such packages come only from repositories declared in the root composer.json: "Repositories are not resolved recursively. You can only add them to your main composer.json. Repository declarations of dependencies' composer.jsons are ignored."

  • null · source, verified 2026-11-02.

Composer · project.workspaces ❓ uncertain

Composer has no workspaces; a monorepo links its packages with path repositories.

  • null · source, verified 2026-11-02.

Composer · project.workspacesObjectKey ❓ uncertain

No workspaces.

  • null · source, verified 2026-11-02.

Composer · extra.olderVersions ❓ uncertain

Read from the code at 2.10.3, not tested: fromConfig passes every key of policy but advisories, malware, abandoned and ignore-unreachable to CustomListPolicyConfig::fromRawConfig, which reads only block, audit, ignore and sources, and the schema at 2.10.3 does not reject period there. Config::merge keeps any unknown config key, and the schema of config has no additionalProperties: false.

  • Composer 2.10 reads policy.cooldown as a custom dependency policy without sources, which blocks nothing; older versions ignore config.policy as an unknown config key · source, verified 2026-11-02.

Bundler · cooldown.exclude.setting ❓ uncertain

No setting exempts single gems: the cooldown setting and --cooldown apply to every source, the keyword to one source, and settings.rb has no other cooldown key (concluded from the documented settings and the code). The documented way to take a newer version of one gem sooner is bundle update GEM --cooldown 0, with --conservative to keep its dependencies where they are (bundle-update(1)).

  • null · source, verified 2026-11-03.

Bundler · installScripts.allowList.setting ❓ uncertain

No setting allows or blocks the build of single gems (concluded from the documented settings); build.<gem> only passes flags to the build ("BUILD OPTIONS").

  • null · source, verified 2026-11-03.

Bundler · installScripts.disableAll ❓ uncertain

No setting or option turns the builds off (concluded from the documented settings of bundle-config(1) and the options of bundle-install(1)); force_ruby_platform even builds gems from source that have a precompiled platform gem.

  • null · source, verified 2026-11-03.

Bundler · sources.git.setting ❓ uncertain

No setting of bundle-config(1) allows or forbids git sources (concluded from the documented settings and the keys of settings.rb).

  • null · source, verified 2026-11-03.

Bundler · sources.remoteTarball.setting ❓ uncertain

Bundler has no archive URL source: a gem comes from a gem server (source), a git repository (git:, github: and the other git sources) or a directory (path:, which "must point to a directory containing the gem's unpacked source code, not to a packaged .gem file"); plugin sources are not covered.

  • null · source, verified 2026-11-03.

Bundler · sources.file.setting ❓ uncertain

Bundler has no local archive source: a gem comes from a gem server (source), a git repository (git:, github: and the other git sources) or a directory (path:, which "must point to a directory containing the gem's unpacked source code, not to a packaged .gem file"); plugin sources are not covered.

  • null · source, verified 2026-11-03.

Bundler · sources.directory.setting ❓ uncertain

No setting of bundle-config(1) allows or forbids path sources (concluded from the documented settings and the keys of settings.rb).

  • null · source, verified 2026-11-03.

Bundler · project.workspaces ❓ uncertain

Bundler has no workspaces: a Gemfile describes one bundle (concluded from gemfile(5)).

  • null · source, verified 2026-11-03.

Bundler · project.workspacesObjectKey ❓ uncertain

No workspaces.

  • null · source, verified 2026-11-03.

Renovate · cooldown.exclude.availableSince ❓ uncertain

Assumed to work since the option exists with packageRule scope; not stated by a release note.

  • 35.46.0 · source, verified 2026-10-28.

Renovate · installScripts.allowList.setting ❓ uncertain

No per-package allow-list was found: scripts are all or nothing, via allowScripts: true (self-hosted global config) plus ignoreScripts: false.

  • null · source, verified 2026-10-28.

Renovate · extra.pnpmSecurityExclusions ❓ uncertain

updatePnpmWorkspace: when a security update (vulnerability alert) changes a project with a pnpm lockfile whose pnpm-workspace.yaml sets minimumReleaseAge, Renovate adds the entry <name>@<version> to minimumReleaseAgeExclude with the comment "# Renovate security update: <name>@<version>" on the line above it; a later fix of the same package appends " || <version>" to the entry (and to the comment), and an entry for the package that has no comment gets one. The tests next to it (artifacts.spec.ts) show the written file. No other package manager (npm, Yarn, Bun, Deno) has such code at this tag; read from the code.

  • {"managers":["pnpm"],"file":"pnpm-workspace.yaml","setting":"minimumReleaseAgeExclude","comment":"# Renovate security update: ","versionSeparator":" || "} · source, verified 2026-10-30.

Renovate · extra.digestBypassFixed ⚠️ disputed

Digest updates could bypass minimumReleaseAge; the advisory and a maintainer comment give different fixed versions. Rebase requests could bypass strict checks before 44.61.3 (GHSA-2frq-pm48-6j4h).

  • Variant 1: 44.3.1 · source, verified 2026-10-28.
  • Variant 2: 44.10.0 · source, verified 2026-10-28.

Dependabot · cooldown.cliFlag ❓ uncertain

Cooldown is configured only in dependabot.yml; the Dependabot CLI README mentions no such flag.

  • null · source, verified 2026-10-28.

Dependabot · cooldown.exclude.availableSince ❓ uncertain

Presumably shipped with cooldown GA; not confirmed separately.

  • 2025-07-01 · source, verified 2026-10-28.

Dependabot · installScripts.defaultPolicy ❓ uncertain

From dependabot-core source, not the docs: npm, Yarn and Bun lockfile updates run with scripts disabled; for pnpm only --lockfile-only was found. bundler, mix and pip may execute external code.

  • all versions: deny · source, verified 2026-11-03.

Dependabot · installScripts.disableAll ❓ uncertain

Nothing to configure for JavaScript ecosystems: scripts are always disabled (source code). For bundler, mix and pip, external code execution is disabled automatically when registries are configured.

  • null · source, verified 2026-10-28.

Dependabot · extra.yamlMergeKeys ❓ uncertain

Not known. The options reference does not mention YAML anchors or merge keys, GitHub parses dependabot.yml in its own service, and the dependabot-core pull request that would allow aliases ("we can't use the YAML anchor (aliases) feature in dependabot.yml file") is still open and marked stale (read 2026-10-31). depcurfew reads dependabot.yml without merge keys: a cooldown that an entry would get only through <<: *defaults counts as missing, which bot-cooldown reports, and depcurfew apply writes the cooldown into the entry itself, which wins over merged keys where they apply.

  • false · source, verified 2026-10-31.

Dependabot · extra.actionsReleaseDate ❓ uncertain

Read from the code, not the docs. A proposed commit SHA is aged by published_at of the GitHub release of its tag, else the creatordate of the tag (git for-each-ref), else the commit date; version tags by the creatordate of each tag (refs_for_tag_with_detail in common/lib/dependabot/git_metadata_fetcher.rb), which is the tagger date of an annotated tag and the commit date of a lightweight one, both set in git by whoever makes them. Only default-days counts. A missing or unreadable date lets the update through (check_if_version_in_cooldown_period? returns false).

  • the publication date of the GitHub release of the tag, else the date of the tag, else the date of the commit; with no date the update does not wait · source, verified 2026-11-02.

Dependabot · extra.dayRange ⚠️ disputed

Matters for opting out of the default cooldown; cooldown.exclude: ["*"] works under the documented precedence rule either way. The announcement does not state its author's role.

  • Variant 1: 1 to 90 days · source, verified 2026-10-28.
  • Variant 2: 0 removes the cooldown · source, verified 2026-10-28.

Dependabot · extra.transitiveGating ❓ uncertain

Read from dependabot-core source.

  • Regular updates pass the cooldown to npm (11.10+), pnpm (10.16+) and Yarn Berry to hold back transitive dependencies; the Bun updater passes none · source, verified 2026-11-03.

Environment · botOnlyEcosystems.cargo.releaseAge ❓ uncertain

The changelog of the Cargo book on master lists under "Cargo 1.100 (2026-11-12)": "Stabilize minimum publish age configurations. When registry.global-min-publish-age is set, the resolver ignores versions published more recently than that, unless they are already in Cargo.lock" (RFC 3923, rust-lang/cargo#17335); reference/config.md on master documents registry.global-min-publish-age (default "0", values such as "14 days"), registries.<name>.min-publish-age and resolver.incompatible-publish-age, read from .cargo/config.toml. On 2026-11-03 Cargo 1.100 is not released: the latest Rust release is 1.99.1 of 2026-10-15 (RELEASES.md on the stable branch of rust-lang/rust), and Cargo 1.99 has the setting only behind the nightly flag -Zmin-publish-age (doc/book/src/reference/unstable.md at rust-1.99.0, which lists no stable setting in config.md). Uncertain because 1.100 is a planned release; until a repository runs Cargo 1.100, Cargo has no release-age delay of its own.

  • {"setting":"registry.global-min-publish-age","since":"1.100.0","product":"Cargo","file":".cargo/config.toml"} · source, verified 2026-11-03.

Environment · botOnlyEcosystems.gomod.releaseAge ❓ uncertain

Concluded from the absence of a setting: the documentation of the go command at go1.27.3, the latest tag on 2026-11-03, and the Go Modules Reference name no environment variable, go.mod directive or flag that holds back recently published module versions. The proposal for one, "cmd/go: support dependency cooldown in Go tooling" (https://github.com/golang/go/issues/76485), is open and was placed on hold by the proposal review group on 2026-06-25, which first explores a cooldown in the module proxy.

  • {"setting":null,"since":null} · source, verified 2026-11-03.

Environment · botOnlyEcosystems.maven.releaseAge ❓ uncertain

Concluded from the absence of a setting: Constants.java of Maven 4.0.0-rc-5 lists the maven.* properties Maven reads, and ConfigurationProperties.java of Maven Resolver 2.0.19 (https://github.com/apache/maven-resolver/blob/maven-resolver-2.0.19/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java) the aether.* properties of dependency resolution; none of them holds back recently published versions (no cooldown, publish date or minimum age).

  • {"setting":null,"since":null} · source, verified 2026-11-03.

Environment · botOnlyEcosystems.gradle.releaseAge ❓ uncertain

Concluded from the absence of a setting: ResolutionStrategy of Gradle 9.8.2, the latest release on 2026-11-03 (released-versions.json on master), has no setting that holds back recently published versions, and neither the release notes of 9.8.2 nor those of 9.9.0-rc-1 on master (platforms/documentation/docs/src/docs/release/notes.md) mention one.

  • {"setting":null,"since":null} · source, verified 2026-11-03.

Environment · botOnlyEcosystems.nuget.releaseAge ❓ uncertain

The accepted design "Package update cooldown V1" adds a minPublishAgeHours attribute to the package sources of nuget.config (whole hours; none means 0) and a <minPublishAgeExceptions> section; Visual Studio, dotnet package update and dotnet package list --outdated pick or report only versions published at least that long ago, while restore does no cooldown checks (it only fails for floating versions when cooldown is on). NuGet.Client merged it into dev in August and September 2026 (pull requests 7622 and 7713), and MinPublishAgeExceptions.cs is in the v11.0.100-rc.3.26522.148 tag of dotnet/dotnet but not in v10.0.403, the latest released SDK on 2026-11-03; the .NET 11 release on 2026-10-25 is 11.0.0-rc.3 (release-notes/11.0/releases.json in dotnet/core), and the nuget.config reference on learn.microsoft.com (reference/nuget-config-file.md) does not list minPublishAgeHours. Uncertain because .NET SDK 11.0.100 is not released.

  • {"setting":"minPublishAgeHours","since":"11.0.100","product":".NET SDK","updatesOnly":true,"file":"nuget.config"} · source, verified 2026-11-03.

Environment · corepack.defaults ⚠️ disputed

Corepack 0.36.0 runs the version lastKnownGood.json names for a package manager when no package.json above the current folder sets packageManager; without an entry it fetches the latest version of the npm package (yarn: Yarn Classic 1.x, which never reads .yarnrc.yml) and records it there, or with COREPACK_DEFAULT_TO_LATEST=0 uses its built-in default (getDefaultVersion in sources/Engine.ts). The code looks for the home folder in COREPACK_HOME, XDG_CACHE_HOME, LOCALAPPDATA (on every system) and then the home folder, using a variable that is set even when it is empty (??); the README leaves out XDG_CACHE_HOME and LOCALAPPDATA outside Windows. The code is what runs, so depcurfew follows it; the layout is the same since 0.13.0 (sources/folderUtils.ts), before which the folder was ~/.node/corepack. Values carry a hash after + (1.22.22+sha1.ac34...), which is not part of the version.

  • Variant 1: {"since":"0.13.0","locations":[{"platforms":["linux","darwin"],"directories":[{"from":{"env":"COREPACK_HOME","emptyCounts":true},"path":""},{"from":{"env":"XDG_CACHE_HOME","emptyCounts":true},"path":"node/corepack"},{"from":{"env":"LOCALAPPDATA","emptyCounts":true},"path":"node/corepack"},{"from":"home","path":".cache/node/corepack"}],"file":"lastKnownGood.json"},{"platforms":["win32"],"directories":[{"from":{"env":"COREPACK_HOME","emptyCounts":true},"path":""},{"from":{"env":"XDG_CACHE_HOME","emptyCounts":true},"path":"node/corepack"},{"from":{"env":"LOCALAPPDATA","emptyCounts":true},"path":"node/corepack"},{"from":"home","path":"AppData/Local/node/corepack"}],"file":"lastKnownGood.json"}]} · source, verified 2026-11-01. getCorepackHomeFolder: process.env.COREPACK_HOME ?? join(process.env.XDG_CACHE_HOME ?? process.env.LOCALAPPDATA ?? join(homedir(), process.platform === `win32` ? `AppData/Local` : `.cache`), `node/corepack`); sources/Engine.ts reads join(getCorepackHomeFolder(), `lastKnownGood.json`), a JSON object of package manager names and versions.
  • Variant 2: {"since":"0.13.0","locations":[{"platforms":["linux","darwin"],"directories":[{"from":{"env":"COREPACK_HOME"},"path":""},{"from":"home","path":".cache/node/corepack"}],"file":"lastKnownGood.json"},{"platforms":["win32"],"directories":[{"from":{"env":"COREPACK_HOME"},"path":""},{"from":{"env":"LOCALAPPDATA"},"path":"node/corepack"}],"file":"lastKnownGood.json"}]} · source, verified 2026-11-01. "COREPACK_HOME can be set in order to define where Corepack should install the package managers. By default it is set to %LOCALAPPDATA%\node\corepack on Windows, and to $HOME/.cache/node/corepack everywhere else."

Environment · docker.dockerfilePrefix ❓ uncertain

Dockerfile.<name> (Dockerfile.dev) is a common practice, but no Docker documentation that was read mentions it; depcurfew reads such files too, because they are Dockerfiles passed with --file.

  • Dockerfile. · source, verified 2026-11-01.

Environment · docker.nodeImageTags ❓ uncertain

Moving tags on 2026-10-28, when library/node was last generated: lts, lts-<codename>, current, latest and a variant alone (alpine, slim, bookworm) all mean 26.13.0. They move to another line without notice: after 26 became LTS no line is current, and how current and latest resolve once 27 is released is not documented. Tags of lines no longer built (20, iron, 18) are gone from library/node and are not updated any more.

  • {"tags":{"latest":"26","current":"26","lts":"26"}} · source, verified 2026-11-01.

Environment · docker.pythonImageTags ❓ uncertain

On 2026-11-01 latest, 3 and a variant alone (slim, alpine, trixie) mean 3.15.2 (aliases [3.15]='3 latest' in generate-stackbrew-library.sh); they move when a new line is released. X.Y-rc tags are prereleases.

  • {"tags":{"3":"3.15","latest":"3.15"}} · source, verified 2026-11-01.

Environment · npmRegistry.notFoundStatus ❓ uncertain

The API description leaves its Errors section empty; a name that does not exist answered 404 with {"error":"Not found"} on 2026-10-29.

  • 404 · source, verified 2026-10-29.

Environment · npmRegistry.search ❓ uncertain

The description documents text, size (at most 250) and from. Results carried downloads.weekly on 2026-10-29, which the description does not list, and from was ignored, so one query returns at most 250 packages.

  • {"path":"/-/v1/search","maxSize":250,"weeklyDownloadsField":"downloads.weekly"} · source, verified 2026-10-29.

Environment · claudeCode.hookContext ❓ uncertain

The PreToolUse decision control table lists additionalContext in hookSpecificOutput as "String added to Claude's context alongside the tool result. Ignored when permissionDecision is "defer"", next to permissionDecision, permissionDecisionReason and updatedInput, and #add-context-for-claude says Claude Code wraps the string in a system reminder that Claude reads on the next model request, places it next to the tool result for PreToolUse, writes a value over 10,000 characters to a file and passes its path with a preview of 2,000 characters, and recommends factual statements over imperative instructions. Uncertain: the page does not say in so many words that additionalContext works without permissionDecision; the table ties it to no decision but defer, and an output without permissionDecision leaves the call to the normal permission flow.

  • {"field":"additionalContext","withoutDecision":true,"inlineLimit":10000} · source, verified 2026-11-01.