Skip to content

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 are created automatically during indexing, from your Git tags. Push a tag and it appears:

Terminal window
git tag -a v1.4.0 -m "Vision stack 1.4.0"
git push origin v1.4.0

The 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:

Terminal window
cav repo index --full
Terminal window
export API=https://cavsnode.com/api/v1
export 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:

Terminal window
cav release
cav release --json | jq -r '.[] | "\(.tag)\t\(.lfs_file_count) files\t\(.lfs_logical_bytes) bytes"'

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:

Terminal window
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.

A release is a ref, so the normal Git flow works:

Terminal window
git checkout v1.4.0
git lfs pull

Or, to pull just the files in a release without a Git checkout, list the tree at that tag and download the oids:

Terminal window
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"; done

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.

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.
Terminal window
cav snapshot # at the default branch
cav snapshot --reference v1.4.0 # at a specific ref
Over the API
curl -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.

Terminal window
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.

.github/workflows/cavs-snapshot.yml
name: CAVS monthly snapshot
on:
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"}'
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?”