Language-agnostic version management across project files
Project description
vrzn
Author: Scott Arne Johnson (scott.arne.johnson@gmail.com)
Language-agnostic version management across project files.
Overview
Projects often store version numbers in multiple files: pyproject.toml, __init__.py, CMakeLists.txt, package.json, and others. When these fall out of sync, builds break and releases ship incorrect metadata.
vrzn solves this by letting you declare every file that contains a version number in a single configuration file. It can then read, set, and bump versions across all of them at once, with full PEP 440 support.
Installation
Requires Python 3.10 or later.
pip install vrzn
For YAML config file support:
pip install 'vrzn[yaml]'
Quick Start
Create a vrzn.toml in your project root:
[[locations]]
file = "pyproject.toml"
type = "pyproject-version"
[[locations]]
file = "src/mypackage/__init__.py"
type = "python-dunder"
Check that all version locations are in sync:
$ vrzn get
vrzn — version report
╭───────────────────────────┬───────────────────┬─────────┬────────╮
│ File │ Location │ Version │ Status │
├───────────────────────────┼───────────────────┼─────────┼────────┤
│ pyproject.toml │ pyproject-version │ 1.0.0 │ ok │
├───────────────────────────┼───────────────────┼─────────┼────────┤
│ src/mypackage/__init__.py │ python-dunder │ 1.0.0 │ ok │
╰───────────────────────────┴───────────────────┴─────────┴────────╯
Consensus version: 1.0.0
All version numbers are consistent.
Set a specific version everywhere:
$ vrzn -y set 1.2.0
Setting version to 1.2.0
updated files
╭───────────────────────────┬───────────────────┬─────────┬───────┬─────────╮
│ File │ Location │ Current │ New │ Result │
├───────────────────────────┼───────────────────┼─────────┼───────┼─────────┤
│ pyproject.toml │ pyproject-version │ 1.0.0 │ 1.2.0 │ updated │
│ src/mypackage/__init__.py │ python-dunder │ 1.0.0 │ 1.2.0 │ updated │
╰───────────────────────────┴───────────────────┴─────────┴───────┴─────────╯
All versions set to 1.2.0.
Bump the version:
$ vrzn -y bump patch
Version bump: 1.2.0 → 1.2.1
updated files
╭───────────────────────────┬───────────────────┬─────────┬───────┬─────────╮
│ File │ Location │ Current │ New │ Result │
├───────────────────────────┼───────────────────┼─────────┼───────┼─────────┤
│ pyproject.toml │ pyproject-version │ 1.2.0 │ 1.2.1 │ updated │
│ src/mypackage/__init__.py │ python-dunder │ 1.2.0 │ 1.2.1 │ updated │
╰───────────────────────────┴───────────────────┴─────────┴───────┴─────────╯
Version bumped to 1.2.1.
Preview changes without writing files:
$ vrzn --dry-run bump minor
Version bump: 1.2.1 → 1.3.0
dry run
╭───────────────────────────┬───────────────────┬─────────┬───────┬──────────────╮
│ File │ Location │ Current │ New │ Result │
├───────────────────────────┼───────────────────┼─────────┼───────┼──────────────┤
│ pyproject.toml │ pyproject-version │ 1.2.1 │ 1.3.0 │ would update │
│ src/mypackage/__init__.py │ python-dunder │ 1.2.1 │ 1.3.0 │ would update │
╰───────────────────────────┴───────────────────┴─────────┴───────┴──────────────╯
Dry run — no files were modified.
Pre-release workflows:
vrzn -y bump patch --pre rc # 1.0.0 -> 1.0.1rc1
vrzn -y bump pre # 1.0.1rc1 -> 1.0.1rc2
vrzn -y bump release # 1.0.1rc2 -> 1.0.1
CLI Reference
Global Options
Global options must be placed before the subcommand (e.g., vrzn --dry-run bump patch).
| Option | Description |
|---|---|
--dry-run |
Show what would change without writing files. |
--yes, -y |
Skip confirmation prompts. |
--quiet, -q |
Machine-readable output, no tables. |
--config, -c PATH |
Path to config file (overrides discovery). |
Commands
vrzn get
Display the current version in all configured files. Prints a table showing each location, its version, and whether it matches the consensus.
With --quiet, prints only the consensus version string.
Exit codes: 0 if all versions agree, 1 if mismatches exist, 2 if no config found.
vrzn set VERSION
Set all version numbers to VERSION. Accepts any PEP 440 version string (e.g., 1.0.0, 1.0.0rc1, 1.0.0.post1). Non-normalized forms are accepted and automatically normalized.
Prompts for confirmation unless --yes or --dry-run is set.
Exit codes: 1 for invalid version format, 2 if no config found.
vrzn bump PART [--pre LABEL]
Bump the version number. PART must be one of: major, minor, patch, pre, release.
Use --pre with a label (alpha, a, beta, b, rc) to enter a pre-release state. Use bump pre to increment an existing pre-release. Use bump release to finalize a pre-release to its stable version.
If versions are out of sync, vrzn warns and uses a consensus version (most common across locations). Prompts for confirmation unless --yes or --dry-run is set.
Exit codes: 1 for errors (no readable version, invalid bump operation), 2 if no config found.
Configuration
vrzn searches up the directory tree for config in this order:
vrzn.tomlvrzn.yamlvrzn.jsonpyproject.toml(under[tool.vrzn])
Built-in Presets
Each preset is a template string with a version placeholder that tells vrzn how to find and replace the version in a file.
| Preset | Matches | Format |
|---|---|---|
pyproject-version |
version = "X.Y.Z" in TOML |
full |
python-dunder |
__version__ = "X.Y.Z" |
full |
python-version-info |
__version_info__ = (X, Y, Z) |
base |
cmake-project |
project(NAME VERSION X.Y.Z) |
base |
c-define |
#define PREFIX_VERSION_MAJOR N |
component |
cargo-toml |
version = "X.Y.Z" in Cargo.toml |
full |
package-json |
"version": "X.Y.Z" in JSON |
full |
maven-pom |
<version>X.Y.Z</version> |
full |
gradle-version |
version = 'X.Y.Z' in Gradle |
full |
Format types:
- full — reads/writes a complete PEP 440 version string (e.g.,
1.2.3rc1) - base — reads/writes only MAJOR.MINOR.PATCH (e.g.,
1.2.3), ignoring pre-release suffixes - component — reads/writes a single integer (MAJOR, MINOR, or PATCH); excluded from agreement checking
The c-define preset requires a prefix parameter and expands to three component locations:
[[locations]]
file = "include/mylib.h"
type = "c-define"
prefix = "MYLIB"
Custom Locations
For files that don't match a built-in preset, use custom with a template string containing a version placeholder:
[[locations]]
file = "docs/conf.py"
type = "custom"
label = "Sphinx config"
template = 'release\s*=\s*"{version}"'
The template is a regex string with exactly one placeholder embedded in it. The text around the placeholder is standard regex that matches the surrounding context in the file.
Available placeholders:
| Placeholder | Writes | Format |
|---|---|---|
{version} |
Full PEP 440 version (e.g., 1.2.3rc1) |
full |
{base} |
MAJOR.MINOR.PATCH only (e.g., 1.2.3) |
base |
{info_tuple} |
Comma-separated tuple (e.g., 1, 2, 3) |
base |
{major} |
Major version integer | component |
{minor} |
Minor version integer | component |
{patch} |
Patch version integer | component |
Development
pip install --config-settings editable_mode=compat -e ".[dev,yaml]"
pytest
License
MIT License. Copyright (c) 2026 Scott Arne Johnson. See LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vrzn-0.2.0.tar.gz.
File metadata
- Download URL: vrzn-0.2.0.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39cd50d40c0c5a182cdf939718f1aae72cc2325e8f519e8ff81c5ffaa28e6dcf
|
|
| MD5 |
41b8c1c8308fe9bfd05bc4a4c57f8941
|
|
| BLAKE2b-256 |
f6cea40c0a5c132d5b60e8565bb9d19a679dda31ea3fd3238497bc73f30395ac
|
Provenance
The following attestation bundles were made for vrzn-0.2.0.tar.gz:
Publisher:
build-wheels.yml on scott-arne/vrzn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vrzn-0.2.0.tar.gz -
Subject digest:
39cd50d40c0c5a182cdf939718f1aae72cc2325e8f519e8ff81c5ffaa28e6dcf - Sigstore transparency entry: 1274094793
- Sigstore integration time:
-
Permalink:
scott-arne/vrzn@ed82ec1cc0ffe78b2da3dd2015019a25721f54b2 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/scott-arne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-wheels.yml@ed82ec1cc0ffe78b2da3dd2015019a25721f54b2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vrzn-0.2.0-py3-none-any.whl.
File metadata
- Download URL: vrzn-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
992fb2425161a6dcf286f161cd7f532bee33406ab67da0cd2994c153f2f3560a
|
|
| MD5 |
7c43b38395e393aee7b1877b637a4d7a
|
|
| BLAKE2b-256 |
c5267621b5b9fde16aad258531978ce1f09b6e411384814a5c39845750d477f4
|
Provenance
The following attestation bundles were made for vrzn-0.2.0-py3-none-any.whl:
Publisher:
build-wheels.yml on scott-arne/vrzn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vrzn-0.2.0-py3-none-any.whl -
Subject digest:
992fb2425161a6dcf286f161cd7f532bee33406ab67da0cd2994c153f2f3560a - Sigstore transparency entry: 1274094863
- Sigstore integration time:
-
Permalink:
scott-arne/vrzn@ed82ec1cc0ffe78b2da3dd2015019a25721f54b2 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/scott-arne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-wheels.yml@ed82ec1cc0ffe78b2da3dd2015019a25721f54b2 -
Trigger Event:
push
-
Statement type: