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.
Installation
Section titled “Installation”curl -fsSL https://raw.githubusercontent.com/orelvis15/cavs-hub-cli/main/install.sh | shDetects 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.
curl -fsSL https://raw.githubusercontent.com/orelvis15/cavs-hub-cli/main/install.sh \ | CAVS_INSTALL_DIR="$HOME/bin" shYou also need git-lfs: brew install git-lfs.
curl -fsSL https://raw.githubusercontent.com/orelvis15/cavs-hub-cli/main/install.sh | shDetects x86_64 or aarch64. If the target directory isn’t on your PATH the
script prints the line to add:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profileAnd git-lfs: apt install git-lfs, dnf install git-lfs, or equivalent.
The installer is POSIX shell, so install manually:
-
Download
cav-x86_64-pc-windows-msvc.exefrom the releases page. -
Rename it to
cav.exeand put it somewhere like%LOCALAPPDATA%\Programs\cav\. -
Add that folder to your
PATH:Terminal window $dir = "$env:LOCALAPPDATA\Programs\cav"[Environment]::SetEnvironmentVariable("Path", "$([Environment]::GetEnvironmentVariable('Path','User'));$dir", "User") -
Open a new terminal, then also put
cavs-lfs-agent.exefrom the engine releases on yourPATHsocav repo connectcan wire Git LFS up.
Scoop and winget packages are planned.
git clone https://github.com/orelvis15/cavs-hub-clicd cavs-hub-clicargo build --releasecp target/release/cav ~/.local/bin/Requires a recent stable Rust toolchain.
Verify and update
Section titled “Verify and update”cav --versioncav doctor # full environment + connectivity diagnosiscav update # self-update to the latest releasecav update --check # report only, download nothingcav 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.
First-time setup
Section titled “First-time setup”cav config set api https://cavsnode.comcav loginAPI base precedence: --api flag → $CAVS_API → stored config → built-in
default.
Global flags
Section titled “Global flags”| 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 |
Commands
Section titled “Commands”Authentication
Section titled “Authentication”cav login # prompts for the tokencav login --token cavs_pat_... # avoid: lands in shell historyecho "$CAVS_TOKEN" | cav login --token-stdincav logout # forget stored credentialscav whoami # identity + organizationscav status # configuration and login statecav login validates the token against the API before persisting it, then prints
your identity and organizations.
Configuration
Section titled “Configuration”cav config list # all values + the config file pathcav config get apicav config set api https://cavsnode.comapi is the only writable key — use cav login for tokens.
Repository
Section titled “Repository”cav repo connect <org>/<repo> # the full connect + import flowcav repo connect <org>/<repo> --skip-lfs # only set lfs.urlcav repo connect <org>/<repo> --skip-index # no hook, no initial backfillcav repo connect <org>/<repo> --agent-path /opt/cavs/cavs-lfs-agent
cav repo index --full # backfill all branches and tagscav repo index # incrementalcav repo index --ref main --ref develop # specific refscav repo index --dry-run # show what would be uploadedcav install-lfs [--agent-path PATH] wires only the transfer agent, without
touching the repository link — useful in a repository already connected by hand.
Git wrappers
Section titled “Git wrappers”Thin wrappers that check the CAVS wiring first, then forward extra arguments straight to Git:
cav init [path]cav clone <url> [dir] [--connect <org>/<repo>]cav push [git push args…]cav pull [git pull args…]cav sync # pull, then pushcav upload <file>... # to the connected repositorycav 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.
Hub queries
Section titled “Hub queries”cav artifacts [--org SLUG] [--type model|dataset|media|archive|other] [--query TEXT]cav search <query> # repositories and commit messagescav storage [--org SLUG] # organization storage usagecav snapshot [--reference REF] # queue a storage snapshotcav 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:
cav artifacts --json | jq -r '.[] | select(.size > 1e9) | .name'cav storage --json | jq '.saved_pct'cav upload ./model.bin --json | jq -r '.[].oid'Diagnostics
Section titled “Diagnostics”cav doctorChecks, 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.
Configuration file
Section titled “Configuration file”~/.config/cav/config.tomlapi_base = "https://cavsnode.com"token = "cavs_pat_…"account = "[email protected]"Environment variables
Section titled “Environment variables”| 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) |
Git config the CLI writes
Section titled “Git config the CLI writes”git config --get lfs.url # the repository's /lfs endpointgit config --get lfs.standalonetransferagent # cavsgit config --get lfs.customtransfer.cavs.path # cavs-lfs-agentgit config --get lfs.customtransfer.cavs.concurrent # falsegit config --get cavs.repo-id # the repository UUIDgit config --get cavs.api-base # the API basePlus 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.
Exit codes
Section titled “Exit codes”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 |
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 ;; esacfiScripting notes
Section titled “Scripting notes”- Use
--jsonand parse withjq; the human output is not a stable interface. - Use
--quietin CI so logs stay readable. - Pass
CAVS_TOKENfrom a secret store; never--tokenon the command line. - Branch on exit codes, not on message text.
cav upload,cav downloadandcav verifyneed a connected repository — they readcavs.repo-idfrom the Git config. In a bare CI checkout, runcav repo connectfirst or use the HTTP API directly.
- Connect a Git repository — the full workflow.
- CAVS LFS agent — options and tuning.
- Troubleshooting — common failures.

