Object Storage (S3)¶
The verda object-storage commands provide AWS-CLI-style access to Verda's S3-compatible object storage (the oss alias is shorter: verda oss ls). They use a separate credential set (keys prefixed verda_s3_) so object-storage access is independent of your main API credentials while still sharing the profile system.
Every command works two ways: non-interactively with positional URIs and flags (for scripts, pipes, and AI agents), and interactively with a TUI when you omit the target on a terminal.
Command reference¶
| Command | Description |
|---|---|
verda object-storage configure |
Set up S3 credentials (wizard or flags) |
verda object-storage show |
Print active S3 credential status (no secrets) |
verda object-storage ls |
List buckets, or list keys under a prefix |
verda object-storage cp |
Copy between local and S3, or S3 and S3 |
verda object-storage mv |
Move (copy + delete source) |
verda object-storage rm |
Delete one or many keys |
verda object-storage sync |
Sync a directory and a prefix in either direction |
verda object-storage mb |
Make bucket |
verda object-storage rb |
Remove bucket (optionally force-empty first) |
verda object-storage presign |
Generate a time-limited GET URL for a key |
verda object-storage ls-uploads |
List incomplete multipart uploads (resumable) |
verda object-storage abort-uploads |
Abort incomplete multipart uploads |
Configure credentials¶
First create an access key in the Verda dashboard: log in → select your project → Project management → Credentials → Object Storage Access Keys.
Run the interactive wizard. The endpoint and region come pre-filled with defaults (https://objects.fin-03.verda.storage, us-east-1), so you normally just pick a profile and paste the access key and secret:
Non-interactive (endpoint defaults if omitted; pass --endpoint for another region):
Show the active configuration (no secrets are printed):
| Flag | Description |
|---|---|
--access-key |
S3 access key ID |
--secret-key |
S3 secret access key |
--endpoint |
S3 endpoint URL (defaults to https://objects.fin-03.verda.storage) |
--region |
Region (defaults to us-east-1) |
--profile |
Profile to write to (defaults to the active profile) |
--credentials-file |
Override the credentials file path |
S3 credentials are stored in the same credentials file as your API credentials (~/.verda/credentials), using verda_s3_-prefixed keys.
List buckets and objects¶
verda object-storage ls # list all buckets
verda object-storage ls s3://my-bucket # top-level keys + prefixes (delimiter /)
verda object-storage ls s3://my-bucket --recursive # every key under the bucket
verda object-storage ls s3://my-bucket --human-readable --summarize
On a terminal, running verda object-storage ls with no argument opens an interactive folder browser — drill into prefixes, run per-object actions, or multi-select objects to download.

Copy files¶
# upload
verda object-storage cp ./local-file s3://my-bucket/key.txt
# download
verda object-storage cp s3://my-bucket/key.txt ./local-file
# server-side copy (S3 → S3, no data traverses the client)
verda object-storage cp s3://src-bucket/key s3://dst-bucket/key
# recursive directory upload
verda object-storage cp ./dir s3://my-bucket/prefix/ --recursive
# with include/exclude filters (match against relative path; * does not cross /)
verda object-storage cp ./dir s3://my-bucket/prefix/ --recursive \
--include '*.go' --exclude '*_test.go'
# override content-type (otherwise inferred from extension)
verda object-storage cp ./file s3://my-bucket/key --content-type 'application/json'
# preview what would happen
verda object-storage cp ./dir s3://my-bucket/prefix/ --recursive --dryrun
# tune throughput for large transfers
verda object-storage cp ./big.bin s3://my-bucket/big.bin --concurrency 16 --part-size 32MiB
| Flag | Description |
|---|---|
--recursive |
Copy a directory or prefix recursively |
--include / --exclude |
Filter by relative path (filepath.Match; * does not cross /) |
--content-type |
Override the content-type (otherwise inferred from extension) |
--dryrun |
Print what would happen without transferring |
--concurrency |
Number of concurrent parts for large transfers |
--part-size |
Multipart part size (e.g. 32MiB) |
--no-resume |
Force a fresh transfer, ignoring any saved progress |
To upload without typing an s3:// URI, run verda object-storage cp <file> with no destination on a terminal — a wizard picks the destination bucket and folder for you:

Resumable large transfers¶
Single-file uploads and single-object downloads larger than the part size are multipart, parallel (5 concurrent parts by default), and resumable. If a transfer is interrupted (network drop, Ctrl+C, crash), re-run the exact same command and it continues — only the missing parts are sent or fetched:
# upload; if it breaks, run the SAME command again to resume
verda object-storage cp ./model.safetensors s3://my-bucket/models/model.safetensors
# download; re-run to resume (a partial <dest>.part is kept until it completes)
verda object-storage cp s3://my-bucket/models/model.safetensors ./model.safetensors
# force a fresh transfer, ignoring any saved progress
verda object-storage cp s3://my-bucket/models/model.safetensors ./model.safetensors --no-resume

A few details worth knowing:
- Resume reuses the same part size that the interrupted run used. Passing a different
--part-size(or changing the file) is detected and the transfer restarts cleanly. Part sizes accept binary forms (MiB,GiB); the looseMB/Mforms are also treated as binary (1MB= 1048576 bytes). - Resume state lives locally: uploads under
~/.verda/s3-uploads/, downloads under~/.verda/s3-downloads/(plus a<dest>.partfile). The key is a hash of the source path + destination, so resume requires re-running with the same source and destination. -
Incomplete uploads stage parts on the server that cost storage until completed or aborted. Use
verda object-storage ls-uploadsto list them (and pick one to resume) andverda object-storage abort-uploadsto clean them up.
-
No silent overwrites: if a local file of the same name already exists, an interactive download is saved as
name-2.ext,name-3.ext, … A genuine resume of the same object keeps its original name so its.partis continued. - Recursive (
--recursive),sync, andmvtransfers are not yet resumable per-file.
Move files¶
mv has the same flag surface as cp; the source is removed on success.
verda object-storage mv ./tmpfile s3://my-bucket/final-name
verda object-storage mv s3://my-bucket/old-key s3://my-bucket/new-key
On a terminal, verda object-storage mv with no arguments (or a single s3:// source) opens an S3 → S3 move/rename wizard. Local ↔ S3 moves always require both explicit arguments.

Sync directories¶
# local → S3
verda object-storage sync ./local-dir s3://my-bucket/prefix/
# S3 → local
verda object-storage sync s3://my-bucket/prefix/ ./local-dir
# remove destination files that don't exist in source (AWS-convention --delete)
verda object-storage sync ./a s3://bucket/ --delete
# treat any mtime difference as "changed" (not just newer-source)
verda object-storage sync ./a s3://bucket/ --exact-timestamps --dryrun
By default, sync copies a file when the source size differs or the source is newer. --exact-timestamps instead copies on any mtime difference.
Remove objects¶
verda object-storage rm s3://bucket/key
verda object-storage rm s3://bucket/prefix/ --recursive
verda object-storage rm s3://bucket/prefix/ --recursive --include '*.log' --yes
verda object-storage rm s3://bucket/prefix/ --recursive --dryrun
Warning
rm is destructive and prompts for confirmation unless --yes is passed. In agent mode, --yes is mandatory.

Buckets¶
verda object-storage mb s3://new-bucket-name
verda object-storage rb s3://old-bucket # only works if empty
verda object-storage rb s3://old-bucket --force # empty the bucket first, then remove
rb prompts for confirmation unless --yes. --force implies a recursive delete of the bucket contents, so be sure before using it.
Presigned URLs¶
Generate a time-limited GET URL for an object:
verda object-storage presign s3://bucket/key # default 1h
verda object-storage presign s3://bucket/key --expires-in 15m
verda object-storage presign s3://bucket/key --expires-in 24h
The URL is printed to stdout (pipe-friendly) and the expiration hint goes to stderr, so it's safe to pipe:
Multiple profiles¶
Profiles work across both API and S3 credentials. Create a second profile via:
configure and show take a local --profile flag. The other commands (ls, cp, rm, …) have no local --profile flag — select a profile with the global --auth.profile staging, the VERDA_PROFILE=staging environment variable, or persist it with verda auth use staging.
Info
configure writes to the profile you pick or name; it does not auto-follow the active profile the way the read commands do. If you create credentials for a non-active profile, point the read commands at it with --auth.profile <name>, VERDA_PROFILE, or switch with verda auth use <name>.
Output formats¶
All commands honour the global output flags:
--output table(default)--output json/--output yaml— a single structured payload at the end--agent— disables interactive prompts, implies JSON, and requires--yesfor destructive operations--debug— dumps SDK request/response metadata to stderr
Per-file progress lines (uploaded, downloaded, copied, moved, deleted) are only emitted when the format is table. Structured output produces exactly one payload so it stays parseable.
Interactive vs non-interactive¶
The interactive TUI triggers only when stdout is a terminal, you're not in --agent mode, and the output format is the default table. Otherwise an omitted target returns the command help (or a structured error in --agent).
| Command | Interactive trigger (on a TTY) | Flow |
|---|---|---|
configure |
any of --access-key/--secret-key/--endpoint missing |
credential wizard |
ls |
no argument | folder browser (drill in, per-object actions, multi-download) |
cp |
no destination (and not a bare s3:// download) |
upload wizard (source → bucket → folder → confirm) |
mb |
no argument | prompts for the new bucket name |
rb |
no argument | bucket picker, then the destructive confirm |
rm |
no argument | folder browser; tick files at a level to delete (confirm + preview) |
mv |
no args, or a single s3:// source |
S3 → S3 move/rename wizard |
Esc steps back (ascends a folder or returns to the previous wizard step); Ctrl+C exits immediately.
Environment variables¶
| Variable | Description |
|---|---|
VERDA_SHARED_CREDENTIALS_FILE |
Override the default credentials path (~/.verda/credentials) |
VERDA_PROFILE |
Select the active profile for read/transfer commands |