Skip to content

CLI — cav

cav is the CAVS Node command-line client. It’s deliberately thin: authentication plus control-plane calls, with the heavy chunking work delegated to cavs-lfs-agent and the local packaging toolkit living in the separate open-source cavs binary.

Terminal window
curl -fsSL https://raw.githubusercontent.com/orelvis15/cavs-hub-cli/main/install.sh | sh

Detects Apple Silicon (arm64) or Intel (x86_64) and installs both cav and cavs-lfs-agent into /usr/local/bin, falling back to ~/.local/bin when /usr/local/bin isn’t writable.

Custom destination
curl -fsSL https://raw.githubusercontent.com/orelvis15/cavs-hub-cli/main/install.sh \
| CAVS_INSTALL_DIR="$HOME/bin" sh

You also need git-lfs: brew install git-lfs.

Terminal window
cav --version
cav doctor # full environment + connectivity diagnosis
cav update # self-update to the latest release
cav update --check # report only, download nothing

cav checks for a newer release once a day and warns on stderr. There’s an uninstall script in the repository if you need to remove it.

Terminal window
cav config set api https://cavsnode.com
cav login

API base precedence: --api flag → $CAVS_API → stored config → built-in default.

Flag Effect
--api <URL> Override the API base for this invocation
--json Machine-readable JSON on stdout (data commands)
-q, --quiet Suppress progress and info output; errors and results remain
--version Print the version
Terminal window
cav login # prompts for the token
cav login --token cavs_pat_... # avoid: lands in shell history
echo "$CAVS_TOKEN" | cav login --token-stdin
cav logout # forget stored credentials
cav whoami # identity + organizations
cav status # configuration and login state

cav login validates the token against the API before persisting it, then prints your identity and organizations.

Terminal window
cav config list # all values + the config file path
cav config get api
cav config set api https://cavsnode.com

api is the only writable key — use cav login for tokens.

Terminal window
cav repo connect <org>/<repo> # the full connect + import flow
cav repo connect <org>/<repo> --skip-lfs # only set lfs.url
cav repo connect <org>/<repo> --skip-index # no hook, no initial backfill
cav repo connect <org>/<repo> --agent-path /opt/cavs/cavs-lfs-agent
cav repo index --full # backfill all branches and tags
cav repo index # incremental
cav repo index --ref main --ref develop # specific refs
cav repo index --dry-run # show what would be uploaded

cav install-lfs [--agent-path PATH] wires only the transfer agent, without touching the repository link — useful in a repository already connected by hand.

Thin wrappers that check the CAVS wiring first, then forward extra arguments straight to Git:

Terminal window
cav init [path]
cav clone <url> [dir] [--connect <org>/<repo>]
cav push [git push args…]
cav pull [git pull args…]
cav sync # pull, then push
Terminal window
cav upload <file>... # to the connected repository
cav download <oid> [--output PATH] [--force]
cav verify <file>... # do these exact bytes exist on the Hub?

upload hashes every file first, so a bad path fails before a session opens. download requires a full 64-character SHA-256 and refuses to overwrite without --force. verify hashes locally and asks whether those oids exist — a cheap completeness check before shipping.

Terminal window
cav artifacts [--org SLUG] [--type model|dataset|media|archive|other] [--query TEXT]
cav search <query> # repositories and commit messages
cav storage [--org SLUG] # organization storage usage
cav snapshot [--reference REF] # queue a storage snapshot
cav release # list the connected repo's releases

--org defaults to your only organization; if you belong to several, it’s required (exit code 13, ORG_AMBIGUOUS).

Every data command supports --json:

Terminal window
cav artifacts --json | jq -r '.[] | select(.size > 1e9) | .name'
cav storage --json | jq '.saved_pct'
cav upload ./model.bin --json | jq -r '.[].oid'
Terminal window
cav doctor

Checks, grouped:

Group Checks
Environment git, git-lfs, cavs-lfs-agent on PATH
Authentication a stored token, and whether the API accepts it
Connectivity the API is reachable, identity resolves
Repository cavs.repo-id set, lfs.url set, pre-push hook installed

This is the first thing to run when a transfer misbehaves.

~/.config/cav/config.toml
api_base = "https://cavsnode.com"
token = "cavs_pat_…"
account = "[email protected]"
Variable Meaning
CAVS_API API base URL — overrides the stored config
CAVS_TOKEN Access token — also read by the transfer agent
CAVS_INSTALL_DIR Installer destination
CAVS_LFS_REMOTE Transfer-agent remote override
CAVS_LFS_CACHE Transfer-agent chunk cache directory
CAVS_LFS_ALLOW_INSECURE_HTTP Permit plaintext-HTTP pushes (local dev only)
CAVS_FETCH_MAX_INFLIGHT_BYTES Cap on in-flight range-request bytes (default 128 MiB)
Terminal window
git config --get lfs.url # the repository's /lfs endpoint
git config --get lfs.standalonetransferagent # cavs
git config --get lfs.customtransfer.cavs.path # cavs-lfs-agent
git config --get lfs.customtransfer.cavs.concurrent # false
git config --get cavs.repo-id # the repository UUID
git config --get cavs.api-base # the API base

Plus a pre-push hook wrapper that tees stdin to git lfs pre-push, then runs cav hook pre-push best-effort — it never blocks or fails a push.

Stable, so you can branch on them in scripts. Errors print as error[CODE]: message.

Code Slug Meaning
1 Generic failure
10 AUTH_REQUIRED Not logged in, or the token was rejected
11 PERMISSION_DENIED Authenticated but not authorized
12 REPO_NOT_CONNECTED No cavs.repo-id in this working tree
13 ORG_AMBIGUOUS Several organizations; pass --org
14 NETWORK_UNAVAILABLE Couldn’t reach the API
15 API_ERROR The API returned an error
16 RATE_LIMITED 429 — back off and retry
17 INVALID_PATH A local path or oid was invalid
18 CHECKSUM_MISMATCH Downloaded bytes didn’t match the oid
19 MISSING_OBJECT The object isn’t on the Hub
20 CONFIG_INVALID The config file is malformed
21 VERSION_UNSUPPORTED This CLI is too old for the server
Branching on a code
if ! cav verify ./model.bin; then
case $? in
19) echo "not uploaded yet"; cav upload ./model.bin ;;
10) echo "log in first"; exit 1 ;;
*) echo "unexpected failure"; exit 1 ;;
esac
fi
  • Use --json and parse with jq; the human output is not a stable interface.
  • Use --quiet in CI so logs stay readable.
  • Pass CAVS_TOKEN from a secret store; never --token on the command line.
  • Branch on exit codes, not on message text.
  • cav upload, cav download and cav verify need a connected repository — they read cavs.repo-id from the Git config. In a bare CI checkout, run cav repo connect first or use the HTTP API directly.