The wb CLI
wb (also wharfbase) does from a terminal what the web UI does: find databases, inspect them, connect, browse, run SQL, open a native client, and look after the installation. Every command can print JSON for scripts.
Where to run it
Section titled “Where to run it”On the server, nothing to install: the installer’s wharfbase command passes everything it doesn’t know to the CLI inside the container, which needs no login (it acts as the owner through a socket only the server can open).
wharfbase lswharfbase query pg17 "SELECT count(*) FROM orders"The installer’s own commands (up, down, restart, logs, status, upgrade, uninstall) keep their meaning: wharfbase status shows the containers, wharfbase wb status the CLI’s summary. Without the installer’s command: docker exec -it wharfbase wb ls.
From your laptop or CI, install it from npm (Node 24+) and sign in:
npm install -g wharfbasewb login https://db.example.com # asks for email, password, and a 2FA code if you use onewb lsA URL without https:// means plain HTTP (fine for localhost; elsewhere wb login warns you). For a self-signed certificate add --insecure. The session lasts 30 days (WB_CLI_SESSION_TTL_DAYS) and is stored in ~/.config/wharfbase/config.json, readable only by you. wb logout ends it.
Several servers: wb login https://staging.example.com --profile staging, then --profile staging on any command (the last login becomes the default). In CI, set WB_URL and WB_TOKEN instead of logging in: on Team, WB_TOKEN can be an API token from Settings → API tokens (wbt_…, scoped and revocable).
Finding and inspecting
Section titled “Finding and inspecting”wb status # version, plan, databases found/connected, last scanwb scan # scan now and print what changed (--deep also looks for SQLite files)wb ls # every database: engine, version, container, endpoint, reachability, findingswb ls --engine postgres,mysql --status runningwb inspect pg17 # everything about one: storage, credentials hints, consumers, findings, evidencewb topology # compose projects → containers → the databases they run or usewb topology --dot | dot -Tsvg > topology.svgwb findings --severity highWhile wb scan waits, it shows where the scan is: inspecting containers 120/200, checking databases, finding SQLite files, saving. That works for a scan of an agent’s server too (--server).
<db> can be the id (or its first characters), the name shown in the list, the container name or the compose service. When a name matches several databases, wb lists them and asks for the id.
Connecting and browsing
Section titled “Connecting and browsing”wb connect pg17 # asks for the user and password; offers the container's password when it has onewb connect pg17 --user app --use-detected-password --rememberprintf %s "$PW" | wb connect mysql --user root --password-stdin --read-onlywb dbs pg17 # databases on that server, with sizeswb tables pg17 -d appdb -s public # tables, views, collections, with row estimateswb describe pg17 customers # columns, indexes, foreign keysA connection follows the same rules as in the UI: production databases are read-only until writes are unlocked, viewers are read-only, and the Community plan connects up to 5 databases per server (wb connect exits with code 5 at the limit). A password you didn’t save is asked for again when the server restarts (or pass --password-stdin).
Running SQL
Section titled “Running SQL”wb query pg17 "SELECT id, email FROM customers ORDER BY id LIMIT 10"wb query pg17 --format csv "SELECT * FROM orders" > orders.csvcat migration.sql | wb query mysql -d appdb # a whole script from stdin; stops at the first errorwb query redis "HGETALL user:1" # console commands for Redis and MongoDBwb query pg17 --json "SELECT 1" | jq '.statements[0].rows'Results stream as they come. Each statement stops at 1,000 rows unless you pass --max-rows. Ctrl+C cancels the query on the database. The same read-only rules and audit log as the SQL editor apply.
A native client: wb shell
Section titled “A native client: wb shell”wb shell pg17 # psql, mysql, mongosh or redis-cli, already connectedIt starts the database’s own client in a short-lived container on the database’s network, and removes it when you exit. This needs ephemeral containers, which are off by default: add WB_GUARD_ALLOW_EPHEMERAL=true to .env next to docker-compose.yml and run wharfbase up. The connection must be writable for you, since the client can do anything the database user can.
Administration
Section titled “Administration”wb users lswb audit verify # checks the audit log's hash chainwb audit tail -f --action sql.executedwb license status # plan, limits, usage, expirywb license activate eyJhbGciOi… # or `-` to read the key from stdinwb license deactivate # frees this instance's seat; --force when the license server is unreachablewb doctor # checks Docker, the guard, networks, disk, the master keywb doctor --bundle # a redacted zip for support (see "What Wharfbase reads")On the server only:
wharfbase setup-token # before setup: the first-run tokenwharfbase keys rotate # a new master key; every stored password is re-sealedWith the standard install the key is a file you own (secrets/master.key), so keys rotate prints the new key once: put it in that file and run wharfbase up. The restart re-seals everything; until then the old key keeps working. With a key Wharfbase generated in its data volume, the rotation happens right away.
wb store migrate copies the store to PostgreSQL, for a hub that will run on it (and, on Team, with a standby next to it). Run it inside the container, with the URL in the environment so the password stays out of the process list:
docker exec -it -e WB_STORE_URL="postgres://wharfbase:…@db:5432/wharfbase" wharfbase wb store migrateThen set WB_STORE_URL for the container and restart it. High availability has the whole procedure.
Scripts
Section titled “Scripts”--jsonprints one JSON document per command (audit tail -fprints one per line). Each command’s output has a schema: apps/cli/test/schemas.-qprints only ids (wb ls -q,wb connect … -q) and silences progress.- Errors go to stderr; with
--jsonas{"error":{"code","message","hint"}}. - Exit codes:
0ok,1error,2usage,3auth,4not found,5plan limit,6unreachable,130cancelled.
for id in $(wb ls -q --engine postgres --status running); do wb inspect "$id" --json | jq -r '"\(.displayName) \(.version)"'doneTroubleshooting
Section titled “Troubleshooting”Not signed in(exit 3):wb login <url>, or check--profile,WB_URLandWB_TOKEN.Cannot reach …(exit 6): the URL, the port (8480 by default) and any reverse proxy in between. Behind a proxy,wb shellalso needs HTTP upgrades passed through (the same setting as websockets).Permission denied on the admin socket: inside the container, run it as the server’s user:docker exec -u wharfbase wharfbase wb …(thewharfbasecommand does).wb shell: “the socket-guard does not allow”: see A native client. “The image … is not on the server”: pull it there once (docker pull postgres:17-alpine); Wharfbase never pulls images.