Skip to main content

depkeeper

Tests Coverage PyPI Python versions License: Apache-2.0 Docs

Safe, conflict-aware dependency updates for pip requirements files.

depkeeper analyses requirements.txt-style files, computes a safe upgrade target for every requirement, cross-validates those targets against each other, and rewrites the file in place — without discarding the constraints you authored.

It is a single-purpose CLI. It does not manage virtual environments, install packages, replace pip, or introduce a lock file format.


Contents


Why depkeeper

pip list --outdated reports the latest version, which is frequently a major release that will break your build. Lock-file tools solve this properly but require adopting a new workflow and file format.

depkeeper fills the gap. It answers one question, precisely:

What is the largest upgrade I can take for each requirement without crossing a major version, without breaking Python compatibility, without violating the constraints I declared, and without conflicting with the other packages in my file?

Then it applies the answer to the file you already have.

pip pip-tools Poetry depkeeper
Reports available updates latest only no yes yes, with a safe target
Enforces major-version boundaries no no no yes
Preserves your declared ranges on write n/a regenerates rewrites yes
Full transitive resolution at install time yes yes no — see Limitations
Requires a new file format no .in files pyproject.toml + lock no

What it guarantees

These are enforced in code, not advisory:

Guarantee Meaning
Major-version boundary A package on 1.x is never moved to 2.x.
Python compatibility Releases whose requires_python excludes your interpreter are never proposed.
Constraint preservation Upper bounds, exclusions and ~= bands are preserved verbatim and never violated.
No pre-releases Alpha/beta/rc versions are excluded from every candidate list.
Atomic, reversible writes Multi-file updates are all-or-nothing, with rollback and optional backups.
Hash integrity Updates that would strip --hash entries are refused unless explicitly allowed.
Clean stdout --format json puts the payload on stdout and every diagnostic on stderr.
Idempotency Re-running produces no change. Safe to run on a schedule.

The trade-off is explicit: depkeeper is deliberately conservative. It will never propose the major upgrade you eventually need.


Install

python -m pip install depkeeper     # into the project's environment (recommended)
pipx install depkeeper              # isolated global tool

Requires Python 3.8+.

[!IMPORTANT] depkeeper filters candidate versions against the interpreter it runs on, not your project's. Installing it on 3.8 while your service targets 3.12 makes recommendations silently conservative. Install it into the project environment, or use pipx install --python python3.12 depkeeper.

Verify:

depkeeper --version        # depkeeper 0.1.1
python -m depkeeper --help # equivalent module entry point

Quick start

Given this file:

requests==2.28.0
flask>=2.0,<2.3
celery[redis]>=5.0,<6.0
click~=8.0
certifi
urllib3==1.26.0

1. Inspect (read-only, never writes):

$ depkeeper check
┏━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃   Status   ┃ Package  ┃ Current ┃  Latest   ┃ Recommended ┃ Update Type ┃ Conflicts ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ [OUTDATED] │ requests │ 2.28.0  │  2.34.2   │   2.34.2    │    minor    │ -         │
│ [OUTDATED] │ flask    │   2.0   │   3.1.3   │    2.2.5    │    minor    │ -         │
│ [OUTDATED] │ celery   │   5.0   │   5.6.3   │    5.6.3    │    minor    │ -         │
│ [OUTDATED] │ click    │   8.0   │   8.4.2   │    8.4.2    │    minor    │ -         │
│    [OK]    │ certifi  │    -    │ 2026.7.22 │      -      │      -      │ -         │
│ [OUTDATED] │ urllib3  │ 1.26.0  │   2.7.0   │   1.26.20   │    patch    │ -         │
└────────────┴──────────┴─────────┴───────────┴─────────────┴─────────────┴───────────┘
[WARNING] 5 package(s) have updates available

2. Preview the exact write:

depkeeper update --dry-run

3. Apply:

$ depkeeper update --backup
Update 6 packages? (y, n) [y]: y
[OK] ✓ Successfully updated 6 package(s)
requests==2.34.2
flask>=2.2.5,<2.3          # your <2.3 cap held — latest is 3.1.3
celery[redis]>=5.6.3,<6.0  # extra and upper bound preserved
click~=8.4                 # compatible-release form preserved
certifi==2026.7.22         # unversioned requirement gained a pin
urllib3==1.26.20           # major boundary held — latest is 2.7.0

