Skip to content

CLI reference

The datavo CLI covers configuration, catalog inspection, dataset and split authoring from spec files, downloads, and the archive/delete lifecycle. Data-plane work — selecting, iterating, attaching — is the SDK (guide).

Everything below runs as datavo <command> when the CLI is installed, or uv run datavo <command> from this repo. Most commands take --format json for machine-readable output.

Auth

datavo auth login                                    # interactive Entra login
datavo auth status                                   # local credential state
datavo auth logout                                   # clear token and MSAL cache

The CLI targets https://prod.datavo.io unless you tell it otherwise, so a fresh install needs nothing but auth login.

Profiles — only for other instances

datavo config set dev --url https://dev.datavo.io   # create/update a profile
datavo config use dev                                # make it active
datavo config list                                   # profiles, active one marked
datavo config show                                   # the active profile + server config
datavo config remove dev

Profiles live in ~/.datavo/config.json; omitting the profile name on config set names it after the URL's hostname. auth login takes no flags against an Entra server — --token, --tenant-id, --client-id and --scope are overrides for unusual setups.

Every command targets the active profile — and with none set that is production. Check datavo config list before anything that writes; DATAVO_PROFILE=<name> datavo … overrides for one invocation, as does DATAVO_API_BASE_URL=<url>.

datavo version prints the CLI's own version; it does not call the server. The server's version and public settings come from GET /config, which config set fetches and caches.

On a failure the CLI prints the request method, URL and status; a validation error (422) is summarized field-by-field, and --verbose (or DATAVO_VERBOSE=1) adds the full response body. When the CLI's version differs from the server's, the error ends with an upgrade line — a stale CLI is the usual cause of a 422 or an unparseable response, and uv tool upgrade datavo-cli is the fix.

Stores

datavo sample-store create voice_corpus_v1
datavo sample-store list
datavo sample-store list --query "spirelight trial" --sort samples   # every word, any order
datavo sample-store get voice_corpus_v1
datavo sample-store archive voice_corpus_v1         # required before delete
datavo sample-store restore voice_corpus_v1         # undo an archive
datavo sample-store delete voice_corpus_v1          # archived stores only

# operation log — inspect and revert
datavo sample-store operations list voice_corpus_v1
datavo sample-store operations remove voice_corpus_v1 <op-id> --dry-run   # what it would delete, and its blockers
datavo sample-store operations remove voice_corpus_v1 <op-id>

# the source imports whose samples the store holds, wherever each ran (the ImportedBy names)
datavo sample-store imports voice_corpus_v1
datavo sample-store imports voice_corpus_v1 --prefix studio:spirelight:session: --limit 50

# seed a disposable store from real data (chapter 5 of the guide)
datavo sample-store copy eval-scratch --source-store voice_corpus_v1 --limit 50
datavo sample-store copy ds-scratch --source-dataset voice_train_v1 --limit 30

datavo sample-store transfer <source> <target>      # move a whole store's contents

imports lists one row per source import whose samples the store holds — imported into it or brought in by adds — with its operation_id and how many of the store's samples ImportedBy would select. --prefix narrows by operation id, exactly; --offset and --limit page.

copy requires a source and --limit; --key projects keys, --has-key narrows to samples that have one, and --randomize (with --seed) takes a repeatable random subset. The full archive→delete lifecycle runs from the CLI: archive first, then delete. You archive and delete what you created — a store, a dataset, a split set — and a write grant on someone else's does not change that. You can remove the operations and producers you added, and a store's owner can remove any of them in their store. Permanent deletion is blocked while a protecting dataset depends on the store — see lifecycle and retention.

operations list shows the store's grow/attach operations oldest-first with their ids; operations remove <op-id> reverts one — an attach operation invalidates exactly the samples it wrote (so a producer re-run recomputes only them), an add or source_import removes the samples it introduced with every row on them, keys attached onto them included. It reports HTTP 409, naming every blocker, while a dataset holds those samples, work in the store is in flight, or a protected reference pins the operation. --dry-run previews an add or source_import removal, counts and blockers, and changes nothing. A removal is one transaction: a large one can outlast the client's read timeout and still commit, so confirm against operations list rather than retrying.

Samples

datavo sample get <sample_id>            # detail + available keys
datavo sample history <sample_id>        # key revision history

