Set a minimum release age on local package managers so installs ignore versions younger than N days. Most malicious packages are caught and yanked within days of publishing; refusing fresh versions blocks the bulk of supply-chain attacks.
uvx gestate # interactive
uvx gestate set 3 # 3-day minimum, installed tools only
uvx gestate set 3 --all # also pre-configure file-based tools (bun, deno, uv)
uvx gestate revert # remove gestate's settings
uvx gestate explain bun # show how one tool's setting is stored
uvx gestate trust my-pkg --python # exempt a package from the age delay
uvx gestate trust --rm my-pkg # remove an exemption
uvx gestate trust # list trusted packages
Interactive mode always shows a plan and asks for explicit confirmation before touching anything. The subcommands skip the confirm — meant for scripts, not your daily shell. Running with no subcommand outside a TTY exits with an error.
Plain text output is used when stdout isn't a terminal (no Rich tables/colors).
| Tool | Where | Key (unit) |
|---|---|---|
| npm | ~/.npmrc |
min-release-age (days) |
| pnpm | global pnpm config | minimumReleaseAge (minutes) |
| yarn | ~/.yarnrc.yml (4.10+) |
npmMinimalAgeGate (minutes) |
| bun | ~/.bunfig.toml |
[install] minimumReleaseAge (seconds) |
| deno | shell profile | alias deno='command deno --minimum-dependency-age=P<N>D' |
| pip | user pip config | global.uploaded-prior-to (P<N>D) |
| uv | ~/.config/uv/uv.toml |
exclude-newer ("N days") |
gestate explain <tool> prints that tool's current value and the exact mechanism set / revert use.
Scope:
- default — only configure installed tools
--all— also pre-write config files forbun,deno,uveven if they aren't installed yet
uvx gestate revert removes everything gestate set:
- CLI tools —
config delete/config unset bun/uv— remove the key; delete the file if it was the only keydeno— remove our alias line; leave foreignalias deno=lines alone
Backups (.bak) are written next to any edited shell-profile or TOML file.
gestate trust lets you exempt specific packages from the age delay so they always get the latest version:
gestate trust @myorg/* # auto-detects Node (scoped package)
gestate trust my-lib --python # exempt in uv
gestate trust --rm my-lib --python # remove exemption
gestate trust # list all trusted packages
gestate trust --python # list Python ecosystem only
The --python / --node flags are optional — gestate auto-detects the ecosystem from scoped packages (@scope/name → Node) or the current directory (pyproject.toml → Python, package.json → Node). When it can't tell, it asks you to specify.
Supported tools: bun, uv, yarn, pnpm (project-local only). npm, deno, and pip don't support per-package allowlists and print a warning. For manual config details, see docs/allowlists.md.
- yarn: 4.10+ only. Older yarn is detected and skipped.
- deno: no global config exists; the shell alias only covers interactive shells. For CI, pass
--minimum-dependency-age=P<N>Dtodeno install/deno update, or commit a projectdeno.jsonwith"minimumDependencyAge": "P<N>D". - npm exclude: tracked in npm/cli#8994.
- pip exclude: none —
global.uploaded-prior-tois global only.
For PR-creation guards (Dependabot, Renovate) and adjacent layers, see docs/complementary.md.
uv sync
uv run pytest
Requires Python 3.11+, macOS or Linux.