4. Verify — this step is not optional:

python -m pip install -r requirements.txt && pytest

depkeeper validates the packages you declared against each other. It does not expand the transitive graph, so pip remains the authority on whether the set installs.


Commands

depkeeper check [FILE]

Read-only analysis. Never modifies the filesystem. Exits 0 on success regardless of findings.

Option Description
--outdated-only Show only packages with an update or a conflict
-f, --format table|simple|json Output format (default table)
--strict-version-matching Only a sole == pin counts as a current version
--check-conflicts / --no-check-conflicts Cross-package conflict resolution (default on)

depkeeper update [FILE]

Applies recommended versions in place.

Option Description
--dry-run Run the full pipeline, print the plan, write nothing
-y, --yes Skip the confirmation prompt
--backup Timestamped backup of every affected file before writing
--pin Replace every specifier with an exact == pin
--allow-hash-removal Permit updating --hash-pinned requirements (removes the digests)
-p, --packages NAME Restrict to specific packages (repeatable)
--strict-version-matching As above
--check-conflicts / --no-check-conflicts As above

Global options

-c/--config PATH · -v / -vv (INFO / DEBUG, always on stderr) · --color/--no-color · --version · -h/--help

Global options must precede the subcommand: depkeeper -v check, not depkeeper check -v.

Full specification: CLI reference.

Exit codes

Code Meaning
0 Success — including "updates are available"
1 Application error (parse, config, write, refused hash removal)
2 Usage error (unknown option, missing file)
130 Interrupted (Ctrl+C)

Gate automation on the JSON payload, never on check's exit code.


Configuration

Two settings are persistable, in depkeeper.toml or pyproject.toml. Everything else is a per-invocation flag, deliberately — options that change what gets written stay visible in the command line.

# depkeeper.toml
[depkeeper]
check_conflicts = true            # cross-package conflict resolution
strict_version_matching = false   # treat only `==` as a current version
# pyproject.toml
[tool.depkeeper]
check_conflicts = true
strict_version_matching = false

Precedence: defaults < config file < CLI flag. Unknown keys and wrong types are hard errors. Discovery is limited to the current working directory (not recursive).

Environment: DEPKEEPER_CONFIG, DEPKEEPER_COLOR, NO_COLOR, CI, plus httpx's HTTPS_PROXY / SSL_CERT_FILE.


Common workflows

Daily

depkeeper check --outdated-only
depkeeper update --dry-run
depkeeper update --backup && pip install -r requirements.txt && pytest

One package at a time (keeps regressions bisectable)

depkeeper update -p django -y && pytest

Application release — freeze to exact versions

depkeeper update --pin --backup

CI drift report — stdout stays parseable even with -v

depkeeper -v check --format json --no-check-conflicts > report.json 2> depkeeper.log
jq '[.[] | select(.status == "outdated")] | length' report.json

Multi-file projects-r includes are followed and rewritten

depkeeper update requirements/dev.txt --dry-run   # also writes base.txt

Hash-pinned files — depkeeper refuses these by default

depkeeper update --allow-hash-removal -y
pip-compile --generate-hashes requirements.in     # regenerate; not optional

More: User guide · CI/CD integration


Architecture

Synchronous CLI around an asynchronous core. No daemon, no persistent state, no cache directory.

requirements.txt
      │
      ▼
RequirementsParser ──► PyPIDataStore ──► VersionChecker ──► DependencyAnalyzer ──┐
  (text → model)      (one HTTP call     (per-package      (cross-package         │
                       per package)       target version)   consistency)          │
                                                                                  ▼
                                                             renderer (table/simple/json)
                                                             writer (atomic, rollback-safe)
Component Responsibility
core/parser.py Requirements text → Requirement objects, -r/-c resolution, provenance
core/data_store.py PyPI metadata cache with per-key request coalescing
core/checker.py Per-package recommendation under boundary, Python and constraint filters
core/dependency_analyzer.py Iterative conflict resolution within major boundaries
commands/ User interaction, rendering, the write pipeline, exit codes
utils/ HTTP, console, logging, atomic filesystem, naming, version algebra

