Skip to content
PayEz-NetPublic

About

vsql — zero-dep CLI for VibeSQL. Query, manage schemas, seed data.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

32 Commits

Folders and files

Repository files navigation

vsql

A terminal interface for the hosted VibeSQL API: query your data, manage collection schemas, and insert documents.

vsql query "SELECT * FROM notes LIMIT 5"

Zero runtime dependencies. Node.js 18+. Windows, macOS and Linux.

Install

npm install -g https://github.com/PayEz-Net/vsql/releases/download/v1.3.5/vsql-1.3.5.tgz
vsql version

That installs the prebuilt release package and puts vsql on your PATH. This CLI is not on the npm registry (@vibesql/cli is not published), and npm install -g vsql is not this package: it installs an unrelated package of the same name from someone else, so always install from the release URL above. A plain npm install -g github:PayEz-Net/vsql does not work either, because on npm 11 the build step cannot find TypeScript.

To build from source instead: git clone https://github.com/PayEz-Net/vsql.git && cd vsql && npm install && npm run build && npm link.

Two ways to authenticate, for two jobs

For Use Covers
You, at the terminal: schemas, DDL, admin, ad-hoc queries Your sign-in (vsql login, device code). The primary path. every command
An app's runtime calls (a test app, a script, a service) Your KeelBase client id + KeelBase secret from the KeelBase page health, tables, schemas, collections, rows, describe, schema show, rollback --list, insert, update, replace, delete

query, and anything that CHANGES a schema (schema update, rollback), always use your sign-in: with a KeelBase secret set they are refused locally, with a hint pointing you at vsql login, and nothing is sent. Reading a schema (schema show, rollback --list) is data access, not a change, so it still works with the key. This is by design (not a permissions bug) — the KeelBase secret is the application's identity; queries and schema changes are attributed to a person, so they run on your sign-in.

Quick start: sign in (primary)

export VSQL_IDP_URL=https://idp.payez.net       # the identity service
export KEELBASE_CLIENT_ID=<your Tenant>          # your Tenant, as shown on your KeelBase page
export VSQL_HOST=<the VibeSQL API URL>           # the hosted VibeSQL API

vsql login                                   # device code (default)
vsql query "SELECT 1 AS ok"

The device approval screen does not exist yet. vsql login prints a user code and a verification URL; that URL answers 401 today (a known gap). Until the screen ships, a device code is approved by a call the signed-in user makes to the identity service, after completing 2FA:

POST {VSQL_IDP_URL}/api/ExternalAuth/agent-device/approve
Authorization: Bearer <your own access token>
Content-Type: application/json

{ "user_code": "ABCD-1234" }

Never give your user code to anyone else to approve: whoever approves it signs the CLI in as themselves. The account also needs the vibe_agents_user role on its client; if the approve answers 403 saying so, ask your administrator to grant it.

vsql login --passwordless you@example.com (an emailed 6-digit code) avoids the approval step altogether.

Tokens (access + refresh) are stored per profile in ~/.vsql/config.json and refreshed automatically.

Key-signing with a KeelBase secret (optional, for app runtime calls)

The KeelBase page in the portal issues a KeelBase client id (vibe_…) and a KeelBase secret (base64, shown once). The SDK calls them VIBE_CLIENT_ID and VIBE_HMAC_KEY; so does vsql, so one .env serves both.

export VSQL_IDP_URL=https://idp.payez.net   # or IDP_URL
export VIBE_CLIENT_ID=vibe_...              # KeelBase client id
export VIBE_HMAC_KEY=...                    # KeelBase secret - keep it in .env, never commit it

vsql health                                  # proves the id + secret: the identity service checks the signature
vsql collections                             # your collections
vsql rows vibe_agents agents                 # read a table's rows back

Key-signing covers health, tables, schemas, describe, collections, rows, schema show, rollback --list, insert, update, replace and delete. query and schema CHANGES (schema update, rollback) use your sign-in.

