@gpuflow/cli
v0.5.2
Published
GPU Flow CLI — European LLM inference, sandboxes and dedicated GPU.
Readme
@gpuflow/cli
The GPU Flow CLI — European LLM inference, sandboxes and dedicated GPU, from the terminal.
No runtime dependencies: just Node 18.3+ (uses native fetch and
util.parseArgs). Data is processed in the EU (api.gpuflow.ai).
Installation
npm install -g @gpuflow/cli
gpuflow doctorOr without installing anything:
npx @gpuflow/cli doctorFrom source
For working on the CLI itself:
git clone https://dev.azure.com/gpusolutions/gpuflow-cli/_git/gpuflow-cli
cd gpuflow-cli
npm install
npm run build # dist/ is gitignored, so this is a separate step
npm link # optional: puts `gpuflow` on PATH — or run: node dist/index.jsConfiguration
gpuflow config set api-key sk-gpuflow-... # or the GPUFLOW_API_KEY variable
gpuflow config showThe config is stored in ~/.gpuflow/config.json — mode 0600 (owner-only) on
macOS/Linux; on Windows the file inherits your user-profile ACL (Node can't set
POSIX modes on NTFS).
| Variable | Default | Use |
|---|---|---|
| GPUFLOW_API_KEY | — | API key for inference |
| GPUFLOW_API_BASE | https://api.gpuflow.ai | Inference API (OpenAI/Anthropic compatible) |
| GPUFLOW_ACCOUNT_BASE | https://tf-api.gpuflow.ai | Account API (/api/me) |
| GPUFLOW_PORTAL_BASE | https://portal-api.gpusolutions.ai | Portal API (login + identity, /api/auth) |
| GPUFLOW_EMAIL / GPUFLOW_PASSWORD | — | Non-interactive login credentials (CI) |
Commands
Working today (inference API)
gpuflow models # catalog + pricing (public)
gpuflow chat "What is RDMA?" # streaming + latency/cost footer
gpuflow chat --model qwen-3.5-9b "Hello" # pick a model (also: -m)
gpuflow chat --no-stream "..." # full response at once
gpuflow doctor # validate your setup in secondsmodels lists each model with its context and price per 1M tokens
(input/output), exactly as the API returns it.
chat keeps streaming and prints a footer on stderr (so it doesn't pollute
stdout when piped) with the model, latency (TTFB + total), tokens and estimated
cost:
deepseek-v4-flash · TTFB 240ms · total 1.8s · 142 tok (32+110) · ~$0.000312doctor (alias status) checks the config, /live + /ready, API key
validity and the catalog. Balance arrives with login (Phase 1).
JSON output (scripting / CI)
Any command accepts --json: it emits a single JSON value on stdout
(decorative human output is silenced and errors come out as JSON on stderr).
gpuflow models --json | jq '.[0].pricing'
gpuflow chat --json "Hello" | jq '{model, cost_usd, latency_ms}'
gpuflow doctor --json | jq '.healthy' # exit ≠ 0 if something failsAccount (require login)
One login unlocks all of these — the same JWT authenticates both the portal and the account API.
gpuflow login # prompts for email + password
gpuflow whoami # who am I + tenant + roles
gpuflow balance # prepaid balance + key count
gpuflow usage --days 7 # consumption by model
gpuflow keys list # your API keys (prefixes only)
gpuflow keys create ci-key # create a key (shown once!)
gpuflow keys revoke sk-gpuflow-xxxx # revoke by prefix
gpuflow logout # revoke the session + clear tokenslogin uses an email + password grant. On a terminal it prompts (the
password is not echoed); for CI set GPUFLOW_EMAIL and GPUFLOW_PASSWORD (and
--json) to stay non-interactive. Tokens are stored in
~/.gpuflow/config.json (mode 0600 on macOS/Linux; your user-profile ACL on
Windows) and refreshed automatically — the access token is short-lived, so the
CLI silently renews it as needed.
keys create prints the full secret once — save it immediately; only the
prefix is recoverable afterwards.
Sandboxes, GPU & storage
GPU discovery is public (no login). The rest need a prior gpuflow login.
gpuflow gpu list # offerings (vram, cpu/mem ranges)
gpuflow gpu availability # free capacity per GPU SKU
gpuflow sandbox create --plan starter --service opencode # quick create
gpuflow sandbox create --cpu 4 --memory 8 --gpu mig-1g.23gb # custom + GPU
gpuflow sandbox create template > sandbox.yaml # scaffold a manifest
gpuflow sandbox create -f sandbox.yaml # create from a manifest
gpuflow sandbox list # your sandboxes
gpuflow sandbox status my-box # live status (phase, node, ssh port)
gpuflow sandbox usage my-box # cost this billing cycle
gpuflow sandbox pause my-box # scale to 0 (workspace kept)
gpuflow sandbox resume my-box
gpuflow sandbox auto-suspend my-box 30 # pause after 30 min idle (or: off)
gpuflow sandbox delete my-box --yes # tear down (workspace kept)
gpuflow sandbox ssh my-box # print the ssh command to connect
gpuflow storage list # your workspaces (PVCs)
gpuflow storage rm <id> --yes # delete a workspace
gpuflow ssh-key add # register ~/.ssh/id_ed25519.pub
gpuflow ssh-key listA sandbox is addressed by either its friendly label or its generated
devpod-… name (labels must be unambiguous).
sandbox create has three input modes — flags (simple), an interactive
prompt (on a TTY, when neither --plan nor --cpu/--memory is given), and a
YAML manifest (-f). It needs a registered SSH key first (ssh-key add), then
ensures a workspace (reuse --storage <id|label> or create a new one sized by
--size/the plan's disk) and posts the pod. It returns immediately with the
sandbox pending and prints the ssh command — the pod boots in the
background, so check sandbox status until it's running. sandbox create
template [path] scaffolds a commented manifest:
label: my-sandbox # friendly name (optional)
plan: starter # starter|pro|team (CPU-only), OR omit and set cpu/memory_gi
# cpu: 4
# memory_gi: 8
# gpu_sku: null # mig-1g.23gb | mig-2g.45gb | gpu
# gpu_count: 0
services: # claude-code | claude-code-glm | opencode
- opencode
auto_suspend_min: 30 # 0–1440, or: off
storage:
reuse: null # existing workspace id/label, or null to create new
size_gi: 50 # new-workspace size (10–500), used when reuse is nullPod creation may require active billing (a feature-flagged gate); if it's on and you have no card, the CLI returns the panel link to add one.
sandbox ssh prints ssh -J [email protected] developer@<pod> for you
to run — it connects through the bastion using your default
~/.ssh/id_ed25519 (register it first with ssh-key add; custom key filenames
break the proxy-jump auto-offer). Keys can't be removed via the CLI yet.
Still panel-only
Adding a payment method (the Stripe card-setup flow) stays in the panel
(https://app.gpuflow.ai). Live ssh connect is print-only here — copy the
command and run it yourself.
Status
v0.5 — sandbox create lands: flags, interactive prompt, or a YAML manifest
(create template / -f), with client-side validation and a built-in (zero-dep)
manifest reader. v0.4 brought the portal surface online (sandbox
list/status/usage/pause/resume/delete/auto-suspend/ssh, gpu, storage,
ssh-key); v0.3 the user auth (login + balance/keys/usage); Phase 0 the
models/chat/doctor/--json against the inference API. All unchanged.
Development
npm install
npm run build # tsc → dist/
npm run typecheck
node dist/index.js helpStructure
src/
index.ts # entry point + router (dispatches to each command)
lib.ts # core: config, HTTP, colored output, JSON mode, formatting
args.ts # flag parser on top of node:util (parse, JSON_OPT)
yaml.ts # minimal manifest reader (sandbox create -f, zero deps)
catalog.ts # access to /v1/models (shared by models and chat)
constants.ts # VERSION, PANEL_URL
commands/ # one module per command
help.ts config.ts models.ts chat.ts doctor.ts
auth.ts # login / logout / whoami (JWT)
account.ts # balance / keys / usage (tf-api)
sandbox.ts # sandbox lifecycle + ssh (portal/pod)
sandboxCreate.ts # sandbox create (flags / manifest / interactive)
gpu.ts # gpu offerings + availability (public)
storage.ts # workspaces / PVCs (portal/pod)
sshkey.ts # ssh-key add / list (portal)To add a command: create src/commands/<name>.ts that exports a
cmd<Name>(args: string[]) function, and import it into the switch in
src/index.ts.
Pre-commit hooks
This repo uses pre-commit. Set it up once after cloning
(needs npm install first, since the typecheck hook uses the local TypeScript):
pip install pre-commit # or: pipx install pre-commit
pre-commit install # wires .git/hooks/pre-commit
pre-commit run --all-files # optional: run against the whole repoThe hooks (see .pre-commit-config.yaml):
- no-commit-to-branch — blocks direct commits to
main/master(use a feature branch + PR). - tsc --noEmit — the code must typecheck before it lands.
- Hygiene — trailing whitespace, final newline, mixed line endings, merge-conflict markers, large files, case conflicts, and valid JSON/YAML.