See ARCHITECTURE.md for the contributor-facing map, or the architecture deep dive for design decisions, concurrency model and error propagation.


Limitations

Honest, verified, and documented in full at Known limitations. The ones most likely to affect you:

  • Not a resolver. The transitive graph is not expanded. Always pip install and test.
  • Only pypi.org is queried. --index-url lines are parsed and ignored; private packages report as errors.
  • Calendar versions hit the major boundary. certifi 2023.x never auto-bumps to 2024.x.
  • Major upgrades are yours to make. Raise the floor by hand, then let depkeeper continue.
  • Backslash line continuations are not parsed, so default pip-compile --generate-hashes output is unreadable to depkeeper.
  • No runtime tuning. Timeouts, retries and concurrency are constants; override them via the Python API if you must.

Troubleshooting

Start here:

depkeeper -vv check --format json > report.json 2> debug.log

debug.log names the file parsed, the effective configuration, every HTTP retry and every resolution decision.

Symptom Cause
Recommendation far below Latest Your declared cap, the major boundary, a conflict, or requires_python
Recommendations differ between laptop and CI Different Python versions running depkeeper
✗ ERROR rows Package not on public PyPI, network/proxy failure, or TLS interception
update changed a package check showed as ✓ OK Unversioned requirement — it received a pin
A proposed downgrade Declared version is unusable; review before accepting

Full guide: Troubleshooting


Documentation

Published at rahulkaushal04.github.io/depkeeper.

Section Contents
Getting started Install, quick start, reading the output
Concepts Architecture, version recommendation, conflict resolution, parsing, write safety
User guide Checking, updating, configuration, CI/CD, operations, best practices, troubleshooting
Reference CLI, config, exit codes, file formats, JSON schema, errors, limitations, Python API
Contributing Setup, code style, testing, extending, releases

Repository documents: ARCHITECTURE.md · CONTRIBUTING.md · CHANGELOG.md · SECURITY.md · SUPPORT.md · CODE_OF_CONDUCT.md


Project status

Version 0.1.1, classified Development Status :: 4 - Beta.

The write path is defensive — atomic replacement, two-phase commit, rollback, optional backups — and behaviour is documented and covered by tests across Linux, macOS and Windows on Python 3.8–3.12. Pin the version in automation: recommendation logic is a behavioural contract, and a version bump can legitimately change an update plan.


Contributing

Contributions are welcome. Start with CONTRIBUTING.md, and read the system invariants before changing anything in core/.

git clone https://github.com/rahulkaushal04/depkeeper.git
cd depkeeper
pip install -e ".[dev,docs]"
pre-commit install

python -m pytest tests -q --no-cov
python -m mypy depkeeper --python-version 3.13

Report vulnerabilities privately — see SECURITY.md, never a public issue.


License

Apache License 2.0. Copyright 2025-2026 Rahul Kaushal.

Built with Click, Rich, httpx and packaging — the last of which is why depkeeper agrees with pip about what a version means.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

depkeeper-0.1.1.tar.gz (104.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

depkeeper-0.1.1-py3-none-any.whl (107.4 kB view details)

Uploaded Python 3

File details

Details for the file depkeeper-0.1.1.tar.gz.

File metadata

  • Download URL: depkeeper-0.1.1.tar.gz
  • Upload date:
  • Size: 104.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for depkeeper-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bec25e06f363a0c2123a56a52e6f4d32ffee89210868b7f3ba62360ffc106847
MD5 a43ad8fb04c4cf97d012cdf59f0134f0
BLAKE2b-256 143f7cd0633963bde6aba45ebc0faa566b6e223f948e17ed69acf60b78c1e9b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for depkeeper-0.1.1.tar.gz:

Publisher: publish.yml on rahulkaushal04/depkeeper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file depkeeper-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: depkeeper-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 107.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for depkeeper-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7f28842cbb2e80b6d908d2e2ef9d5147a366c184af94dd2b8541f03827be963e
MD5 bf90ac0e0c4f8e02d2692426787af349
BLAKE2b-256 9c042b24c783b78b7876be669b08e97c91f02f5af1f1e56f5ac2cc2c61229bb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for depkeeper-0.1.1-py3-none-any.whl:

Publisher: publish.yml on rahulkaushal04/depkeeper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page