Try CAVS

Try CAVS on your
own game build.

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.

01 — Who this guide is for

If you have two builds,
you can test CAVS today.

// builds

Two versions of a build

Any old→new pair: a folder export, a single binary, an archive of game data.

// godot

A Godot PCK

Certify PCK updates byte-for-byte and keep mounting with load_resource_pack().

// folders

Folder-based exports

Directory builds get per-file diffs, staged applies and no-op detection.

// depots

DLC & language packs

Model depots, branches and ownership locally — no platform account needed.

// launchers

Custom launcher workflows

Test delivery against a local dev server before wiring any infrastructure.

// size

Updates you want to understand

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.

02 — Install

Install CAVS.

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
03 — Quick start

Compare two builds
in one command.

$ 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.

  • Full download baseline and SteamPipe-style estimate.
  • CAVS chunk, hybrid and .cavsplan routes — measured, verified.
  • butler offline and bsdiff/xdelta3 when the tools are installed.
preview.md
# Route comparison — Build_v1 → Build_v2
full download 126.89 MiB
steampipe-style est. 16.90 MiB
CAVS chunk/hybrid 2.51 MiB
CAVS .cavsplan 2.26 MiB ← recommended
Saved−98.2% Apply214 ms Outputbyte-identical
04 — Certify

Certify an update
before release.

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.

  • Profiles: quick · standard · release · strict · ci.
  • Exit codes frozen for v1.x: 0 pass · 1 fail · 2 warnings · 3 missing dep · 4 bad input · 5 internal.
  • Every section is Markdown for humans and JSON for machines.
certification/summary.md
Result: PASS
Recommended route: CAVS .cavsplan
- 2.26 MiB network
- 214 ms apply · streaming memory
- byte-identical output
Integrity: PASS
Routes: PASS
Regression: PASS
SteamPipe-style analysis: PASS WITH WARNINGS
Godot compatibility: PASS

A hash mismatch is never a warning. Byte-identical reconstruction is mandatory — certification fails, and the update should not ship.

05 — Godot PCK

Use case: Godot PCK updates.

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])
01

Download

Only the chunks the player is missing, from a persistent user:// cache.

02

Reconstruct

The PCK is rebuilt byte-for-byte — the format never changes.

03

Verify

SHA-256 per file against the signed manifest. Unverified PCKs are never mounted.

04

Mount

ProjectSettings.load_resource_pack() — plain Godot, every export platform.

06 — Diagnose

Use case: why is my
update so large?

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.

07 — More workflows

Previous installs, folder builds,
depots and a dev server.

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
08 — Reproducible reports

Export a report others
can verify.

$ 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.

repro.tar.zst
repro/
README.md · commands.sh
environment.json · tool-versions.json
inputs/ hashes.json · file-list.json
outputs/ summary · routes · integrity · regressions
reports/ the same, as Markdown
configs/ · seeds/
09 — Troubleshooting

When something looks wrong.

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.

10 — FAQ

Honest answers.

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.

Seven steps, a few minutes

Install. Point at two builds. Read the report.

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.