{"id":36956570,"url":"https://github.com/rvben/upd","last_synced_at":"2026-04-25T20:03:12.880Z","repository":{"id":328202433,"uuid":"1112387352","full_name":"rvben/upd","owner":"rvben","description":"A fast dependency updater for Python and Node.js projects","archived":false,"fork":false,"pushed_at":"2026-04-24T06:04:21.000Z","size":1509,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-24T08:10:33.146Z","etag":null,"topics":["cli","dependency-management","developer-tools","nodejs","python","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rvben.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-08T14:56:56.000Z","updated_at":"2026-04-24T06:04:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rvben/upd","commit_stats":null,"previous_names":["rvben/upd"],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/rvben/upd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvben%2Fupd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvben%2Fupd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvben%2Fupd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvben%2Fupd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rvben","download_url":"https://codeload.github.com/rvben/upd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvben%2Fupd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32274987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","dependency-management","developer-tools","nodejs","python","rust"],"created_at":"2026-01-13T14:01:14.225Z","updated_at":"2026-04-25T20:03:12.874Z","avatar_url":"https://github.com/rvben.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/logo-wide.svg\" alt=\"upd logo\" width=\"400\"\u003e\n\u003c/p\u003e\n\n# upd\n\nA fast dependency updater for Python, Node.js, Rust, Go, Ruby, .NET, Terraform, GitHub Actions, pre-commit, and Mise projects, written in Rust.\n\n## Quick Start\n\n```bash\n# Preview changes without modifying files (default)\nuvx --from upd-cli upd\n\n# Apply updates\nuvx --from upd-cli upd --apply\n\n# Or with pipx\npipx run --spec upd-cli upd --apply\n```\n\n## Features\n\n- **Multi-ecosystem**: Python, Node.js, Rust, Go, Ruby, .NET, Terraform, GitHub Actions, pre-commit, Mise/asdf\n- **Fast**: Parallel registry requests for all dependencies\n- **Constraint-aware**: Respects `\u003e=2.0,\u003c3` (Python), `~\u003e 7.1` (Ruby), and `^2.0.0` / `~2.0.0` (npm, Cargo).\n  For npm, comparator ranges such as `\"\u003e=1.0.0 \u003c2.0.0\"` are rewritten with a **bump strategy**: the lower\n  bound moves to the highest version satisfying the constraint, preserving the upper bound. Hyphen\n  (`\"1 - 2\"`) and OR (`\"^1 || ^2\"`) ranges are reported as warnings and left untouched.\n- **Smart caching**: 24-hour version cache for faster subsequent runs\n- **Update filters**: Filter by bump level with `--only-bump \u003cmajor|minor|patch\u003e` (repeatable) or cap with `--max-bump`\n- **Interactive mode**: Approve updates individually with `-i`\n- **Check mode**: Exit with code 1 if updates available (for CI/pre-commit)\n- **Major warnings**: Highlights breaking changes with `(MAJOR)`\n- **Format-preserving**: Keeps formatting, comments, and structure\n- **Pre-release aware**: Updates pre-releases to newer pre-releases\n- **Gitignore-aware**: Respects `.gitignore` when discovering files\n- **Version alignment**: Align package versions across multiple files\n- **Security auditing**: Check dependencies for known vulnerabilities via OSV\n- **Config file support**: Ignore or pin packages via `.updrc.toml`\n- **Private registries**: Authentication for PyPI, npm, Cargo, Go, and GitHub\n\n## Installation\n\n### From crates.io\n\n```bash\ncargo install upd\n\n# or with cargo-binstall (faster, pre-built binary)\ncargo binstall upd\n```\n\n### From PyPI\n\n```bash\npip install upd-cli\n# or with uv\nuv pip install upd-cli\n```\n\n### From source\n\n```bash\ngit clone https://github.com/rvben/upd\ncd upd\ncargo install --path .\n```\n\n## Usage\n\n```bash\n# Preview changes without modifying files (default when no --apply)\nupd\n\n# Apply updates to files\nupd --apply\n\n# Update specific files or directories (still dry-run without --apply)\nupd requirements.txt pyproject.toml\n\n# Apply updates to specific files\nupd --apply requirements.txt pyproject.toml\n\n# Dry-run mode (explicit; same as omitting --apply)\nupd -n\nupd --dry-run\n\n# Verbose output\nupd -v\nupd --verbose\n\n# Suppress decorative output (errors still shown)\nupd --quiet\nupd -q\n\n# Disable colored output\nupd --no-color\n\n# Disable caching (force fresh lookups)\nupd --no-cache\n\n# Filter to only the named packages\nupd --package requests\nupd --package requests --package flask\nupd --package requests,flask\n\n# Filter by bump level (only exact levels)\nupd --only-bump major      # Show only major (breaking) updates\nupd --only-bump minor      # Show only minor updates\nupd --only-bump patch      # Show only patch updates\n\n# Combine filters (repeat --only-bump or comma-separate)\nupd --only-bump major --only-bump minor\nupd --only-bump major,minor\n\n# Cap by bump level (include up to and including this level)\nupd --max-bump minor       # Allow patch + minor, skip major\nupd --max-bump patch       # Allow patch only\n\n# Interactive mode - approve updates one by one\nupd -i\nupd --interactive\n\n# Filter by language/ecosystem\nupd --lang python           # Update only Python dependencies\nupd -l rust                 # Short form\nupd --lang python --lang go # Update Python and Go only\nupd --lang actions          # Update only GitHub Actions\nupd --lang pre-commit       # Update only pre-commit hooks\nupd --lang ruby             # Update only Ruby gems\nupd --lang dot-net          # Update only .NET NuGet packages\nupd --lang terraform        # Update only Terraform providers/modules\nupd --lang mise             # Update only Mise/asdf tools\n\n# Version precision\nupd --full-precision  # Output full versions (e.g., 3.1.5 instead of 3.1)\n\n# Check mode - exit with code 1 if updates available (for CI/pre-commit)\nupd --check\nupd --check --lang python  # Check only Python dependencies\n\n# Print effective configuration and exit\nupd --show-config\n\n# Use a specific config file\nupd --config /path/to/config.toml\nupd -c .updrc.toml         # Short form\n```\n\n\u003e **Dry-run by default**: `upd` without `--apply` only previews changes. Pass `--apply` to\n\u003e write updates. `--check`, `--dry-run`, and `--interactive` do not require `--apply`.\n\u003e\n\u003e **VCS-root scoping**: When no path argument is given, `upd` scans from the nearest `.git`\n\u003e ancestor directory rather than the current working directory. This prevents accidental\n\u003e rewrites when CWD is a subdirectory inside a repository.\n\n### Commands\n\n```bash\n# Show version\nupd --version\n\n# Check for upd updates\nupd self-update\n\n# Clear version cache\nupd clean-cache\n\n# Align versions across files (use highest version found)\nupd align\nupd align --check  # Exit 1 if misalignments found (for CI)\n\n# Check for security vulnerabilities\nupd audit\nupd audit --check  # Exit 1 if vulnerabilities are found or the audit can't complete (for CI)\n\n# Auto-fix vulnerable packages to minimum safe version, then write changes\nupd audit --fix-audit --apply\n\n# Run audit using only the local cache (no network; cache misses are errors)\nupd audit --offline\n\n# Emit SARIF 2.1.0 for GitHub Code Scanning upload\nupd audit --format sarif \u003e results.sarif\n```\n\n## Supported Files\n\n### Python\n\n- `requirements.txt`, `requirements-dev.txt`, `requirements-*.txt`\n- `requirements.in`, `requirements-dev.in`, `requirements-*.in`\n- `dev-requirements.txt`, `*-requirements.txt`, `*_requirements.txt`\n- `pyproject.toml` (PEP 621 and Poetry formats)\n\n### Node.js\n\n- `package.json` (`dependencies` and `devDependencies`)\n\n### Rust\n\n- `Cargo.toml` (`[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`)\n\n### Go\n\n- `go.mod` (`require` blocks)\n\n### Ruby\n\n- `Gemfile` (gem declarations with version constraints)\n\n### .NET / NuGet\n\n- `.csproj` files (`PackageReference` elements)\n- `Directory.Packages.props` and `Directory.Build.props` (`PackageVersion` elements)\n- Supports both inline `Version` attributes and child `\u003cVersion\u003e` elements\n- Queries the NuGet v3 API (`api.nuget.org`)\n- Skips range version constraints (`[1.0, 2.0)`)\n\n### Terraform / OpenTofu\n\n- `.tf` files (HCL format)\n- Updates `required_providers` version constraints and `module` version declarations\n- Queries the Terraform Registry API (`registry.terraform.io`)\n- Skips local modules (`./`, `../`) and git sources\n- Supports pessimistic constraints (`~\u003e 5.0`)\n\n### GitHub Actions\n\n- `.github/workflows/*.yml` and `.github/workflows/*.yaml`\n- Updates `uses:` version references (e.g., `actions/checkout@v3` → `actions/checkout@v4`)\n- Skips SHA-pinned actions, branch refs, local actions, and Docker references\n- Authenticates via `GITHUB_TOKEN` or `GH_TOKEN` for higher API rate limits\n\n### Pre-commit\n\n- `.pre-commit-config.yaml`\n- Updates `rev:` fields for GitHub-hosted hook repositories\n- Skips local hooks, meta hooks, and non-GitHub repositories\n\n### Mise / asdf\n\n- `.mise.toml` (`[tools]` section)\n- `.tool-versions` (space-delimited format)\n- Supports 24+ common dev tools: node, python, go, rust, zig, deno, bun, uv, ruff, terraform, kubectl, helm, and more\n- Skips `latest` versions and `cargo:*` tools\n\n## Example Output\n\n```text\n.pre-commit-config.yaml:37: Would update pre-commit/pre-commit-hooks v4.6.0 → v6.0.0 (MAJOR)\n.github/workflows/ci.yml:16: Would update actions/checkout v4 → v6 (MAJOR)\n.github/workflows/ci.yml:18: Would update jdx/mise-action v2 → v4 (MAJOR)\n.mise.toml:8: Would update rust 1.91.1 → 1.94.0\nCargo.toml:33: Would update clap 4.5.53 → 4.6.0\nCargo.toml:36: Would update tokio 1.48.0 → 1.50.0\n\nWould update 6 package(s) (2 major, 3 minor, 1 patch) in 4 file(s), 8 up to date\n```\n\nOutput includes clickable `file:line:` locations (recognized by VS Code, iTerm2, and modern terminals).\n\n## Version Precision\n\nBy default, `upd` preserves version precision from the original file:\n\n```text\n# Original file has 2-component versions\nflask\u003e=2.0        →  flask\u003e=3.1        (not 3.1.5)\ndjango\u003e=4         →  django\u003e=6         (not 6.0.0)\n\n# Original file has 3-component versions\nrequests\u003e=2.0.0   →  requests\u003e=2.32.5\n\n# GitHub Actions major-only tags\nactions/checkout@v3  →  actions/checkout@v4  (not @v4.2.0)\n```\n\nUse `--full-precision` to always output full semver versions:\n\n```text\nupd --full-precision\nflask\u003e=2.0        →  flask\u003e=3.1.5\ndjango\u003e=4         →  django\u003e=6.0.0\nrequests\u003e=2.0.0   →  requests\u003e=2.32.5\n```\n\n## Version Alignment\n\nIn monorepos or projects with multiple dependency files, the same package might have different versions:\n\n```text\n# requirements.txt\nrequests==2.28.0\n\n# requirements-dev.txt\nrequests==2.31.0\n\n# services/api/requirements.txt\nrequests==2.25.0\n```\n\nUse `upd align` to update all occurrences to the highest version found:\n\n```bash\nupd align              # Align all packages to highest version\nupd align --dry-run    # Preview changes\nupd align --check      # Exit 1 if misalignments (for CI)\nupd align --lang python # Align only Python packages\n```\n\n**Behavior:**\n\n- Only aligns packages within the same ecosystem (Python with Python, etc.)\n- Skips packages with upper bound constraints (e.g., `\u003e=2.0,\u003c3.0`) to avoid breaking them\n- Ignores pre-release versions when finding the highest version\n\n## Security Auditing\n\nCheck your dependencies for known security vulnerabilities using the [OSV (Open Source Vulnerabilities)](https://osv.dev/) database:\n\n```bash\nupd audit              # Scan all dependency files\nupd audit --dry-run    # Same as audit (read-only operation)\nupd audit --check      # Exit 1 if vulnerabilities are found or the audit can't complete\nupd audit --lang python # Audit only Python packages\nupd audit ./services   # Audit specific directory\n\n# Auto-fix: bump each vulnerable package to the minimum safe version\n# (max of fixed_version across all its vulnerabilities). Packages with\n# no fixed_version are reported but left untouched.\nupd audit --fix-audit --apply\n\n# Offline mode: use only cached OSV responses; cache misses are errors\nupd audit --offline\n\n# SARIF 2.1.0 output for GitHub Code Scanning\nupd audit --format sarif \u003e results.sarif\n```\n\n**Example output:**\n\n```text\nChecking 42 unique package(s) for vulnerabilities...\n\n⚠ Found 3 vulnerability/ies in 2 package(s):\n\n  ● requests@2.19.0 (PyPI)\n    ├── 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\n    │   Fixed in: 2.31.0\n    │   https://github.com/psf/requests/security/advisories/GHSA-j8r2-6x86-q33q\n\n  ● flask@0.12.2 (PyPI)\n    ├── 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\n    │   Fixed in: 0.12.3\n    │   https://nvd.nist.gov/vuln/detail/CVE-2018-1000656\n    ├── 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\n    │   Fixed in: 2.3.2\n    │   https://github.com/pallets/flask/security/advisories/GHSA-m2qf-hxjv-5gpq\n\nSummary: 2 vulnerable package(s), 3 total vulnerability/ies\n```\n\n**Supported ecosystems for auditing:** PyPI, npm, crates.io, Go, RubyGems, NuGet\n\n**CI/CD Integration:**\n\n```yaml\n# GitHub Actions example — fail the build on vulnerabilities\n- name: Check for vulnerabilities\n  run: upd audit --check\n\n# Upload SARIF results to GitHub Code Scanning\n- name: Audit dependencies (SARIF)\n  run: upd audit --format sarif \u003e results.sarif\n- name: Upload to Code Scanning\n  uses: github/codeql-action/upload-sarif@v3\n  with:\n    sarif_file: results.sarif\n```\n\n## Version Constraints\n\n`upd` respects version constraints in your dependency files:\n\n| Constraint | Behavior |\n|------------|----------|\n| `\u003e=2.0,\u003c3` | Updates within 2.x range only |\n| `^2.0.0` | Updates within 2.x range (npm/Cargo) |\n| `~2.0.0` | Updates within 2.0.x range (npm) |\n| `~\u003e 7.1` | Updates within 7.x range (Ruby pessimistic) |\n| `\u003e=2.0` | Updates to any version \u003e= 2.0 |\n| `==2.0.0` | No updates (pinned) |\n\n## Configuration File\n\n`upd` supports configuration files to customize update behavior on a per-project basis.\n\n### File Discovery\n\n`upd` searches for configuration files in the following order (first found wins):\n\n1. `.updrc.toml` - Recommended, explicit config file\n2. `upd.toml` - Alternative name\n3. `.updrc` - Minimal name (TOML format)\n\nThe search starts from the target directory and walks up to parent directories, allowing you to place a config file at the repository root.\n\n### Configuration Options\n\n```toml\n# .updrc.toml\n\n# Packages to ignore during updates (never updated)\nignore = [\n    \"legacy-package\",\n    \"internal-tool\",\n    \"actions/checkout\",        # GitHub Actions use owner/repo\n    \"pre-commit/pre-commit-hooks\",  # Pre-commit hooks too\n]\n\n# Pin packages to specific versions (bypasses registry lookup)\n[pin]\nflask = \"2.3.0\"\ndjango = \"4.2.0\"\n\"actions/setup-node\" = \"v4\"   # Pin GitHub Actions\n\"psf/black\" = \"24.0.0\"        # Pin pre-commit hooks\n```\n\n### Options\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `ignore` | `string[]` | List of package names to skip during updates |\n| `pin` | `table` | Map of package names to pinned versions |\n\n### Verbose Output\n\nUse `--verbose` to see which packages are ignored or pinned:\n\n```bash\nupd --verbose\n# Output:\n# Using config from: .updrc.toml\n#   Ignoring 2 package(s)\n#   Pinning 3 package(s)\n# pyproject.toml:12: Pinned flask 2.2.0 → 3.0.0 (pinned)\n# pyproject.toml:13: Skipped internal-utils 1.0.0 (ignored)\n```\n\n## Cooldown (minimum release age)\n\nHold back updates to versions that have been public for less than N days.\nReduces exposure to supply-chain attacks that rely on freshly published\nmalicious versions being installed before detection. Modelled after\nRenovate's `minimumReleaseAge` / Dependabot's `cooldown`.\n\nEnable in `.updrc.toml`:\n\n```toml\n[cooldown]\ndefault = \"7d\"           # applies to every ecosystem unless overridden\n\n[cooldown.ecosystem]\nnpm = \"14d\"              # stricter for npm\npypi = \"14d\"\n\"crates.io\" = \"3d\"\n```\n\nDuration syntax: `\u003cinteger\u003e\u003cunit\u003e` where unit is `s`, `m`, `h`, `d`, `w`.\nA bare `0` disables cooldown.\n\nOverride from the CLI for one-off runs:\n\n```text\nupd --min-age 14d         # use 14 days regardless of config\nupd --min-age 0           # disable cooldown entirely for this run\n```\n\n**How it works:** when the latest version is still inside the cooldown\nwindow, `upd` updates to the newest version that *is* old enough. If nothing\nnewer is old enough yet, the package is held back. Output marks these\npackages explicitly:\n\n```text\nrequirements.txt: Updated requests 2.28.0 → 2.31.0\npackage.json: Held back lodash 4.17.20 → 4.17.21 (4.17.22 released 2d ago, cooldown 7d)\npackage.json: Skipped express (only newer version 4.19.0 released 1d ago, cooldown 7d)\n```\n\n**Supported ecosystems:** PyPI, npm, crates.io, Go modules, RubyGems,\nGitHub releases (covers GitHub Actions, pre-commit, Mise). NuGet and\nTerraform Registry do not expose per-version publish dates we can\nconsume today; cooldown is reported as unavailable for those files.\n\n## Caching\n\nVersion lookups are cached for 24 hours in:\n\n- macOS: `~/Library/Caches/upd/versions.json`\n- Linux: `~/.cache/upd/versions.json`\n- Windows: `%LOCALAPPDATA%\\upd\\versions.json`\n\nUse `upd clean-cache` to clear the cache, or `upd --no-cache` to bypass it.\n\n## Private Repositories\n\n`upd` supports private package registries for all ecosystems. Credentials are automatically detected from environment variables and configuration files.\n\n### PyPI / Private Python Index\n\n```bash\n# Option 1: Environment variables\nexport UV_INDEX_URL=https://my-private-pypi.com/simple\nexport UV_INDEX_USERNAME=myuser\nexport UV_INDEX_PASSWORD=mypassword\n\n# Option 2: PIP-style environment variables\nexport PIP_INDEX_URL=https://my-private-pypi.com/simple\nexport PIP_INDEX_USERNAME=myuser\nexport PIP_INDEX_PASSWORD=mypassword\n\n# Option 3: ~/.netrc file\n# machine my-private-pypi.com\n# login myuser\n# password mypassword\n\n# Option 4: pip.conf / pip.ini\n# ~/.config/pip/pip.conf (Linux/macOS)\n# %APPDATA%\\pip\\pip.ini (Windows)\n[global]\nindex-url = https://my-private-pypi.com/simple\nextra-index-url = https://pypi.org/simple\n\n# Option 5: Inline in requirements.txt (with credentials)\n# --index-url https://user:pass@my-private-pypi.com/simple\n# or just the URL (credentials from netrc):\n# --index-url https://my-private-pypi.com/simple\n```\n\n**pip.conf locations** (searched in order):\n\n1. `$PIP_CONFIG_FILE` environment variable\n2. `$VIRTUAL_ENV/pip.conf` (if in a virtual environment)\n3. `$XDG_CONFIG_HOME/pip/pip.conf` or `~/.config/pip/pip.conf`\n4. `~/.pip/pip.conf`\n5. `/etc/pip.conf` (system-wide)\n\n**Inline index URLs**: When a `requirements.txt` file contains `--index-url` or `-i`,\n`upd` automatically uses that index instead of the default PyPI. Credentials can be\nembedded in the URL (`https://user:pass@host/simple`) or looked up from `~/.netrc`.\n\n### npm / Private Registry\n\n```bash\n# Option 1: Environment variables\nexport NPM_REGISTRY=https://npm.mycompany.com\nexport NPM_TOKEN=your-auth-token\n\n# Option 2: NODE_AUTH_TOKEN (GitHub Actions)\nexport NODE_AUTH_TOKEN=your-auth-token\n\n# Option 3: ~/.npmrc file (global registry)\nregistry=https://npm.mycompany.com\n//npm.mycompany.com/:_authToken=your-auth-token\n# Or for environment variable reference:\n//npm.mycompany.com/:_authToken=${NPM_TOKEN}\n\n# Option 4: ~/.npmrc file (scoped registries)\n@mycompany:registry=https://npm.mycompany.com\n//npm.mycompany.com/:_authToken=your-auth-token\n@another-scope:registry=https://another.registry.com\n```\n\n**Scoped registries**: Packages with scopes (e.g., `@mycompany/package`) will use the\nregistry configured for that scope in `.npmrc`. This allows mixing public and private\npackages in the same project.\n\n### Cargo / Private Registry\n\n```bash\n# Option 1: Environment variables\nexport CARGO_REGISTRY_TOKEN=your-token  # For crates.io default\nexport CARGO_REGISTRIES_MY_REGISTRY_TOKEN=your-token  # For named registry\n\n# Option 2: ~/.cargo/credentials.toml\n[registry]\ntoken = \"your-crates-io-token\"\n\n[registries.my-private-registry]\ntoken = \"your-private-token\"\n\n# Option 3: ~/.cargo/config.toml (registry URLs)\n[registries.my-private-registry]\nindex = \"https://my-registry.com/git/index\"\n# or sparse registry:\nindex = \"sparse+https://my-registry.com/index/\"\n```\n\n**Custom registries**: `upd` reads `~/.cargo/config.toml` to discover custom registry\nURLs. Combine with `credentials.toml` for authenticated access.\n\n### Go / Private Module Proxy\n\n```bash\n# Option 1: Environment variables\nexport GOPROXY=https://proxy.mycompany.com\nexport GOPROXY_USERNAME=myuser\nexport GOPROXY_PASSWORD=mypassword\n\n# Option 2: Private module patterns\nexport GOPRIVATE=github.com/mycompany/*,gitlab.mycompany.com/*\nexport GONOPROXY=github.com/mycompany/*\nexport GONOSUMDB=github.com/mycompany/*\n\n# Option 3: ~/.netrc file (commonly used with go modules)\n# machine github.com\n# login myuser\n# password mytoken\n```\n\n**Private modules**: Set `GOPRIVATE` to specify module patterns that should bypass\nthe public proxy. `upd` respects these patterns and will attempt direct access\nfor matching modules.\n\n### GitHub (Actions \u0026 Pre-commit)\n\n```bash\n# Option 1: GITHUB_TOKEN (automatically available in GitHub Actions)\nexport GITHUB_TOKEN=ghp_your-token-here\n\n# Option 2: GH_TOKEN (used by the gh CLI)\nexport GH_TOKEN=ghp_your-token-here\n```\n\nWithout a token, the GitHub API rate limit is 60 requests/hour. With a token, it's 5,000 requests/hour.\n\nUse `--verbose` to see when authenticated access is being used:\n\n```bash\nupd --verbose\n# Output: Using authenticated PyPI access\n# Output: Using authenticated npm access\n# Output: Using authenticated GitHub access\n```\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `UV_INDEX_URL` | Custom PyPI index URL |\n| `PIP_INDEX_URL` | Custom PyPI index URL (fallback) |\n| `PIP_CONFIG_FILE` | Path to pip configuration file |\n| `UV_INDEX_USERNAME` | PyPI username (with UV_INDEX_URL) |\n| `UV_INDEX_PASSWORD` | PyPI password (with UV_INDEX_URL) |\n| `PIP_INDEX_USERNAME` | PyPI username (with PIP_INDEX_URL) |\n| `PIP_INDEX_PASSWORD` | PyPI password (with PIP_INDEX_URL) |\n| `NPM_REGISTRY` | Custom npm registry URL |\n| `NPM_TOKEN` | npm authentication token |\n| `NODE_AUTH_TOKEN` | npm token (GitHub Actions compatible) |\n| `CARGO_REGISTRY_TOKEN` | crates.io authentication token |\n| `CARGO_REGISTRIES_\u003cNAME\u003e_TOKEN` | Named registry token |\n| `GOPROXY` | Custom Go module proxy URL |\n| `GOPROXY_USERNAME` | Go proxy username |\n| `GOPROXY_PASSWORD` | Go proxy password |\n| `GOPRIVATE` | Comma-separated private module patterns |\n| `GONOPROXY` | Modules to exclude from proxy |\n| `GONOSUMDB` | Modules to exclude from checksum DB |\n| `GITHUB_TOKEN` | GitHub API token (for Actions and pre-commit) |\n| `GH_TOKEN` | GitHub API token (gh CLI compatible) |\n| `UPD_CACHE_DIR` | Custom cache directory |\n\n## Pre-commit Integration\n\nAdd `upd` to your `.pre-commit-config.yaml`:\n\n```yaml\nrepos:\n  - repo: https://github.com/rvben/upd-pre-commit\n    rev: v0.0.24\n    hooks:\n      - id: upd-check\n        # Optional: only check specific ecosystems\n        # args: ['--lang', 'python']\n```\n\nAvailable hooks:\n\n| Hook ID | Description |\n|---------|-------------|\n| `upd-check` | Fail if any dependencies are outdated |\n| `upd-check-major` | Fail only on major (breaking) updates |\n\nBoth hooks run on `pre-push` by default. Uses `language: python` which installs `upd-cli` from PyPI automatically — no manual installation needed.\n\n## Development\n\n```bash\n# Build\nmake build\n\n# Run tests\nmake test\n\n# Lint\nmake lint\n\n# Format\nmake fmt\n\n# All checks\nmake check\n```\n\n## Stability\n\nStarting with `0.1.0`, `upd` commits to the following public surfaces.\nAnything listed here will not change in a backwards-incompatible way\nwithout a major-version bump.\n\n### Stable CLI\n\nGlobal flags (accepted on every subcommand):\n\n| Flag | Short | Purpose |\n|------|-------|---------|\n| `--apply` | | Write changes to files (omit for dry-run preview) |\n| `--dry-run` | `-n` | Preview changes without writing (explicit form) |\n| `--verbose` | `-v` | Verbose output |\n| `--quiet` | `-q` | Suppress decorative output (errors still shown) |\n| `--interactive` | `-i` | Approve each update individually |\n| `--check` | | Exit 1 if updates/misalignments/vulnerabilities found |\n| `--only-bump \u003cmajor\\|minor\\|patch\u003e` | | Restrict to exactly these bump levels (repeatable, comma-separated) |\n| `--max-bump \u003cmajor\\|minor\\|patch\u003e` | | Include updates up to and including this level |\n| `--package \u003cNAME\u003e` | | Restrict to named packages (repeatable, comma-separated) |\n| `--lang \u003cLANG\u003e` | `-l` | Filter by ecosystem (repeatable) |\n| `--full-precision` | | Output full versions |\n| `--no-cache` | | Disable version cache |\n| `--no-color` | | Disable colored output |\n| `--lock` | | Regenerate lockfiles after updates |\n| `--config \u003cFILE\u003e` | `-c` | Use a specific config file |\n| `--show-config` | | Print effective configuration and exit |\n| `--format \u003ctext\\|json\\|sarif\u003e` | | Output format (`sarif` applies to `audit`) |\n| `--version` | `-V` | Print version (built-in clap flag) |\n| `--help` | `-h` | Print help (built-in clap flag) |\n\nSubcommands: `update` (default), `align`, `audit`, `clean-cache`, `self-update`.\n\n#### Commands run by `--lock`\n\n`upd --lock` runs the narrowest per-ecosystem refresh command that\nupdates only the packages `upd` just rewrote. Targeted forms are used\nwherever the package manager supports them; targeting falls back to\n`--lockfile-only` flags where no per-package form exists; otherwise\nthe manifest-wide refresh command is used.\n\n| Ecosystem | Lockfile                 | Command                                        |\n|-----------|--------------------------|------------------------------------------------|\n| Python    | `poetry.lock`            | `poetry lock --no-update`                      |\n| Python    | `uv.lock`                | `uv lock`                                      |\n| Node      | `package-lock.json`      | `npm install --package-lock-only`              |\n| Node      | `yarn.lock`              | `yarn install --mode update-lockfile` (Yarn 2+)|\n| Node      | `pnpm-lock.yaml`         | `pnpm install --lockfile-only`                 |\n| Node      | `bun.lockb`              | `bun install`                                  |\n| Rust      | `Cargo.lock`             | `cargo update -p \u003cchanged\u003e -p \u003cchanged\u003e …`     |\n| Go        | `go.sum`                 | `go mod tidy` (no targeted form)               |\n| Ruby      | `Gemfile.lock`           | `bundle lock --update \u003cchanged\u003e …`             |\n| .NET      | `packages.lock.json`     | `dotnet restore` (no targeted form)            |\n| Terraform | `.terraform.lock.hcl`    | `terraform providers lock` (no targeted form)  |\n\nManifests whose `upd` pass produced zero changes have their lockfile\nrefresh skipped entirely. A directory where only config pins were\napplied is still refreshed, and the changed-package list includes\nthose pinned packages so `cargo update -p \u003cpkg\u003e` / `bundle lock --update \u003cpkg\u003e` stay scoped.\n\nStable `audit`-specific flags:\n\n| Flag | Purpose |\n|------|---------|\n| `--fix-audit` | Bump each vulnerable package to minimum safe version |\n| `--offline` | Use only cached OSV responses; cache misses are errors |\n| `--format sarif` | Emit SARIF 2.1.0 for GitHub Code Scanning |\n\n### Stable exit codes\n\n| Code | Meaning |\n|------|---------|\n| `0` | Success — no action required, or updates applied cleanly |\n| `1` | `--check` flagged pending updates / misalignments / vulnerabilities, or an audit could not complete |\n| `2` | Invalid CLI arguments or unparseable configuration (clap default) |\n| `3` | Vulnerabilities found (`upd audit`). Pass `--no-fail` to force exit 0. |\n\n### Stable output\n\n- **Text output** is designed for humans. Exact wording, colour, and spacing may change between minor versions — do not parse it.\n- **JSON output** (`--format json`) follows an additive schema. New\n  fields may appear in minor releases; existing fields will not change\n  type, be renamed, or be removed before `1.0`.\n\n### Stable configuration\n\n- `.updrc.toml` / `upd.toml` / `.updrc` discovery order and the `ignore` array + `[pin]` table are stable.\n- New top-level keys may be added in minor releases, but will always default to the pre-existing behaviour.\n\n### Not covered by stability guarantees\n\n- Error message wording and verbose/debug log lines.\n- Cache file layout on disk (`$UPD_CACHE_DIR/versions.json`).\n- The `upd` Rust library crate — internal types may change between any releases. Depend on the CLI, not the crate.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frvben%2Fupd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frvben%2Fupd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frvben%2Fupd/lists"}