SDKs & integrations
CLI
The orbitnest CLI signs you in, links a directory to a project, runs SQL migrations, checks schema drift, generates TypeScript types and manages webhooks and SMS.
The orbitnest CLI brings the day-to-day backend workflow into your terminal and your repo. Sign in once, link a directory to a project, then run versioned SQL migrations, ad-hoc SQL, schema drift checks and type generation against that project.
Install
The CLI is published to npm as @orbitneststudio/cli and installs a binary named orbitnest. It requires Node.js 18 or later. This page describes version 0.6.0, which isn't on npm yet. Behavior that is new in 0.6.0 is marked "from version 0.6.0".
npm install -g @orbitneststudio/cli
orbitnest --helpOr run it without installing:
npx @orbitneststudio/cli --helpQuickstart
# 1. Sign in (stores tokens in ~/.orbitnest/credentials.json)
orbitnest login
# 2. Link this directory to a project (writes .orbitnest/config.json)
orbitnest link my-app
# 3. Scaffold a migration, edit it, then apply it
orbitnest migration new "create posts table"
orbitnest db push
# 4. Generate TypeScript types from the live schema
orbitnest gen typesAuthentication
Sign in
orbitnest loginlogin signs in with your OrbitNest admin email and password. It reads each value from the first source that has one:
| Value | Flag | Environment variable | Fallback |
|---|---|---|---|
--email, -e | ORBITNEST_EMAIL | Interactive prompt | |
| Password | --password | ORBITNEST_PASSWORD | Masked interactive prompt |
| Two-factor code | --code | ORBITNEST_MFA_CODE | Interactive prompt |
| API URL | --url | ORBITNEST_API_URL | https://api.orbitnest.io |
Without a TTY (for example in CI), the password and two-factor code cannot be prompted for, so pass them as flags or environment variables.
If your account has two-factor authentication turned on, the first sign-in step returns a challenge and the CLI asks for a code. Enter the 6-digit code from your authenticator app or one of your recovery codes.
ORBITNEST_EMAIL=you@example.com \
ORBITNEST_PASSWORD="$ORBITNEST_PASSWORD" \
ORBITNEST_MFA_CODE=123456 \
orbitnest loginEmail and password only
The CLI has no browser-based Google, GitHub or Apple sign-in. If you use the MCP server, its orbitnest_login tool supports those providers and writes the same credentials file, so the CLI can use that session too.
Tokens and sessions
- Tokens are stored in
~/.orbitnest/credentials.jsonwith file mode0600, in a~/.orbitnestdirectory with mode0700. The MCP server reads and writes the same file. From version 0.6.0, the file is written atomically (a temporary file, then a rename), and its mode is reset to0600on every write. - When the API rejects an expired access token, the CLI exchanges the stored refresh token for a new one, saves it, and retries the request once. If the refresh fails, the command exits and asks you to run
orbitnest loginagain. - Refresh tokens rotate, and reusing an old one revokes the session. From version 0.6.0 (and MCP server 1.4.0), refreshes are serialized through a lock file,
~/.orbitnest/credentials.lock. Before refreshing, the CLI re-reads the credentials file. If another CLI or MCP process has already rotated the token, it uses that token instead of refreshing again. A lock left by a crashed process is ignored after 75 seconds. orbitnest whoamishows the signed-in email, the API URL, and when the access token expires.orbitnest logoutrevokes the session on the server and clears the local session. The stored API URL is kept. From version 0.6.0, it refreshes an expired access token first so it can revoke the current refresh token, and prints a warning if the revoke fails. Older versions could send an already-rotated token, which revoked nothing.
Linking a project
Most commands act on one project. Link the current directory once:
orbitnest projects # list name, slug and id
orbitnest link my-app # match by id, slug or name (name match is case-insensitive)With no argument, link links your only project automatically, or prints the list to choose from if you have more than one. From version 0.6.0, a name that matches more than one project is refused, here and with --project, and the error lists the matching slugs. Use the slug or id instead.
link writes .orbitnest/config.json in the current directory. It contains the project id, slug, name and API URL, no secrets, so you can commit it. The MCP server reads the same file.
{
"projectId": "3f6c1a52-8d0e-4c1b-9a43-1e2f5b7c9d10",
"projectSlug": "my-app",
"name": "My App",
"apiUrl": "https://api.orbitnest.io"
}The shape is { projectId, projectSlug, name?, apiUrl? }. Versions before 0.6.0 wrote the slug as slug. The CLI and the MCP server still read that key, and from version 0.6.0 the CLI writes projectSlug.
To target a different project for a single command, pass --project (-p) with a project UUID, slug or name:
orbitnest db status --project my-other-appThe CLI reads .orbitnest/config.json from the current directory only. It does not search parent directories.
API URL resolution
The API base URL is taken from the first of these that is set:
ORBITNEST_API_URLapiUrlin.orbitnest/config.jsonapiUrlin~/.orbitnest/credentials.json(saved bylogin --url)https://api.orbitnest.io
From version 0.6.0, trailing slashes are removed from the URL, so https://api.example.com/ works.
Migrations
A migration is a plain .sql file in the migrations directory (default migrations/, change it with --dir/-d). The file name must start with a numeric id followed by _ or -, for example 001_create_posts.sql. Files are applied in numeric id order, and ids must be unique. .sql files without a numeric prefix are ignored.
An optional -- migrate:down line splits the file into a forward section and a rollback section. From version 0.6.0, the marker must be the whole line: -- migrate:down, -- down or --- DOWN ---. A comment that only starts with "down", such as -- Down-sampled metrics, no longer splits the file. The Node.js SDK and the MCP server use the same rule.
-- Migration 001: create posts table
CREATE TABLE posts (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
title text NOT NULL,
created_at timestamptz DEFAULT now()
);
-- migrate:down
DROP TABLE posts;orbitnest migration new "<name>" creates the next file (002_<name>.sql, and so on) with both sections stubbed out. It never overwrites an existing file.
| Command | What it does |
|---|---|
orbitnest db push | Applies every migration that has not been applied successfully, in order. Each file's forward section runs as one BEGIN; … COMMIT; batch. |
orbitnest db status | Lists every migration file as applied, pending, modified or (from version 0.6.0) failed. |
orbitnest db rollback [id] | Runs the -- migrate:down section of the latest applied migration, or of the given id, then removes it from the registry. Fails if the file has no down section. |
orbitnest db reset --yes | Drops every table in the public schema except internal tables (names starting with auth_, pg_ or _), then applies all migrations from scratch. From version 0.6.0, it does a dry run first. |
How tracking works:
- Applied migrations are recorded in a
migrationstable in your project database (migration_id,name,checksum,executed_at,status). The CLI creates it on first use. - The checksum is a SHA-256 of the whole file. If an applied file changes,
db statusmarks itmodifiedanddb pushstops with an error. Add a new migration instead of editing history. - If a migration fails, its transaction is rolled back, it is recorded with status
failed, andpushstops. The nextpushretries it. - The MCP server's migration tools use the same file format and the same
migrationstable.
db reset deletes data
db reset drops your tables, including the migrations registry, and everything in them. It refuses to run without --yes (or --force). Use it on development projects only.
From version 0.6.0, db reset first sends the whole reset as one script that ends in a rollback: BEGIN;, the drops, every migration's forward section, then ROLLBACK;. If any part fails, nothing is dropped and the command stops with "Reset aborted — nothing was dropped". The API accepts at most 50,000 characters of SQL per call. When the drops plus all migrations are longer than that, the dry run fails and the reset doesn't run.
See Migrations for writing migrations and running them from other tools.
Running SQL
orbitnest db sql "select id, title from posts order by created_at desc limit 5"
orbitnest db sql --file scripts/backfill.sqlThe result rows are printed as JSON, followed by a row count. SQL runs through the project's admin SQL endpoint (POST /api/projects/:projectId/database/sql), which validates each statement. For example, statements that drop, truncate, alter or DELETE FROM the internal auth_* tables return 403, as does a DO block that loops over the table catalog without excluding them.
Project owner only
The database commands (db push, db status, db rollback, db reset, db sql, db diff and gen types) call the project SQL endpoint, which only the project's creator may use. Other workspace members get 403 This operation is restricted to the project owner. From version 0.6.0, the CLI adds an explanation to that error.
Schema drift
db diff compares the live public schema (tables, columns, types, nullability and defaults) with a snapshot you commit to the repo.
# Record the current live schema as the baseline
orbitnest db diff --save # writes .orbitnest/schema.snapshot.json
# Later: report what changed since the snapshot
orbitnest db diffdb diff prints added, removed and changed tables and columns. It exits with code 1 when it finds drift, so you can fail a CI job on unexpected schema changes. Internal tables (auth_*, pg_*, _*) are skipped.
Type generation
orbitnest gen types # writes orbitnest.types.ts
orbitnest gen types --out src/db.ts # custom path (-o)
orbitnest gen types --stdout > types.ts # print instead of writinggen types reads information_schema.columns for the public schema, skipping internal tables, and emits one interface per table plus a Database map:
// Generated by @orbitneststudio/cli — do not edit by hand.
// Re-run `orbitnest gen types` after schema changes.
export interface Posts {
id: string;
title: string;
created_at: string | null;
}
export interface Database {
"posts": Posts;
}- Nullable columns are typed
T | null. From version 0.6.0 they are required properties, because selected rows always include every column. Older versions made them optional (column?: T | null). smallint,integer,realanddouble precisionmap tonumber. From version 0.6.0,bigint(int8),numericanddecimalmap tostring, because the API returns those values as strings.booleanmaps toboolean. Text,uuid, date/time andbyteatypes map tostring. From version 0.6.0, enums (USER-DEFINED) map tostringandjson/jsonbtounknown.- Arrays become
T[]. Any other type becomesunknown.
Keep types in sync
Run orbitnest gen types in a predev or prebuild script, or after every db push, and commit the output.
Direct database connection
orbitnest db connectPrints the project's direct Postgres connection string, then the host, port, database, user and sslmode, and a pooled connection string when the server has one configured. Direct connections are turned off unless the OrbitNest deployment enables them. When they are off, the command fails with "Direct database connections are not enabled for this deployment."
Webhooks
Manage database webhooks for the linked project:
orbitnest webhooks list
orbitnest webhooks create --url https://example.com/hooks/orbitnest \
--events INSERT,UPDATE --table posts --name post-changes
orbitnest webhooks test <webhook-id>
orbitnest webhooks delete <webhook-id>Flag (create) | Default | Description |
|---|---|---|
--url | required | Endpoint that receives the signed POST |
--events | INSERT,UPDATE,DELETE | Comma-separated row events |
--table | all tables | Only fire for this table |
--name | webhook | Display name |
create prints the webhook's signing secret once. Store it right away. test sends a test event and prints the HTTP status your endpoint returned.
SMS (Twilio)
Configure the project's Twilio credentials for SMS OTP sign-in:
orbitnest sms get
orbitnest sms set --sid AC0123456789abcdef --token "$TWILIO_AUTH_TOKEN" --from +15555550123 --enable
orbitnest sms test +15555550123sms set updates only the fields you pass: --sid, --token, --from, and --enable or --disable. The auth token is stored encrypted and is never returned. sms get only shows whether it is set.
Auth security
Read or change the limits for your app's users: code length, code expiry, wrong codes allowed, codes per email per hour, and password lockout.
orbitnest auth-security get
orbitnest auth-security set --code-length 6 --max-attempts 3 --lockout-attempts 5 --lockout-minutes 30set changes only the flags you pass: --code-length (6–8), --code-expiry (minutes, 1–60), --max-attempts (1–10), --codes-per-hour (1–100), --lockout-attempts (1–50) and --lockout-minutes (1–1440). It needs the workspace admin role.
Command reference
| Command | Description |
|---|---|
orbitnest login | Sign in (--email, --password, --code, --url) |
orbitnest logout | Revoke the server session and clear the local session |
orbitnest whoami | Show the current session, API URL and token expiry |
orbitnest projects | List your projects |
orbitnest link [id|slug|name] | Link the current directory to a project |
orbitnest migration new <name> | Scaffold the next migration file |
orbitnest db push | Apply pending migrations |
orbitnest db status | Show applied, pending and modified migrations |
orbitnest db rollback [id] | Roll back the latest (or given) migration |
orbitnest db reset --yes | Drop all tables and re-apply every migration |
orbitnest db sql "<SQL>" | Run SQL (--file <path> to read from a file) |
orbitnest db diff | Report schema drift against the snapshot (--save to update it) |
orbitnest db connect | Print the direct Postgres connection string |
orbitnest gen types | Generate TypeScript types (--out, --stdout) |
orbitnest webhooks list|create|delete|test | Manage database webhooks |
orbitnest sms get|set|test | Manage Twilio SMS settings |
orbitnest auth-security get|set | Read or change end-user auth limits |
Global options
| Option | Applies to | Description |
|---|---|---|
-p, --project <id|slug|name> | db, gen, webhooks, sms | Target a project instead of the linked one |
-d, --dir <path> | migration new, db push/status/rollback/reset | Migrations directory (default migrations) |
-o, --out <file> | gen types | Output file (default orbitnest.types.ts) |
--stdout | gen types | Print to stdout |
-f, --file <path> | db sql | Read SQL from a file |
-h, --help | all | Show help |
-v, --version | all | Show the version |
Environment variables
| Variable | Purpose |
|---|---|
ORBITNEST_API_URL | API base URL, overrides the linked and stored URL |
ORBITNEST_EMAIL, ORBITNEST_PASSWORD | Non-interactive login |
ORBITNEST_MFA_CODE | Two-factor code for non-interactive login |
NO_COLOR | Turn off colored output |
Files
| Path | Scope | Contents |
|---|---|---|
~/.orbitnest/credentials.json | Per user, mode 0600 | Access and refresh tokens, API URL, user. Shared with the MCP server. Never commit it. |
~/.orbitnest/credentials.lock | Per user | Short-lived lock held while a token refresh runs (from version 0.6.0). Shared with the MCP server. |
.orbitnest/config.json | Per directory | { projectId, projectSlug, name?, apiUrl? }. Safe to commit. |
.orbitnest/schema.snapshot.json | Per directory | Baseline for db diff. Commit it. |
migrations/*.sql | Per directory | Your migrations |