upd
A fast dependency updater for Python, Node.js, Rust, and Go projects, written in Rust.
Quick Start
# Run without installing (using uv)
# Or with pipx
# Preview changes without modifying files
Features
- Multi-ecosystem: Python, Node.js, Rust, and Go dependencies
- Fast: Parallel registry requests for all dependencies
- Constraint-aware: Respects version constraints like
>=2.0,<3 - Smart caching: 24-hour version cache for faster subsequent runs
- Update filters: Filter by
--major,--minor, or--patchupdates - Interactive mode: Approve updates individually with
-i - Check mode: Exit with code 1 if updates available (for CI/pre-commit)
- Major warnings: Highlights breaking changes with
(MAJOR) - Format-preserving: Keeps formatting, comments, and structure
- Pre-release aware: Updates pre-releases to newer pre-releases
- Gitignore-aware: Respects
.gitignorewhen discovering files - Version alignment: Align package versions across multiple files
- Security auditing: Check dependencies for known vulnerabilities via OSV
Installation
From crates.io
# or with cargo-binstall (faster, pre-built binary)
From PyPI
# or with uv
From source
Usage
# Update all dependency files in current directory
# Update specific files or directories
# Dry-run mode (preview changes without writing)
# Verbose output
# Disable colored output
# Disable caching (force fresh lookups)
# Filter by update type
# Combine filters
# Interactive mode - approve updates one by one
# Filter by language/ecosystem
# Version precision
# Check mode - exit with code 1 if updates available (for CI/pre-commit)
Commands
# Show version
# Check for upd updates
# Clear version cache
# Align versions across files (use highest version found)
# Check for security vulnerabilities
Supported Files
Python
requirements.txt,requirements-dev.txt,requirements-*.txtrequirements.in,requirements-dev.in,requirements-*.indev-requirements.txt,*-requirements.txt,*_requirements.txtpyproject.toml(PEP 621 and Poetry formats)
Node.js
package.json(dependenciesanddevDependencies)
Rust
Cargo.toml([dependencies],[dev-dependencies],[build-dependencies])
Go
go.mod(requireblocks)
Example Output
pyproject.toml:12: Would update requests 2.28.0 → 2.31.0
pyproject.toml:13: Would update flask 2.2.0 → 3.0.0 (MAJOR)
Cargo.toml:8: Would update serde 1.0.180 → 1.0.200
Cargo.toml:9: Would update tokio 1.28.0 → 1.35.0
Would update 4 package(s) in 2 file(s), 15 up to date
Output includes clickable file:line: locations (recognized by VS Code, iTerm2, and modern terminals).
Version Precision
By default, upd preserves version precision from the original file:
# Original file has 2-component versions
flask>=2.0 → flask>=3.1 (not 3.1.5)
django>=4 → django>=6 (not 6.0.0)
# Original file has 3-component versions
requests>=2.0.0 → requests>=2.32.5
Use --full-precision to always output full semver versions:
upd --full-precision
flask>=2.0 → flask>=3.1.5
django>=4 → django>=6.0.0
requests>=2.0.0 → requests>=2.32.5
Version Alignment
In monorepos or projects with multiple dependency files, the same package might have different versions:
# requirements.txt
requests==2.28.0
# requirements-dev.txt
requests==2.31.0
# services/api/requirements.txt
requests==2.25.0
Use upd align to update all occurrences to the highest version found:
Behavior:
- Only aligns packages within the same ecosystem (Python with Python, etc.)
- Skips packages with upper bound constraints (e.g.,
>=2.0,<3.0) to avoid breaking them - Ignores pre-release versions when finding the highest version
Security Auditing
Check your dependencies for known security vulnerabilities using the OSV (Open Source Vulnerabilities) database:
Example output:
Checking 42 unique package(s) for vulnerabilities...
⚠ Found 3 vulnerability/ies in 2 package(s):
● requests@2.19.0 (PyPI)
├── GHSA-j8r2-6x86-q33q [CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:N/A:N] Unintended leak of Proxy-Authorization header
│ Fixed in: 2.31.0
│ https://github.com/psf/requests/security/advisories/GHSA-j8r2-6x86-q33q
● flask@0.12.2 (PyPI)
├── GHSA-562c-5r94-xh97 [CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H] Denial of Service vulnerability
│ Fixed in: 0.12.3
│ https://nvd.nist.gov/vuln/detail/CVE-2018-1000656
├── GHSA-m2qf-hxjv-5gpq [CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N] Session cookie disclosure
│ Fixed in: 2.3.2
│ https://github.com/pallets/flask/security/advisories/GHSA-m2qf-hxjv-5gpq
Summary: 2 vulnerable package(s), 3 total vulnerability/ies
Features:
- Queries the OSV API (free, no API key required)
- Supports all ecosystems: PyPI, npm, crates.io, Go
- Deduplicates packages across files
- Shows severity scores (CVSS), descriptions, and fixed versions
- Batch queries for efficiency (up to 1000 packages per request)
CI/CD Integration:
# GitHub Actions example
- name: Check for vulnerabilities
run: upd audit --check
# Pre-commit hook (.pre-commit-config.yaml)
repos:
- repo: local
hooks:
- id: upd-audit
name: security audit
entry: upd audit --check
language: system
pass_filenames: false
stages:
Version Constraints
upd respects version constraints in your dependency files:
| Constraint | Behavior |
|---|---|
>=2.0,<3 |
Updates within 2.x range only |
^2.0.0 |
Updates within 2.x range (npm/Cargo) |
~2.0.0 |
Updates within 2.0.x range (npm) |
>=2.0 |
Updates to any version >= 2.0 |
==2.0.0 |
No updates (pinned) |
Caching
Version lookups are cached for 24 hours in:
- macOS:
~/Library/Caches/upd/versions.json - Linux:
~/.cache/upd/versions.json - Windows:
%LOCALAPPDATA%\upd\versions.json
Use upd clean-cache to clear the cache, or upd --no-cache to bypass it.
Private Repositories
upd supports private package registries for all ecosystems. Credentials are automatically detected from environment variables and configuration files.
PyPI / Private Python Index
# Option 1: Environment variables
# Option 2: PIP-style environment variables
# Option 3: ~/.netrc file
# machine my-private-pypi.com
# login myuser
# password mypassword
# Option 4: Inline in requirements.txt (with credentials)
# --index-url https://user:pass@my-private-pypi.com/simple
# or just the URL (credentials from netrc):
# --index-url https://my-private-pypi.com/simple
Inline index URLs: When a requirements.txt file contains --index-url or -i,
upd automatically uses that index instead of the default PyPI. Credentials can be
embedded in the URL (https://user:pass@host/simple) or looked up from ~/.netrc.
npm / Private Registry
# Option 1: Environment variables
# Option 2: NODE_AUTH_TOKEN (GitHub Actions)
# Option 3: ~/.npmrc file
//npm.mycompany.com/:_authToken=your-auth-token
# Or for environment variable reference:
//npm.mycompany.com/:_authToken=
Cargo / Private Registry
# Option 1: Environment variables
# For crates.io default
# For named registry
# Option 2: ~/.cargo/credentials.toml
Go / Private Module Proxy
# Option 1: Environment variables
# Option 2: ~/.netrc file (commonly used with go modules)
# machine proxy.mycompany.com
# login myuser
# password mypassword
Use --verbose to see when authenticated access is being used:
# Output: Using authenticated PyPI access
# Output: Using authenticated npm access
Environment Variables
| Variable | Description |
|---|---|
UV_INDEX_URL |
Custom PyPI index URL |
PIP_INDEX_URL |
Custom PyPI index URL (fallback) |
UV_INDEX_USERNAME |
PyPI username (with UV_INDEX_URL) |
UV_INDEX_PASSWORD |
PyPI password (with UV_INDEX_URL) |
PIP_INDEX_USERNAME |
PyPI username (with PIP_INDEX_URL) |
PIP_INDEX_PASSWORD |
PyPI password (with PIP_INDEX_URL) |
NPM_REGISTRY |
Custom npm registry URL |
NPM_TOKEN |
npm authentication token |
NODE_AUTH_TOKEN |
npm token (GitHub Actions compatible) |
CARGO_REGISTRY_TOKEN |
crates.io authentication token |
CARGO_REGISTRIES_<NAME>_TOKEN |
Named registry token |
GOPROXY |
Custom Go module proxy URL |
GOPROXY_USERNAME |
Go proxy username |
GOPROXY_PASSWORD |
Go proxy password |
UPD_CACHE_DIR |
Custom cache directory |
Development
# Build
# Run tests
# Lint
# Format
# All checks
License
MIT