Datasets

Dataset and split authoring is spec-file first, which is what makes definitions reviewable and checked in:

datavo dataset list                                # names, state, sample counts, split sets
datavo dataset list --query "hw32 train" --sort relevance   # every word, any order; best match first
datavo dataset list --store voice_corpus_v1        # the datasets that read a store
datavo dataset preview --spec voice_train.yaml     # dry run: counts, no writes
datavo dataset create  --spec voice_train.yaml
datavo dataset get voice_train_v1
datavo dataset add-key-group voice_train_v1 --spec conditioning_group.yaml
datavo dataset pull voice_train_v1 --output-dir ./downloaded/train
datavo dataset archive voice_train_v1              # required before delete
datavo dataset restore voice_train_v1
datavo dataset delete  voice_train_v1              # archived datasets only

list takes --query, --include-archived, and --offset/--limit. As with stores, deletion runs archive→delete from the CLI and is blocked while a consumer depends on the dataset.

get on a ready dataset also prints its key provenance: for each key, the producers it reads with their member counts, and whether the key is pinned or reads the newest revision when the dataset froze. An imported key shows as imported xN for its N source imports. --format json prints the dataset alone; the provenance is client.get_dataset_key_provenance(name).

A spec is the create request in YAML. The canonical form keeps a workset you selected with the SDK (guide chapter 11):

name: voice_train_v1
from_workset: ws_7f3c…
shard_plan:
  shard_size: 1000
scalars:
  sample_rate: 24000

Add --wait to create to poll until the dataset is ready instead of returning the planning response. pull writes one tar per shard under <output-dir>/<key-group>/, every key group unless --key-group narrows it. Re-running a pull resumes it — each shard tar is named by its content, so a tar already on disk is skipped and only the missing shards download; --overwrite forces a fresh download of every shard.

Split sets

datavo split-set preview voice_train_v1 --spec voice_split.yaml   # dry run + diagnostics
datavo split-set create  voice_train_v1 --spec voice_split.yaml
datavo split-set get     voice_train_v1 voice_v1
datavo split-set list    voice_train_v1        # split sets under a parent dataset
datavo split-set list    --query voice_train   # search split sets by their or their dataset's name
datavo split-set splits  voice_train_v1        # the child datasets they generated
datavo split-set archive voice_train_v1 voice_v1   # required before delete
datavo split-set restore voice_train_v1 voice_v1
datavo split-set delete  voice_train_v1 voice_v1   # archived split sets only
name: voice_v1
assignment_seed: 7
splits:
  - name: train
    ratio: 0.6
  - name: val
    ratio: 0.2
  - name: test
    ratio: 0.2
rules:
  - kind: exclusivity
    keys: [speaker.txt]
    enforcement: hard
shard_plan:
  shard_size: 256

The spec's name is the split-set name and becomes the prefix of the generated datasets (voice_v1/train, …). Every split command takes the parent dataset as its first argument. Pass --split-set <name> to splits to scope the listing when a dataset has several.

Those children are ordinary datasets, so datavo dataset pull voice_v1/train --output-dir ./data downloads one split's tars the same as any other dataset.

Cache

datavo warm voice_v1/train                       # pre-populate the local cache
datavo warm voice_v1/train --key audio.wav       # only these keys
datavo warm voice_v1/train --concurrency 16      # parallel installs (default: the read prefetch pool)

warm installs shards ahead of a run by content hash — every key unless --key narrows it — and never opens a tar or decodes a sample, so it runs at the speed of the tier it reads. It reports what it did on stderr:

warmed 4032 shards / 4032 tars, 324.3 GB (4032 fetched, 0 already cached) in 812s — 399.4 MB/s for 'voice_v1/train'

--concurrency bounds the parallel installs and --cache-config points at a shards.yaml other than the default. See the shard cache and its Getting maximum read throughput section.

datavo prune-cache                               # clear stale locks and staging orphans
datavo prune-cache --dry-run                     # report only

prune-cache sweeps every folder tier of the resolved hierarchy: it removes lock files and staging orphans past their TTL, brings entries written before the tier had modes up to them, and reports what it cleared plus each tier's occupancy against max_bytes. It touches local disk only — no server, no credentials. Run it as the owner of the cache directories; entries owned by someone else are counted and named rather than skipped silently.