Quickstart
This guide takes you from a blank shell to a passing chill-out check in about five minutes. It assumes you already
have a Python or npm project lying around; if not, the smallest possible fixtures live under examples/.
Install
If you live in uv-land:
Run a check
cd into any project that has either a pyproject.toml or a package.json and run:
chill-out auto-detects the ecosystem, loads the cooldown thresholds, reads your lockfile, and prints a table of any
violations. Every package in the lockfile gets audited, principals and transitives alike, since the lockfile is what
actually gets installed. The exit code is 0 if everything is clear and 2 if at least one dependency is still
inside its cooldown window.
For pypi projects the lockfile is uv.lock, and it's required: if it's missing, chill-out asks you to run uv lock
first rather than guessing at what would be resolved. For npm projects the lockfile is package-lock.json (or its
copy under node_modules/), read via npm list.
Read the output
A violation row looks roughly like this:
2 cooldown violation(s) in 14 pypi package(s):
┌────────────────────────────────────┬───────────┬──────────────────────────────┐
│ Package │ Limit │ Strategy │
├────────────────────────────────────┼───────────┼──────────────────────────────┤
│ requests = 2.31.0 (age 3d > 10d) │ minor 10d │ requests -> 2.30.0 (45d old) │
│ urllib3 = 2.0.7 (age 1d > 10d) │ minor 10d │ urllib3 -> 2.0.6 (60d old) │
└────────────────────────────────────┴───────────┴──────────────────────────────┘
The "Package" column shows the violating dep with its installed version and the age vs limit called out. For a transitive violation, the column renders as a tree from the principal down to the violating leaf, and the "Limit" column shows a parallel tree so you can see each chain member's release type and threshold side by side. The "Strategy" column tells you exactly which package to pin and to what version, so it's unambiguous that the fix targets the transitive rather than rolling the principal back.
Apply a fix
Run chill-out fix to rewrite your manifest and re-resolve:
For npm projects, this pins each violating dep to its safe version directly in dependencies (the resolver hoists
transitive pins above whatever the principal asks for) and runs npm install. For Python projects, it pins each
violating dep to its safe version inside pyproject.toml and runs uv lock. When a transitive conflict can't be
resolved by hoisting alone, the principal gets rolled back to a version that admits the safe transitive.
After applying fixes, chill-out re-runs the check automatically so you can see whether the fix actually cleared every
violation. Pass --no-recheck to skip that second pass.
Wire it into CI
The exit code is the contract:
# .github/workflows/cooldown.yml
- name: Check dependency cooldown
run: |
pip install chill-out
chill-out check --fast --quiet
If a violation appears, the job fails with exit code 2 and the table is in the log. See GitHub Actions for the full set of recipes: scheduled audits, separating cooldown signal from the test matrix, opening issues from violations, and more.
Speed knobs
--fast skips the safe-version lookup, which saves one extra registry round trip per violating package. Use it in CI
where you only care about pass/fail; the report still names the violating package, it just doesn't suggest a rollback
target.
Next stops
- Configuration for tuning the thresholds
- CLI for every flag
- GitHub Actions for CI recipes
- Programmatic API for calling
chill-outfrom your own code