@vcityio/cli
v0.7.4
Published
vcity command-line interface for org owners
Readme
@vcityio/cli
Official command-line interface for vcity. Modeled after gh, gcloud, and vercel — terminal-first product management for org owners and staff.
Install
# Standalone binary — no Node, no bun, nothing else required
curl -fsSL https://vcity.io/cli/install.sh | sh
# OR via npm (Node 20+)
npm install -g @vcityio/cliThe curl installer detects your platform (darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64), downloads the matching binary from GitHub Releases, and drops it into /usr/local/bin/vcity. Falls back to npm install -g if your platform doesn't have a published binary.
Pin a specific version or install dir:
VCITY_CLI_VERSION=0.1.0 curl -fsSL https://vcity.io/cli/install.sh | sh
VCITY_CLI_INSTALL_DIR=$HOME/.local/bin curl -fsSL https://vcity.io/cli/install.sh | sh
VCITY_CLI_FORCE_NPM=1 curl -fsSL https://vcity.io/cli/install.sh | shUninstall
curl -fsSL https://vcity.io/cli/uninstall.sh | shAuto-detects how you installed (binary in /usr/local/bin or npm-global) and removes both. Also wipes ~/.vcity (auth tokens + config) by default — set VCITY_CLI_KEEP_CONFIG=1 to keep your tokens, or VCITY_CLI_FORCE=1 to skip the confirmation prompt when run interactively.
Manual paths if you prefer:
sudo rm /usr/local/bin/vcity # binary install
npm uninstall -g @vcityio/cli # npm install
rm -rf ~/.vcity # local config + tokensFirst run
vcity loginOpens a browser for the device-flow approval. Stores tokens at ~/.vcity/auth.json (mode 0600). Subsequent commands use that file — no password to manage.
vcity org list # show orgs you have access to
vcity org use my-shop # set the active org for future commands
vcity products list # uses the active org
vcity products list --org acme # one-off override
vcity products get prod_abc123
vcity whoami
vcity logoutEvery read command accepts --json for scripting. Output auto-falls-back to JSON when stdout isn't a TTY (pipes, redirects, CI runs).
Available commands
| Command | What it does |
|---------|--------------|
| vcity login [--api-base-url <url>] [--no-browser] | Device-flow login. Writes auth file. |
| vcity logout | Revoke server-side token + delete local auth file. |
| vcity whoami [--json] | Print the logged-in user + active org. |
| vcity org list [--json] | List orgs you can access. |
| vcity org use <slug> | Set the active org. |
| vcity products list [--org <slug>] [--limit <n>] [--json] | List products of the active org. |
| vcity products get <id> [--org <slug>] [--json] | Print a single product. |
| vcity products create [--name --price --currency --sku --data @file] [--json] | Create a product. --data seeds the body; named flags override. |
| vcity products update <id> [--name --price --currency --sku --visibility --availability --data] | Patch product fields. |
| vcity products delete <id> [--yes] [--json] | Soft-delete a product. Asks y/N unless --yes. |
| vcity events list [--org <slug>] [--limit <n>] [--status active\|disabled] [--json] | List events. |
| vcity events get <id> [--org <slug>] [--json] | Print a single event. |
| vcity events create [--name --starts-at --ends-at --slug --data] | Create an event. --starts-at / --ends-at accept ISO or epoch-ms. |
| vcity events update <id> [--name --starts-at --ends-at --slug --status --data] | Patch event fields. |
| vcity events delete <id> [--yes] | Soft-delete an event. |
| vcity rooms list [--org <slug>] [--limit <n>] [--json] | List rooms. |
| vcity rooms get <id> [--org <slug>] [--json] | Print a single room. |
| vcity rooms create [--title --description --type --data] | Create a room. |
| vcity rooms update <id> [--title --description --type --disabled --data] | Patch room fields. |
| vcity rooms delete <id> [--yes] | Soft-delete a room. |
| vcity bookings list [--org <slug>] [--limit <n>] [--status <s>] [--json] | List bookings. |
| vcity bookings get <id> [--org <slug>] [--json] | Print a single booking. |
| vcity orders list [--org <slug>] [--limit <n>] [--status <s>] [--json] | List orders. |
| vcity orders get <id> [--org <slug>] [--json] | Print a single order. |
| vcity quotes list [--org <slug>] [--limit <n>] [--status <s>] [--json] | List quote requests. |
| vcity quotes get <id> [--org <slug>] [--json] | Print a single quote. |
| vcity quotes create [--name --email --product --quantity --phone --variation --company --note --data] | Create a quote request. |
| vcity quotes update <id> [--status --assignee --name --email --product --quantity --phone --variation --company --note --data] | Patch quote fields. |
| vcity quotes delete <id> [--yes] [--json] | Delete a quote. Asks y/N unless --yes. |
| vcity update [--check] [--yes] [--json] | Self-update the CLI binary. |
--data flag
Create / update commands accept --data <jsonOrPath>:
- Inline:
--data '{"name":"My Product","price":19.99}' - File:
--data @./product.json - Stdin:
--data -— reads the JSON body from stdin, e.g.cat product.json | vcity products create --data -
The @file form is deliberately restricted as a path-traversal defence: the
path must end in .json and must resolve inside the current working
directory (symlinks are resolved first, and hard links are rejected). An
absolute path outside the cwd fails with --data: @file path must be inside the
current working directory. To send a body that lives elsewhere, pipe it
instead: cat /elsewhere/body.json | vcity products create --data -.
Named flags (--name, --price, …) override values in --data. Combine the
two to start from a template file and override one field per invocation.
Delete safety
Delete commands ask y/N before sending the request. Pass --yes to skip the
prompt (required in --json / non-TTY mode). products / events / rooms
deletes are soft — the record stays in the database with deletedAt set,
and read endpoints filter it out. quotes delete is permanent — the
record is removed outright.
Environment variables
| Variable | Purpose |
|----------|---------|
| VCITY_API_BASE_URL | Override the API host (e.g. https://staging.vcity.io). Also pins ~/.vcity/auth.json's stored origin: if the file's api_base_url doesn't match this value (or the hardcoded https://vcity.io default when unset), the CLI treats it as untrusted and prompts for re-login. If you log in against a non-default host with --api-base-url, set this env var to the same value so subsequent commands can verify the persisted URL. |
| VCITY_CONFIG_DIR | Override the config dir (default ~/.vcity). Handy for sandboxing dev sessions. |
| VCITY_NO_OPEN_BROWSER | Never auto-launch a browser during vcity login. |
| VCITY_NO_UPDATE_CHECK | Disable the background "new version available" check. |
| VCITY_DEBUG | Print full stack traces on error — helpful when filing a bug report. |
CI tip: vcity detects non-interactive stdout and emits JSON without --json. Combine with jq for pipelines.
Update notifications
vcity checks the npm registry once every 24h (cached at
~/.vcity/update-check.json) for a newer release. When one exists, a one-line
banner is printed to stderr after the command finishes:
→ vcity 0.3.0 available (you have 0.2.1). Run `vcity update` to upgrade.The check is silent when piped or non-interactive, in --json mode, when
running vcity update itself, or when VCITY_NO_UPDATE_CHECK=1 is set. The
fetch has a 1.5s timeout and never blocks command output.
Authentication
The CLI uses device-flow tokens (vcli_…) issued through the vcity web app. They inherit your user's org permissions. Refresh tokens rotate single-use — token theft revokes the entire session.
For server-to-server integrations, generate an org API key (vapi_…) from the vcity dashboard and use the @vcityio/api-client SDK directly.
Scripting
# Pipe to jq
vcity products list --org acme --limit 5 \
| jq -r '.products[] | "\(.id)\t\(.name)"'
# Exit codes
if ! vcity whoami --json >/dev/null 2>&1; then
vcity login
fiNon-zero exit codes:
1— generic error (no active org, no auth, request failed)2— usage / bad arguments
Running from source (monorepo contributors)
To exercise an unreleased command without publishing, run the CLI from the monorepo root:
npm run vcity-cli -- cards list --org acme --project <projectId> --jsonEverything after -- is passed straight through, so the invocation is identical to the
installed binary.
Do not call npx tsx packages/vcity-cli/src/index.ts directly — it fails with
Cannot find package '@vcityio/api-client'. That import is a TypeScript path alias declared
in tsconfig.base.json, and there is no root tsconfig.json for tsx to pick up implicitly,
so the alias goes unresolved. The vcity-cli script bakes in the required
--tsconfig tsconfig.base.json flag.
Support
Email [email protected] for issues, feature requests, or token problems.
Related
@vcityio/api-client— the typed SDK this CLI is built on. Use it directly when you need programmatic access from your own services.- API reference — OpenAPI 3.1 + Scalar.
License
MIT © Otherwise SAS
