Run CAVS locally against two builds, compare update routes, inspect why updates are large, and generate a release certification report. No CDN required. No account required. Point it at two builds and get a report.
Any old→new pair: a folder export, a single binary, an archive of game data.
Certify PCK updates byte-for-byte and keep mounting with load_resource_pack().
Directory builds get per-file diffs, staged applies and no-op detection.
Model depots, branches and ownership locally — no platform account needed.
Test delivery against a local dev server before wiring any infrastructure.
Find out why an update is large — and what layout change fixes it.
You do not need a CDN or a hosted CAVS server. Everything in this guide runs locally.
Grab the latest release from GitHub, or build from source with Rust.
From source
$ git clone https://github.com/orelvis15/cavs $ cargo build --release # → target/release/{cavs, cavs-server, cavs-client}
Check the version
$ cavs --version cavs 1.0.0
Optional tools for external comparisons — CAVS skips them when missing
$ butler --version # itch.io butler (offline benchmark) $ xdelta3 -V # pairwise delta proxy $ bsdiff # pairwise delta proxy
$ cavs publish-preview ./Build_v2 \ --previous ./Build_v1 \ --routes all \ --out preview
Then open preview/preview.md and look for the recommended route, the estimated download size, apply time, disk I/O and pack-layout warnings.
New in v1.0.0: cavs certify runs the whole release-readiness suite — integrity, routes, regressions, layout analysis — and produces one report with stable exit codes for CI.
$ cavs certify \ --old ./Build_v1 \ --new ./Build_v2 \ --profile release \ --out ./certification $ open certification/summary.md
CAVS checks byte-identical reconstruction, route selection per client state, update size, disk I/O, SteamPipe-style behavior, pack-layout health, regressions when a baseline is provided, and optional butler/xdelta/bsdiff comparisons.
A hash mismatch is never a warning. Byte-identical reconstruction is mandatory — certification fails, and the update should not ship.
Certify the PCK flow
$ cavs certify godot \ --old-pck old.pck \ --new-pck new.pck \ --out ./certification/godot # .cavsplan / chunk / bootstrap routes: byte-identical # plugin API surface: unchanged
The runtime flow stays simple (GDScript, no native code)
# addons/cavs — stable API for v1.x var cavs := CavsClient.new("http://127.0.0.1:8990") var result := cavs.fetch("main_pack") if result.ok: ProjectSettings.load_resource_pack(result.files[0])
Only the chunks the player is missing, from a persistent user:// cache.
The PCK is rebuilt byte-for-byte — the format never changes.
SHA-256 per file against the signed manifest. Unverified PCKs are never mounted.
ProjectSettings.load_resource_pack() — plain Godot, every export platform.
Diagnose the transition
$ cavs analyze steampipe ./Build_v1 ./Build_v2 \ --out steampipe-analysis.md $ cavs analyze-packs ./Build_v1 ./Build_v2 \ --out pack-analysis.md
The reports identify
- scattered pack-file churn
- asset shuffling
- distributed TOC/offset churn
- compressed blobs across asset boundaries
- timestamp / build-id churn
- oversized packs
- new content inserted into old packs
Each finding comes with a concrete fix: split large packs, group assets by level or feature, prefer per-asset compression, avoid repacking unrelated content, and move frequently-updated content into separate packs.
Empty cache + previous install — hybrid reconstruction
# the player has game_v1.pck but no CAVS cache yet $ cavs-client fetch http://127.0.0.1:8990 game_v2 \ --previous-artifact ./game_v1.pck \ --cache ./cache -o game_v2.pck # verified ranges are copied from the old file; # only what changed is downloaded
Folder-based builds — offline plan, staged apply
$ cavs diff-plan ./Build_v1 ./Build_v2 \ --out update.cavsplan $ cavs apply --old ./Build_v1 \ --plan update.cavsplan \ --out ./Build_v2_out --verify $ cavs verify-install ./Build_v2_out \ --signature build_v2.cavssig
Depots, DLC and language packs — local workspace
$ cavs workspace init ./cavs-workspace --app my-game $ cavs depot add base --workspace ./cavs-workspace $ cavs depot add lang-es --language es --optional \ --workspace ./cavs-workspace $ cavs install-plan --platform windows --language es \ --owned base,lang-es --from build_1001 --to build_1002 # per-depot update cost + shared content reuse
Local testing server — development only
$ cavs serve ./cavs-workspace \ --app my-game --branch beta --port 8990 # serves manifests, bootstraps, chunks, ranges, # .cavsplans and signatures to your launcher # or the Godot plugin — localhost, never production
$ cavs certify export-repro \ --certification ./certification \ --out cavs-repro.tar.zst
The bundle includes the commands used, tool versions, environment metadata, configs, report JSON + Markdown, hashes and synthetic dataset seeds. Deterministic: exporting twice gives byte-identical bundles.
By default CAVS does not include private game files in the bundle — hashes only. --include-inputs is for synthetic or shareable test data.
butler is optional. Install it only if you want external butler comparisons — routes that need a missing tool are skipped and reported, never selected.
These are optional pairwise baselines. CAVS skips them unless you run --profile strict with the tool explicitly configured, which makes it required (exit code 3 when missing).
That is expected — global compression destroys binary similarity between versions. Analyze the uncompressed folder instead: cavs analyze steampipe ./Build_v1 ./Build_v2, and prefer per-asset compression in your pipeline.
Run cavs analyze godot-pck old.pck new.pck. Inserting content early in a pack shifts every later offset; consider moving frequently-updated content into a secondary PCK mounted on top of the base one.
Do not ship the update. Check for corrupted input, an incomplete previous artifact, a modified cache, the wrong signature, or the wrong old/new build pair. A mismatch is never a warning.
No. CAVS runs completely locally for analysis, certification and offline update plans. A server only enters the picture when you want to deliver over HTTP — and the dev server ships in the same binary.
No. CAVS includes SteamPipe-style analysis based on public documentation. It is an estimate model — never Valve's SteamPipe implementation, and every report says so.
No. CAVS can benchmark against butler offline when butler is installed, but it does not replace itch.io's upload pipeline.
No. CAVS reconstructs the original PCK byte-for-byte and Godot mounts it normally. If verification fails, nothing is mounted.
No. CAVS signing and optional encryption exist for integrity and controlled testing workflows — not DRM or license enforcement.
The documented CLI families, the .cavs / .cavssig / .cavsplan / .cavspatch formats, the certification JSON schemas and exit codes, and the Godot plugin runtime API. See docs/COMPATIBILITY.md.
1 · Install CAVS → 2 · Point it at two builds → 3 · Run publish-preview → 4 · Run certify → 5 · Read the report → 6 · Try the Godot PCK flow → 7 · Export a reproducible bundle
Have a game with frequent updates? Open an issue or start a discussion — real-world test cases are welcome.