20. CLI Tool
Alex wants to manage projects, run queries, and test RLS policies from the terminal.
The Eurobase CLI lets you manage your projects, database, storage, vault, and more from the command line. Install it via Homebrew or download the Go binary.
Installation
Without Homebrew (CI, agents, Linux servers), download the binary for your platform (macOS or Linux, amd64 or arm64):
The Eurobase CLI is not on npm. The npm package named eurobase is an unrelated product from another publisher. It describes itself as the official Eurobase CLI, but it isn't ours and doesn't work with your Eurobase projects. Don't install it or run npx eurobase, and never give it a Eurobase token. Install only from Homebrew (stgime/tap/eurobase) or the releases at github.com/STGime/homebrew-tap. If you set up a coding agent, tell it the same. (Our only npm package is the app SDK, @eurobase/sdk.)
Getting started
In CI or scripts, log in with a personal access token instead: eurobase login --token "$EUROBASE_PAT". A project token selects its project automatically and can run the project commands with the access you gave it. A project token can't create or delete projects: do that in the console (or after eurobase login, if your account signs in with a password only, without a passkey or SSO).
Where the CLI keeps your login, and working with several projects
Every command reads one file, $HOME/.eurobase/config.json (mode 600): your token, the active project and the API URL. eurobase login and eurobase switch write it; nothing is kept in the macOS Keychain or any other credential store, and the CLI finds the file only through HOME. There’s no profile option or --project flag yet, so to keep a test project fully apart from production, give it its own directory as HOME for the CLI, and log in there with a token scoped to that project:
Setting HOME per command keeps the rest of your shell unchanged, and the test login stays in ~/.eurobase-test for next time. A project token is refused for every other project, so even a mixed-up configuration can’t reach production. eurobase migrations up reads ./migrations/*.sql from the current directory.
Command reference
| Command | Description |
|---|---|
| Auth & Projects | |
| login | Sign in with email and password |
| logout | Clear stored credentials |
| version | Print the CLI version |
| projects list | List all projects |
| projects create <name> | Create a new project |
| projects delete <id> | Delete a project (requires --confirm) |
| switch <slug> | Set active project |
| status | Show usage and plan info |
| Database | |
| db tables | List tables (excludes system tables) |
| db schema [table] | Show columns and types |
| db objects | List views, sequences and types |
| db query "SQL" | Execute SQL and print results |
| db create-table <name> <col:type>... | Create a table with RLS preset |
| db add-column <table> <col:type> | Add a column |
| db drop-column <table> <column> | Drop a column |
| db drop-table <name> | Drop a table |
| db dump | Export schema as text |
| Schema Migrations | |
| migrations new <name> | Create the next numbered migration file in ./migrations |
| migrations up | Apply pending migrations to the active project (idempotent) |
| migrations status | Local files vs applied versions |
| Keys & Config | |
| keys show | Display API keys |
| keys regenerate | Rotate API keys |
| init | Generate .env, CLAUDE.md, .cursorrules |
| Logs | |
| logs | Show recent request logs |
| logs --tail | Stream logs in real time |
| Vault | |
| vault list | List secret names |
| vault get <name> | Get decrypted value |
| vault set <name> <value> | Store a secret |
| vault delete <name> | Delete a secret |
| Edge Functions (serverless TypeScript/JavaScript) | |
| edge-functions list | List deployed edge functions |
| edge-functions deploy <name> | Deploy from functions/<name>.ts (or --file); --no-verify-jwt for public functions |
| edge-functions get <name> | Show details and source code |
| edge-functions invoke <name> | Invoke with optional --data JSON body |
| edge-functions logs <name> | View invocation logs |
| edge-functions delete <name> | Delete an edge function |
| Cron & RPC Functions | |
| cron list | List scheduled jobs |
| cron logs <id> | Show run history |
| functions list | List RPC functions (Postgres) with their arguments |
| functions get <name> [--args "…"] | Print the function's CREATE OR REPLACE statement (next CLI release) |
| functions create <name> | Create from file |
| functions delete <name> | Drop function |
| Storage | |
| storage ls | List files |
| storage upload <local> <key> | Upload a file |
| storage download <key> <local> | Download a file |
| storage delete <key> | Delete a file |
| storage url <key> | Generate signed URL |
| Compliance | |
| compliance report | Generate the DPA / sub-processor report |
| compliance sub-processors | List active sub-processors |
Testing RLS policies
Test your policies the way your users actually reach your data: as an authenticated client. Create a few test end-users in a separate project, sign each one in, and exercise the SDK (or REST API) with that user's access token. Row-Level Security is evaluated under the same non-owner role as in production, so what a test user can read or write is exactly what a real client would get.
import { createClient } from '@eurobase/sdk'
const eb = createClient({ url: PROJECT_URL, apiKey: PUBLIC_KEY })
// Sign in as a seeded test user, then read/write under their session.
await eb.auth.signIn({ email: 'alice@example.test', password: '...' })
const { data: mine } = await eb.db.from('tasks').select('*') // only Alice's rows
const { error } = await eb.db.from('tasks').update(BOB_TASK_ID, { title: 'x' }) // RLS blocks updating Bob's row
// Sign out -> anonymous: a protected table returns nothing.
await eb.auth.signOut()
const { data: anon } = await eb.db.from('tasks').select('*') // []Each session carries its identity automatically: the platform sets app.end_user_id and app.end_user_role for the request, which your policies read through auth_uid(), auth_role() and is_service_role(). Confirm what a session resolves to with GET /v1/auth/user using that user's token. The Row-Level Security chapter has the policy patterns and a "Test it from the SDK" walkthrough.
Why not test from inside the database (e.g. pgTAP)? Every statement you run on Eurobase goes through a non-owner, RLS-enforced role, one statement at a time, with no transaction control — the same constraints that make your RLS guarantees trustworthy. Testing policies from inside the database would mean relaxing exactly that boundary. Our EU-managed Postgres also ships a vetted, security-reviewed set of extensions, and in-database test frameworks such as pgTAP aren't part of it. Testing as an authenticated client covers the whole path — sign-in → identity → policy → response — which is what your users actually exercise.