npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@batadata/cli

v0.2.10

Published

CLI for BataDB — serverless Postgres platform

Readme

@batadata/cli

Command-line interface for BataDB — a serverless Postgres platform. Create projects, open psql, run queries, manage branches and API keys, inspect cost, and generate types, all from your terminal.

Every command also runs headlessly with a single API key and --json output, so an AI coding agent can provision and operate a database with no human in the loop. See Headless / agent use.

Install

npm install -g @batadata/cli

This installs the bata command. Requires Node.js >= 20.

Authenticate

Either log in interactively:

bata login

…or, for CI and agents, set an API key — every command works with just BATA_API_KEY set, no login needed:

export BATA_API_KEY=bata_xxx   # mint one with: bata api-keys create

You can also pass --api-key <key> per command, and point at a different control plane with --api-url <url> or BATA_API_URL.

Quick start

bata create my-app        # create a project and wait until it's ready
bata status               # list all projects and their status
bata connect my-app       # open psql (auto-wakes the compute if suspended)
bata usage                # per-dimension cost for the current billing period

Project linking

Tired of threading --project <id> through every command? Link a directory to a project once — Vercel/Neon-style — and every command run inside it (or any subdirectory) targets that project automatically.

bata link my-app          # resolves by name or id, writes .batadata/project.json
bata link                 # no argument, in a TTY: pick from a list
bata link --status        # show what this directory resolves to
bata db query "SELECT 1"  # no --project needed anymore
bata unlink               # remove the link

bata link writes .batadata/project.json in the current directory:

{ "projectId": "proj_abc123", "branchId": null }

Add .batadata/ to your .gitignore — the link is per-checkout, not shared.

Pin a branch

bata db branch checkout preview   # writes the branch id into .batadata/project.json
bata db query "SELECT 1"          # now runs against `preview` — no --branch flag

Resolution precedence

Everywhere a project or branch is resolved, the same rule applies — an explicit flag always wins, so linking never silently overrides an intentional request:

  1. an explicit --project / --branch flag (or a positional id)
  2. .batadata/project.json, discovered by walking up from the current directory like git (stops at $HOME or the filesystem root)
  3. defaultProject in ~/.batarc (the per-machine fallback)

Commands

| Command | Description | |---------|-------------| | create <name> | Create a project and wait for it to be ready | | import --source <uri> | Migrate a Postgres/Neon database into BataDB (see Migrate from Neon) | | connect <name> | Open psql to a project (auto-wakes if suspended) | | status | Show all projects and their status | | usage | Show per-dimension cost (compute, storage, transfer) for the current period | | link [project] | Link the current directory to a project (see Project linking) | | unlink | Remove the current directory's project link | | login / logout / whoami | Manage your session | | api-keys | Create / list / revoke API keys | | projects | list, create, info, delete | | db url | Print a connection string | | db connect | Open psql to your database (interactive only) | | db query <sql> | Run a SQL query and print the rows | | db branches | List database branches | | db branch create / db branch delete | Manage branches | | db branch checkout <name-or-id> | Pin a branch into the directory's link | | db studio | Open the table browser in your browser | | restore points | List recovery points and the PITR window (see Point-in-time restore) | | restore create | Restore a branch to a timestamp/LSN as a new branch | | schema check <file> | Check a proposed schema change against live query traffic | | generate | Generate types from your database schema (--watch for watch mode) | | dev | Print the local development setup guide |

schema check is implemented today. The remaining schema subcommands (init, push, pull, diff) and all of migrate are not implemented yet — they exit 3 (NOT_IMPLEMENTED) and point you at schema check for migration safety.

Run bata --help for the full, authoritative command list, or bata --version.

Migrate from Neon

bata import moves an existing Postgres database — Neon or anything else — into a fresh BataDB project in one command. It shells out to the standard pg_dump / psql client tools (nothing proprietary), streams the dump straight through, and verifies the result.

bata import --source "postgresql://…@ep-x.neon.tech/neondb"        # → a new project named `neondb`
bata import --source "$NEON_URL" --name my-app                     # name the new project
bata import --source "$NEON_URL" --project proj_abc123 --yes       # into an existing project

Prerequisite: local pg_dump and psql whose major version is ≥ the source server's (pg_dump 16 cannot dump a PostgreSQL 17 server). Neon defaults to PostgreSQL 17, so install matching client tools:

brew install libpq                          # macOS  (or: brew install postgresql@17)
sudo apt install postgresql-client-17       # Ubuntu

What it does, in order: inspects the source, checks your client tools, creates (or resolves) the target project, waits for its compute, preflights extensions (any source extension the target can't provide hard-fails before the restore starts, rather than dying mid-restore at CREATE EXTENSION and half-importing), streams pg_dump … --encoding=UTF8 | psql (the --encoding=UTF8 guarantees a valid-UTF-8 stream so non-UTF-8 source databases aren't corrupted in transit), then verifies every table's row count and every sequence's value on both sides. It exits non-zero on any mismatch. Importing into an existing --project that already holds user objects requires --yes. --json emits a machine-readable result for agents.