With both variables set, every call goes through the identity service's proxy (POST {IdP}/api/vibe/proxy), signed base64(HMAC-SHA256(base64decode(secret), "{unix seconds}|{METHOD}|{endpoint}")). What to know:

  • The secret is read from the environment only: never from a command-line argument, never written to ~/.vsql/config.json, never printed (VSQL_DEBUG=1 shows each request's target, not the secret).
  • Setting only one of the two variables is an error, not a silent fall-back to your sign-in.
  • Rotation is immediate. Rotating the secret on the KeelBase page stops the old one at once; update your .env first.
  • The secret is shown once. If you lose it, rotate it.
  • The signature covers the timestamp, method and endpoint, not the request body. A fix is tracked.
  • --host does not apply in this mode; unset the two variables to use --host with vsql login.

Beta and production environments

A KeelBase account can own more than one environment. Each environment is a separate KeelBase client with its own client id, its own secret, its own data, its own members and its own daily caps — like two separate projects. Use one for beta and one for production.

Create one in the portal: Account → KeelBase → New environment. Give it a name and, optionally, a Site URL — the app's origin, e.g. https://beta.example.com (just the address: no path, no query, no #). If you set one, that environment's users can sign in from that address. The Site URL can only be set when you create the environment; changing it afterwards is a tracked follow-up, so if you need it changed, contact support.

Vibe Agents is a per-person entitlement, so it shows the same on every environment card — enabling it does not belong to one environment.

Each environment is one set of variables:

KEELBASE_CLIENT_ID=<your Tenant>            # your Tenant, as shown on that environment's KeelBase page
VIBE_CLIENT_ID=vibe_...                      # that environment's KeelBase client id
VIBE_HMAC_KEY=...                           # that environment's KeelBase secret
VSQL_IDP_URL=https://idp.payez.net          # the identity service
VSQL_HOST=<the VibeSQL API URL>             # the hosted VibeSQL API

So two environments are two .env files (or two shell profiles): you switch environments by loading the other file. vsql reads .env from the current directory, so a project folder per environment is the simplest arrangement. A new environment starts empty of your data — no rows, no users, its own keys — so nothing is shared between them.

The same email can be a member of both environments and signs in with the same password; what it can reach is per environment.

Commands

vsql query <sql>

vsql query "SELECT * FROM notes LIMIT 5"
vsql query "SELECT * FROM notes" --format json
vsql query --file ./reports/monthly.sql

The hosted query endpoint is read-only for tenant data until row-level security lands. Row writes go through vsql insert and schema changes through vsql schema update; a write sent to query gets the API's own refusal, printed as it comes. query also only ever runs on your sign-in — with a KeelBase secret set it refuses locally instead of reaching the server (see Two ways to authenticate above). describe no longer uses it: it reads the active schema, like tables (see below).

Options: --format <table|json|csv|raw> (default table, csv when piped), --file <path>, --host <url>, --profile <name>.

vsql schemas / vsql tables [collection]

vsql schemas                  # every collection + its active schema (including empty ones)
vsql tables                   # every table, grouped by collection
vsql tables vibe_agents       # just vibe_agents' tables

Both read GET /v1/schemas — the Vibe-native schema listing, not information_schema (which 403s for a tenant key; tables used to hit it and inherited that failure). schemas shows every collection you have, even ones with no documents yet — collections only lists ones that already have some. Both work with a KeelBase secret. The old --schema <name> flag on tables (a Postgres schema namespace) no longer applies — there is no such namespace here — and is refused locally with a pointer to vsql schemas.

vsql describe <table> [collection]

vsql describe notes             # the columns of table "notes"
vsql describe notes vibe_app    # name the collection when the table is in more than one

Reads GET /v1/schemas, like tables, so it works with a KeelBase secret. It prints each column's column_name, type, format (for example date-time), pk, auto_increment and nullable, in the schema's own column order. The schema has no nullability flag, so nullable is YES when the column is not in the table's required list. It does not print a column's default or enum values, even when the schema sets them (the SQL version printed column_default); run vsql schema show <collection> to read them. A table name found in more than one collection is refused with AMBIGUOUS_TABLE and the collections named; an unknown table is TABLE_NOT_FOUND.

vsql schema show <collection> / vsql schema update <collection> --file schema.json

vsql schema show keelbase_demo
vsql schema update keelbase_demo --file schema.json --dry-run
vsql schema update keelbase_demo --file schema.json --yes

update sends the file's JSON as the new schema version and activates it (sign-in only).

vsql insert <collection> <table>

vsql insert keelbase_demo notes --data '{"title":"hello"}'
vsql insert keelbase_demo notes --file rows.json --batch   # each element of a JSON array

The document is sent as-is; the collection's schema decides the required fields. The tenant comes from your credential. --client-id is accepted for old scripts and ignored.

vsql update|replace|delete <collection> <table> <id>

vsql update keelbase_demo notes 41 --data '{"title":"updated"}'   # PATCH: merges into the row
vsql replace keelbase_demo notes 41 --data '{"title":"new"}'      # PUT: whole-document replace
vsql delete keelbase_demo notes 41                                # prompts for confirmation
vsql delete keelbase_demo notes 41 --yes                          # skip the prompt (scripts)

update merges the given fields into the row; replace overwrites the whole document. --data must be a JSON object — invalid JSON, or a non-object (an array, a bare string), fails locally with INVALID_JSON before anything is sent. delete prompts for confirmation on a terminal; --yes skips it; run non-interactively (piped, in a script, CI) without --yes and it refuses rather than deleting or hanging on a prompt nothing can answer. data update|replace|delete are aliases of these three, matching the older vsql-cli 1.1.1 spelling. All three work with a KeelBase secret, the same as insert.

vsql rows <collection> <table> / vsql collections

vsql collections
vsql rows keelbase_demo notes                    # page 1, 20 rows
vsql rows keelbase_demo notes --page 2 --page-size 50 --format json

Use rows to read back what you wrote. Hosted SQL (query) cannot see collection tables. Each row shows its document_id and the document's fields. collections lists collections that have documents; a collection with a schema but no documents yet does not appear, so check it with vsql schema show <collection>. An unknown option fails with UNKNOWN_FLAG rather than being ignored. Both commands are read-only and work with a KeelBase secret.

vsql rollback <collection>

vsql rollback keelbase_demo --list           # version history (works with a KeelBase secret)
vsql rollback keelbase_demo --dry-run
vsql rollback keelbase_demo --version 3      # sign-in only

vsql login / vsql logout / vsql config <set|show|clear> / vsql health / vsql version

config show masks tokens. When key-signing is configured, it names the KeelBase client id and says whether the secret is set. It never prints the secret. With key-signing and no sign-in profile, it says the profile is not needed.

An unknown command exits non-zero (UNKNOWN_COMMAND) rather than printing help and exiting 0.

Errors

Errors go to stderr with a code and a hint; exit code 1. A reply that is not JSON (an error page, an empty 404) is reported with its HTTP status and the start of the body:

Error [BAD_RESPONSE]: HTTP 404: (empty body)
  Hint: The server does not have this route; check the host (or VSQL_IDP_URL) points at VibeSQL.

Development

npm install
npm test        # builds, then runs the tests in test/

License

Apache-2.0 (see package.json and LICENSE).

About

vsql — zero-dep CLI for VibeSQL. Query, manage schemas, seed data.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages