Releases & snapshots
Two different tools that people often confuse:
- A release answers “what did version 1.4.0 consist of?” — it’s a Git tag with metadata and an aggregate of the LFS files reachable at it.
- A snapshot answers “how much were we storing on July 20th, and where?” — it’s a point-in-time capture of storage state.
Releases
Section titled “Releases”Where they come from
Section titled “Where they come from”Releases are created automatically during indexing, from your Git tags. Push a tag and it appears:
git tag -a v1.4.0 -m "Vision stack 1.4.0"git push origin v1.4.0The pre-push hook indexes the tag, and CAVS materialises a release row with the tag name, the commit it points at, and the aggregate of LFS files reachable there — file count and total logical bytes.
If a tag was pushed before the repository was connected, backfill it:
cav repo index --fullReading them
Section titled “Reading them”export API=https://cavsnode.com/api/v1export H="Authorization: Bearer $CAVS_TOKEN"
curl -sS "$API/repositories/$REPO/releases?limit=50" -H "$H"curl -sS "$API/repositories/$REPO/releases/v1.4.0" -H "$H"From the CLI, for the connected repository:
cav releasecav release --json | jq -r '.[] | "\(.tag)\t\(.lfs_file_count) files\t\(.lfs_logical_bytes) bytes"'Editing the presentation
Section titled “Editing the presentation”The tag and its commit are immutable — they come from Git. The name and notes are yours to edit, so a release can carry a changelog:
curl -sS -X PATCH "$API/repositories/$REPO/releases/v1.4.0" \ -H "$H" -H "Content-Type: application/json" \ -d '{ "name": "Vision 1.4.0 — augmented training set", "notes": "## Changes\n- Retrained on the augmented set\n- val_acc 0.942 (was 0.931)\n" }'Requires repository.update. Notes render as Markdown in the dashboard.
Consuming a release
Section titled “Consuming a release”A release is a ref, so the normal Git flow works:
git checkout v1.4.0git lfs pullOr, to pull just the files in a release without a Git checkout, list the tree at that tag and download the oids:
curl -sS "$API/repositories/$REPO/tree?ref=v1.4.0&path=checkpoints" -H "$H" \ | jq -r '.entries[] | select(.oid != null) | .oid' \ | while read -r oid; do cav download "$oid" --output "$oid.bin"; donePublishing side effects
Section titled “Publishing side effects”Indexing a new tag emits repository.release.published, which is a public
webhook event. Use it to trigger deployments, notify a channel, or kick off a
downstream build. See Webhooks.
Snapshots
Section titled “Snapshots”What they capture
Section titled “What they capture”A snapshot records a repository’s storage state at a moment: object counts, logical and physical bytes, and the tree shape at a ref. They are captured asynchronously by the worker, not synchronously by your request.
Use them to:
- Compare before and after a cleanup, a repack, or a format change.
- Keep a monthly record of growth per repository.
- Have a concrete number to point at when a bill surprises someone.
Creating one
Section titled “Creating one”cav snapshot # at the default branchcav snapshot --reference v1.4.0 # at a specific refcurl -sS -X POST "$API/repositories/$REPO/snapshots" \ -H "$H" -H "Content-Type: application/json" \ -H "Idempotency-Key: monthly-2026-07" \ -d '{"ref": "main"}'Requires repository.push. The call returns as soon as the request is queued —
storage.snapshot.created fires when the capture completes.
Listing them
Section titled “Listing them”curl -sS "$API/repositories/$REPO/snapshots?limit=50" -H "$H"curl -sS "$API/repositories/$REPO/snapshots?before=2026-07-01T00:00:00Z" -H "$H"before is an RFC 3339 cursor for paging backwards.
Automating a monthly capture
Section titled “Automating a monthly capture”name: CAVS monthly snapshoton: schedule: - cron: '0 3 1 * *' # 03:00 UTC on the 1st workflow_dispatch:
jobs: snapshot: runs-on: ubuntu-latest steps: - name: Queue a storage snapshot run: | curl -sS --fail-with-body -X POST \ "https://cavsnode.com/api/v1/repositories/${{ vars.CAVS_REPO_ID }}/snapshots" \ -H "Authorization: Bearer ${{ secrets.CAVS_TOKEN }}" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: monthly-$(date -u +%Y-%m)" \ -d '{"ref": "main"}'Releases vs snapshots vs generations
Section titled “Releases vs snapshots vs generations”| Created by | Immutable | Answers | |
|---|---|---|---|
| Release | pushing a Git tag | tag/commit yes, name/notes no | “what shipped as 1.4.0?” |
| Snapshot | you, on demand | yes | “what were we storing on this date?” |
| Generation | every finalized push | yes | “which consistent tree state is current?” |
- Storage insights — the metrics snapshots feed.
- Lifecycle & maintenance — GC, repack, retention.
- Webhooks — react to releases and snapshots.