PostgreSQL 16 vs 17 (honest caveat). BataDB runs PostgreSQL 16 today; Neon defaults to 17. Standard schemas migrate cleanly — bata import transparently strips the one PG17-only line pg_dump emits (SET transaction_timeout = 0;) that PG16 would reject. But genuinely PG17-only schema features (a data type, syntax, or option that only exists in 17) will fail loudly during restore — the command surfaces the exact psql errors and exits non-zero rather than pretending the migration succeeded. See docs/migrate-from-neon.md for the full guide and the manual pg_dump | psql fallback.

Point-in-time restore (PITR)

Recover a branch to an earlier point in time. Restore is non-destructive: it creates a new branch at the chosen point and never overwrites the source branch's data.

bata restore points                         # what can I restore to?
bata restore create \
  --branch main \
  --at 2026-07-04T12:00:00Z \
  --name before-the-bad-migration          # → a new branch at that timestamp

--at accepts either an ISO-8601 timestamp (e.g. 2026-07-04T12:00:00Z) or a Postgres LSN (e.g. 0/15994B0); the CLI detects which you passed. If --name is omitted the new branch is named restore-<branch>-<timestamp>. The new branch's compute may still be provisioning when the command returns — poll bata db branches before you query it.

How far back can I restore? (honest window)

Recovery points are timeline-metadata snapshots the control plane's backup scheduler records about every 6 hours (BACKUP_INTERVAL_HOURS, default 6). They are not full physical backups, and the earliest point restore points lists is simply the oldest metadata row we have — not a guaranteed floor on how far back you can restore. Actual restorability to an arbitrary timestamp depends on how much WAL the storage engine still retains: if the WAL no longer covers your timestamp, the server returns "No data available at the requested timestamp" and the restore is refused. We surface that verbatim rather than implying the window is deeper than it is.

Headless / agent use

Every command runs headlessly with just BATA_API_KEY set — no bata login, no interactive prompts, no human in the loop. This is what makes BataDB agent-native: an AI coding agent can provision a database, run SQL, branch, and clean up entirely on its own.

  • --json — machine-readable output. The error envelope is JSON too and always the same shape: { "error", "code", "hint" }.

  • Exit codes — a stable contract so a script can branch on the failure mode:

    | Code | Meaning | |------|---------| | 0 | Success | | 1 | Generic error (CLI_ERROR) | | 2 | Gate tripped (schema check --fail-on) | | 3 | Not implemented (NOT_IMPLEMENTED) | | 4 | Auth / credentials (NO_CREDENTIALS, INVALID_KEY) | | 5 | Not found / bad input (NO_PROJECT, BRANCH_NOT_FOUND, INVALID_FLAG, INTERACTIVE_ONLY) | | 6 | Upstream / transient (API_UNAVAILABLE, TIMEOUT) — safe to retry |

  • --yes / -y — skip confirmation prompts on destructive commands.

db connect and connect open an interactive psql session and exit 5 (INTERACTIVE_ONLY) when run headlessly. Agents should use db url for a connection string or db query <sql> to execute SQL.

A full agent workflow

Provision, query, branch, check cost, and tear down — no human, no login:

export BATA_API_KEY=bata_xxx

# 1. Create a project and wait until it's ready
bata create my-agent-app --json

# 2. Run SQL headlessly (rows come back as JSON objects)
bata db query "SELECT now()" --json

# 3. Branch the database (copy-on-write)
bata db branch create preview --json

# 4. Inspect cost for the current period
bata usage --json

# 5. Clean up
bata projects delete --yes --json

db branch create returns immediately with "ready": false — the branch row exists but its compute may still be provisioning. Poll bata db branches --json until the branch reports a ready status before connecting to it.

To avoid passing --project on every call, an agent can bata link <id> --json once (it emits { "linked": true, "project_id", "project_name", "branch_id", "link_file" }) and drop the flag from every subsequent command in that directory. bata link --status --json reports the current link.

Cost truth

bata usage reports cost per dimension and is deliberately honest about what is and isn't metered. Transfer (egress) is not metered yet, so it never shows a priced $0 — in --json it reports { "metered": false, "value": null, "cost_cents": null, "status": "not_metered_yet" }, and in the human view it reads Not metered yet. You only ever see a dollar figure for a dimension we genuinely meter end to end (compute and storage today).

bata usage --json | jq '.projects[].transfer.status'   # "not_metered_yet"
bata status --json | jq '.projects[].name'             # list project names

Global options

| Flag | Description | |------|-------------| | --json | Machine-readable JSON output (read commands) | | --api-key <key> | API key (else BATA_API_KEY, else saved login) | | --api-url <url> | API base URL (else BATA_API_URL, else config/default) | | --yes, -y | Skip confirmation prompts | | --help, -h | Show help | | --version, -v | Show version |

License

MIT