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.14+ 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]inpyproject.toml. - Cargo:
[package.metadata.zavis]inCargo.toml. - npm:
"zavis"inpackage.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
just check
uv run pytest -m integration
uv build
The default pytest suite uses local fixtures and requires no public registry access or non-Python toolchains. Opt-in integrations run real uv/npm/Cargo/dotnet commands against temporary local registries or feeds. Windows execution is verified; Linux/macOS native execution remains a release-validation limitation. No remote CI is configured.
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.
Metadata
Release files for zavis 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zavis-0.1.0.tar.gz | 37.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zavis-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.3 kB
Release files / zavis-0.1.0.tar.gz
| Download URL | zavis-0.1.0.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
416ddd17f9fa9c6bb89a9e68874b311a3742bf50a92701b3eb7d6c47a8814570
|
|
BLAKE2b-256 checksum How to use checksums |
4c792e62cc203d5bba42eb19014c7d98342cb8f49253715bfcf6c6f076623145
|
| 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.1.0-py3-none-any.whl
| Download URL | zavis-0.1.0-py3-none-any.whl |
|---|---|
| Size | 52.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d8cd1762d7d46d12fb02762e91d4c82881c53e84568689506e20ae06828714cd
|
|
BLAKE2b-256 checksum How to use checksums |
7849e22791680c58ec5e1b26c899d50666aec34fcf245fd9778b13c012c3d4ff
|
| 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}
|