Skip to main content

Zavis

Zavis is a local Python CLI for inspecting dependency releases and accepting native package-manager updates only after their publication-age policy passes. The default cooling-off period is seven full days (168 hours).

Zavis is not a resolver or package manager. It preserves dependency declarations, uses native resolution, verifies changed direct and transitive selections, and applies only dependency files. It does not synchronize environments or create commits.

Install and run from this checkout

Python 3.11+ and uv are required. Only the toolchain for the ecosystem being updated needs to be installed.

uv sync --locked
uv run zavis --help
uv run zavis check --project D:/Projects/example
uv run zavis why requests --ecosystem python --project D:/Projects/example
uv run zavis pending --project D:/Projects/example --json
uv run zavis update --project D:/Projects/example --dry-run
uv run zavis update requests --ecosystem python --project D:/Projects/example
uv run zavis verify --project D:/Projects/example

Options follow the subcommand. python -m zavis is also supported. The distribution, import package, executable and configuration namespace are all named zavis; the existing checkout directory can retain its original name.

Commands

Command Contract
check Current, latest, and policy-eligible releases; direct dependencies by default
check --include-transitive Include all discovered dependency instances
pending Newer releases blocked specifically by age, with eligibility timestamps
why PACKAGE Evidence, release decisions, declarations and effective policy
verify Verify the entire available resolved graph
update [PACKAGE] Stage native direct upgrades and required transitive changes
update --dry-run Resolve and verify in staging without applying files
update --run-checks Explicitly execute configured checks in staging before apply
audit Send proven-public package names and versions to OSV for advisory lookup
config show Effective settings and provenance
recover Restore an interrupted file application when fingerprints still match

Shared options: --project PATH, repeatable --ecosystem, --config FILE, --json, --offline, --refresh, --verbose, and --no-color. Ecosystem names are python, rust, javascript, dotnet, and go. Select a pip environment with --tool pip --python PATH; without an explicit interpreter, a project .venv is required.

Targeted updates require one selected ecosystem and an existing lockfile. Unqualified updates target direct dependencies, not every transitive package independently. An eligible release may still be incompatible with the project's native constraints. Exact pins may produce no update. No declaration-rewriting option is implemented.

Configuration

Zavis reads user configuration from the platformdirs user configuration directory, under zavis/config.toml (Windows uses Local AppData; Linux follows XDG; macOS uses Application Support). It prefers existing project configuration namespaces:

  • Python: [tool.zavis] in pyproject.toml.
  • Cargo: [package.metadata.zavis] in Cargo.toml.
  • npm: "zavis" in package.json.
  • Otherwise: a project zavis.toml.

A standalone file looks like this:

schema_version = 1

[policy]
minimum_release_age = "7d"
allow_prereleases = false
allow_yanked = false

[cache]
metadata_ttl = "1h"

[[checks]]
name = "tests"
argv = ["uv", "run", "--locked", "pytest"]
timeout = "10m"
cwd = "."

Precedence is defaults, user file, embedded project configuration, then zavis.toml. --config FILE replaces project discovery, retaining user defaults. Tables merge by key; arrays replace. Unknown keys and invalid types fail. If several embedded configs exist, use a standalone file: it becomes the sole project configuration rather than choosing an ecosystem arbitrarily. Durations use integer s, m, h, d, or w units (up to 3650 days). Zero explicitly disables only the age delay, not evidence requirements.

Checks never run just because they appear in configuration. --run-checks authorizes their argument arrays, in order, in the staged project. Check environments are not automatically installed. A failed check rejects the update.

Per-ecosystem/package/direct/transitive overrides, security exceptions and private registry authentication are deferred. Future options are not silently accepted today.

Capabilities and evidence

