CLI

Overview

@storagesdk/cli ships two binary aliases — storage (primary) and storagesdk (for searchability) — both pointing at the same script. After install, both are on your PATH and resolve to the same binary.

The CLI is built on the same @storagesdk/adapters registry the library uses, so any adapter that works in code works from the shell with no extra wiring — just set the adapter-native env vars and pick it with --adapter <name>.

Install

# global
npm install -g @storagesdk/cli

# or one-shot via npx (no install)
npx @storagesdk/cli adapters

# or pin to a project
npm install --save-dev @storagesdk/cli

Use storage or storagesdk — both work; storage is shorter, storagesdk is unambiguous for shell history or grep.

Adapter discovery

storage adapters lists every adapter the registry knows about; pass a name to see its env vars (with required/optional flags + backend-native fallbacks).

storage adapters
fs
s3
r2
minio
tigris
azure
gcs
vercel
github
webdav
backblaze
spaces
wasabi
supabase
linode
fly
railway

Run `storage adapters <name>` to see env vars.
storage adapters tigris
Env vars for tigris:

  TIGRIS_BUCKET             required
  TIGRIS_ACCESS_KEY_ID      required
  TIGRIS_SECRET_ACCESS_KEY  required
  TIGRIS_ENDPOINT           optional
  TIGRIS_FORCE_PATH_STYLE   optional

Backend-native fallbacks show up next to the adapter-prefixed var:

storage adapters s3
Env vars for s3:

  S3_BUCKET             required
  S3_ACCESS_KEY_ID      optional  fallback: AWS_ACCESS_KEY_ID
  S3_SECRET_ACCESS_KEY  optional  fallback: AWS_SECRET_ACCESS_KEY
  S3_REGION             optional  fallback: AWS_REGION
  S3_ENDPOINT           optional
  S3_FORCE_PATH_STYLE   optional

If you already have AWS_* set in your environment, the S3 adapter picks them up automatically — no duplication.

Pick an adapter once

Every command takes --adapter <name>. If you’ll be running several in a row, set STORAGE_ADAPTER once and skip the flag:

export STORAGE_ADAPTER=tigris
export TIGRIS_BUCKET=my-bucket
export TIGRIS_ACCESS_KEY_ID=
export TIGRIS_SECRET_ACCESS_KEY=
storage ls photos/

Output format

The CLI detects whether stdout is a terminal and chooses the format. Piping always yields machine-readable JSON; in a terminal you get aligned text. Both can be forced via flags:

storage ls photos/             # human (in a terminal)
storage ls photos/ | jq        # JSON (piped to jq)
storage ls photos/ --json      # force JSON
storage ls photos/ --no-json   # force human

Errors go to stderr with a clear message and exit code; piped consumers get clean output on stdout.

storage adapters foo
# ✗ Unknown adapter 'foo'.
#   Available: fs, s3, r2, minio, tigris, azure, gcs, vercel,
#              github, webdav, backblaze, spaces, wasabi, supabase,
#              linode, fly, railway
# (exit code 1)

Errors

StorageError becomes a clean stderr message + a per-code hint and exit 1:

Where to next

Write commands print a confirmation line to stderr in human mode so stdout stays clean for piped data (e.g. cp storage://config.json -); JSON mode emits { action, from?, to?, path? } on stdout so it composes with jq.