Ecosystem Supported state and operations Limitations
Python/uv Universal uv.lock version 1, artifact URLs/hashes, groups and conditional edges; uv lock --no-build updates Public PyPI only; workspaces and source builds not enabled
Python/pip Selected interpreter's structured installed inventory Original registry/artifact provenance generally unknown; inspection only
npm Lock versions 2/3, installation locations, aliases, peers and optional edges; lock-only updates Public npm only; competing locks, workspaces, bundled/unproven sources fail closed
Cargo Lock versions 3/4, renamed dependencies, duplicate versions and checksums; native precise updates Public crates.io only; workspace updates deferred; at most 20 direct candidates
NuGet One SDK-style PackageReference project, lock version 1, target frameworks and content hashes; floating reevaluation No targeted updates, solutions, central/dynamic/imported versions; strict source provenance
Go Native module inventory respecting privacy settings Publication timestamps cannot be established; updates blocked

The initial tested update-tool floors are uv 0.12.22, npm 12.0.1, Cargo 1.99.0 and dotnet SDK 10.0.401. The installed tool is checked before updates. These conservative floors describe tested capabilities, not when upstream features were first introduced. See native compatibility evidence.

PyPI upload times are per artifact: a newly uploaded wheel cannot borrow an older wheel's age. Every referenced locked artifact must match registry URL and hash. Crates.io uses version publication timestamps; npm uses time[version]; NuGet uses registration metadata. Unlisted NuGet year-1900 sentinels are not valid old dates. Go proxy commit times and index observation times are never treated as publication.

NuGet public-source verification requires matching lock content hashes, assets metadata, and cached .nupkg.metadata origin information. A public source setting alone does not prove where a cached package came from. Missing evidence is incomplete coverage.

Verification covers the available lockfile/environment inventory, including inactive platform entries represented there. It does not claim to inventory arbitrary dynamic build-backend requirements or dependencies outside that native state. Unsupported or unresolved graph edges are reported, not silently treated as complete.

Update safety

Zavis snapshots the current working tree into a disposable staging directory, including uncommitted and untracked project files. It excludes Git metadata, dependency environments and known build/cache directories. Links/junctions are rejected rather than followed. External project references and unsupported workspace layouts are blocked.

Native tools change staged locks. Zavis verifies every added/changed version, source or artifact; unchanged policy violations remain visible without blocking otherwise valid changes. A first lock verifies all selections. Young or unverifiable transitive dependencies reject the transaction. Zavis does not search combinations of transitive pins.

Before applying, all captured live inputs must still match. Only allowlisted lockfiles are copied back. Each replacement is atomic; a durable journal supports rollback across multiple files. Recovery refuses to overwrite subsequent user edits. Run zavis recover after an interrupted apply. Recovery journals live in the user state directory, separate from disposable metadata caches.

This is not an operating-system sandbox. Native tools can evaluate trusted project tooling (notably MSBuild), and explicitly requested checks can have external effects. File rollback cannot undo those effects, downloads, caches or arbitrary concurrent external writers. Lifecycle scripts are disabled for npm; uv builds are disabled; Cargo dependencies are not built. Never use Zavis as a safe executor for an untrusted repository.

Cache, privacy and output

Registry responses use SQLite caching, one-hour discovery freshness and HTTP validators. Updates refresh evidence for acceptance. No policy verdict is cached. Offline commands require fresh cached evidence; offline updates are disabled. Go offline inventory disables proxy and checksum-network access. Unknown/private package sources are never sent to public registry or OSV clients. HTTP redirects, implicit netrc credentials and environment proxy discovery are disabled in this initial public-registry client.

--json returns a schema-versioned document with results, diagnostics, coverage, UTC evaluation time and transaction state. Native output does not contaminate stdout. Human output escapes terminal controls and redacts common credential forms.

Exit Meaning
0 Completed; a fully assessed no-op is successful
1 Policy violations or advisory findings
2 Invalid arguments/configuration
3 Incomplete evidence or unsupported capability
4 Native/network/metadata failure
5 Configured check failure
6 Concurrent modification or recovery required
130 Interrupted

check does not fail simply because young newer releases exist. verify fails for violations or unknown age. OSV lookup is explicit and does not waive cooling-off policy. No matching advisories is not a guarantee of safety.

Development and verification

Run just ci before bumping the version and releasing. It checks lockfile consistency, formatting, lint, types, both Python 3.11–3.14 test matrices, and builds the source distribution and wheel. The test matrices use locked dependencies. It requires the matrix interpreters and native toolchains documented below and stops on the first failed step.

just ci
just check
just check-all
just test-matrix-native
uv build

just check runs formatting, lint, Python 3.11 type checking, and pytest in the development environment. .python-version retains Python 3.14 as the development default. just check-all runs the static checks once and the offline tox matrix on CPython 3.11, 3.12, 3.13, and 3.14. The same tests and assertions run against a non-editable installed wheel in each environment. No remote CI is configured.

Install the matrix interpreters explicitly before running it:

uv python install 3.11 3.12 3.13 3.14
uv sync --locked

Tox uses tox-uv's lock-aware runner, installs the locked development dependencies, and keeps each interpreter's environment separate under .tox/. Missing interpreters fail the run; automatic Python downloads are disabled. JUnit results are written to .tox/<environment>/junit.xml. The normal .venv remains the development environment. First-time environment setup may download locked dependencies; the default test suite itself uses local fixtures and needs no public registry access or non-Python toolchains.

just test-matrix
just test-matrix -e py311
just test-matrix -e py311 -- -k transaction
just test-matrix-native
just test-matrix-native -e py311-native

The opt-in native matrix runs real uv/npm/Cargo/dotnet commands against temporary local registries or feeds on every matrix interpreter. Node/npm, Cargo, and the .NET SDK must be available on PATH; uv is installed with tox-uv. A missing native tool fails the integration instead of skipping it. The uv fixture explicitly uses the test environment's Python. These adapter fixtures do not lower the production CLI's documented native capability floors.

To add a newly released Python version, install its interpreter, add its environment to tox.toml's env_list, and add its native environment to the native label with the same integration command. Run both matrices before documenting that version as tested. Avoid version-specific skips or changed expectations; common deterministic JSON contracts and the existing policy, artifact, process, and transaction assertions define equivalent behavior. Windows execution is verified; Linux/macOS native execution remains a release-validation limitation.

The repository persists tool.uv.exclude-newer = "1 week", including development dependency selection. The build backend is pinned to an independently age-verified release. Preserve the lock with uv sync --locked; use the configured age gate for future dependency changes.

For a version bump, edit only [project].version in pyproject.toml, then run uv lock and uv sync --locked before testing or building. The CLI's --version output and HTTP User-Agent read the installed distribution metadata; neither contains a separate version declaration. Rebuild and reinstall distributions to pick up a changed version.

After updating the version and lockfile, run just release to delete dist, run ci, run uv build, and publish with uv publish --username __token__. Cleanup uses Python for Windows, Linux, and macOS compatibility and succeeds if dist is already absent. Each step must succeed before the next runs. Supply the publishing token through uv's UV_PUBLISH_TOKEN environment variable or its password prompt.

Metadata

Release files for zavis 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zavis 0.2.0
File Size Uploaded
zavis-0.2.0.tar.gz 39.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zavis 0.2.0
File Interpreter ABI Platform
zavis-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 93.8 kB

Release files / zavis-0.2.0.tar.gz

Download URL zavis-0.2.0.tar.gz
Size 39.5 kB
Tags Source
SHA-256 checksum
How to use checksums
570729c15888d2c1ef3f4d5c59394e4631b605bc0fb7d817d4dc0b070ee7b72c
BLAKE2b-256 checksum
How to use checksums
3e5c270c00b9e9353f775fa0cafd344f920f9b55010852847111d5f30baf13a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / zavis-0.2.0-py3-none-any.whl

Download URL zavis-0.2.0-py3-none-any.whl
Size 54.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b510ec3a0686baaf86a1a7b9de5054a3c8b8f8ac07e55d9087f260bdf0e68f9
BLAKE2b-256 checksum
How to use checksums
8d91d3a53092880cea5c1effbd6a4adc09761229e76758377344208901455cf6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release 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