The jsonpad command lets you manage lists, indexes, items and identities from a terminal, and sync schema documents with your account. Use it to look around your account, script changes, back up a list, or apply your schema in a deploy.
The command line tool is the @basementuniverse/jsonpad-cli npm package, and it needs Node.js 22.12 or later. Install it globally, run it with npx without installing anything, or add it to a project:
# Install the jsonpad command globally
npm install -g @basementuniverse/jsonpad-cli
# Or run it without installing
npx @basementuniverse/jsonpad-cli --help
# Or add it to a project, and run it with npx jsonpad
npm install --save-dev @basementuniverse/jsonpad-cliEvery command needs an API token, which you can create in the dashboard. The token's permissions decide what the commands can do.
In CI and scripts, set the JSONPAD_TOKEN environment variable. There's no option for the token, because an option would end up in your shell history and CI logs. On your own machine, save tokens as profiles instead. The token is asked for without being shown (or read from stdin), and saved in a config file that only you can read.
# In CI and scripts, set JSONPAD_TOKEN
export JSONPAD_TOKEN=<YOUR TOKEN>
# On your own machine, save tokens as profiles (the token is asked for)
jsonpad config set-profile personal
jsonpad config set-profile work
jsonpad config use work
# Check which token you're using, what it can do, and how much quota is left
jsonpad whoami
jsonpad whoami --profile personalA profile chosen with --profile or JSONPAD_PROFILE comes first, then JSONPAD_TOKEN, then the default profile (the first one you add, or the one you use). jsonpad whoami shows which token that is, what it's allowed to do, your plan's limits, and how much of this month's quota is left.
Commands that output records print a table in a terminal, and JSON when their output is piped or redirected. Choose a format with --output (-o):
table: columns, for readingjson: JSON (also --json)ndjson: one JSON record per lineid: one id per line, e.g. for xargs (also --quiet or -q)# A table in a terminal
jsonpad lists
# JSON when the output is piped or redirected
jsonpad lists get recipes | jq .realtime
# Or choose a format
jsonpad items recipes -o ndjson
jsonpad items recipes --all -q > item-ids.txtData goes to stdout, and messages, warnings and questions go to stderr, so they never end up in a file you redirect to. Commands that list things fetch one page, with --page, --limit (up to 100), --order and --direction, or every page with --all, which outputs NDJSON unless you choose a format. --max stops --all early.
Commands that delete something ask first. Where they can't ask, e.g. in a script, they refuse with exit code 5 unless you pass --yes.
Commands are grouped by resource: jsonpad lists, jsonpad indexes, jsonpad items and jsonpad identities. Each group's list command is its default, so jsonpad lists is the same as jsonpad lists list, and ls and rm work in place of list and delete.
Lists and indexes can be named by id or path name, and items by id or alias. Options that take JSON (--data, --schema and --patch) accept JSON, @file to read a file, or - to read stdin.
jsonpad lists
jsonpad lists create --name Recipes --path-name recipes --indexable
jsonpad lists get recipes
jsonpad lists update recipes --pinned --tags cookbook,public
jsonpad lists delete recipesDeleting a list deletes its items and indexes in the background.
A new index is built in the background, and can't be used to filter, order or search items until it's finished. --wait waits for the build, and fails with exit code 3 if the build does.
jsonpad indexes recipes
# Create an index, and wait for it to be built
jsonpad indexes create recipes --path-name title --pointer /title --alias --filtering --wait
# Or wait for a build later
jsonpad indexes wait recipes titlejsonpad items data works with an item's data, or part of it by JSON pointer. set merges into the data, replace replaces it, and patch applies a JSON patch.
jsonpad items create recipes --data '{"title": "pancakes", "servings": 4}'
jsonpad items create recipes --data @waffles.json
# Filter by an index, and fetch an item by its alias
jsonpad items recipes --where title=pancakes --order title
jsonpad items get recipes pancakes
# An item's data, or part of it by JSON pointer
jsonpad items data get recipes pancakes /servings
jsonpad items data set recipes pancakes --data '{"servings": 6}'
jsonpad items data replace recipes pancakes /ingredients --data '["flour", "eggs"]'
jsonpad items data patch recipes pancakes --patch @changes.json
jsonpad items data delete recipes pancakes /ingredients/0Identities can be named by id, or by group/name. Passwords are never taken as an option.
# Passwords are asked for, or read from stdin or JSONPAD_IDENTITY_PASSWORD
jsonpad identities create --group staff --name ada
jsonpad identities get staff/ada
jsonpad identities update staff/ada --display-name Ada --password
jsonpad identities delete staff/adaLists, items, indexes and identities all have stats, events and event commands, which read the event log. Items can also be restored to how they were after an event.
jsonpad lists search recipes pancake --include-items
# Counts by day: items, indexes and events
jsonpad lists stats recipes --days 30
# An item's history, and one event with a snapshot of the item
jsonpad items events recipes pancakes --type item-updated --start-at 2026-09-01
jsonpad items event recipes pancakes e1f6f98d-a66b-45b2-9bd5-a1a00ab900c2 --include-snapshot
# Put an item back how it was after an event (or re-create a deleted item)
jsonpad items events recipes pancakes --restorable
jsonpad items restore recipes pancakes e1f6f98d-a66b-45b2-9bd5-a1a00ab900c2jsonpad items export outputs every item in a list as NDJSON (one item per line), and jsonpad items import creates items from NDJSON or a JSON array, e.g. to back up a list, copy it to another account, or load data you've prepared.
# Every item in a list as NDJSON, oldest first
jsonpad items export recipes --out recipes.ndjson
# Create the items again, e.g. in another list or account
jsonpad items import recipes-copy recipes.ndjson --dry-run
jsonpad items import recipes-copy recipes.ndjson
# Just the data, from one list into another
jsonpad items export recipes --data-only | jsonpad items import archive - --data-onlydata, description, tags and readonly. Ids and dates aren't imported, so the items get new ones. With --data-only, each record is an item's data.--dry-run only checks.--continue-on-error, it carries on and lists the failures at the end.To see what one of your app's users sees, log in as their identity. login -o env outputs the lines that set JSONPAD_IDENTITY_TOKEN (and JSONPAD_IDENTITY_GROUP). While they're set, commands that work with items send the identity along with your API token, so they create, see and change items as that identity would.
jsonpad identities register --group players --name zed
eval "$(jsonpad identities login --group players --name zed -o env)"
# Commands that work with items now act as players/zed
jsonpad items create scores --data '{"score": 42}'
jsonpad whoami
jsonpad identities self update --display-name Zed
jsonpad identities logoutjsonpad listen prints realtime events as they happen, until you press Ctrl+C. Only lists with realtime turned on send events.
# Print events from a list, until Ctrl+C
jsonpad listen recipes
# Only some event types, as NDJSON
jsonpad listen recipes --events item-created,item-deleted -o ndjson
# Wait for the next change to one item
jsonpad listen recipes --items pancakes --count 1A listening terminal holds one of your plan's realtime connections. If the connection is refused because they're all in use, listen says so and keeps retrying.
The schema commands apply a schema document to your account, export one for lists you already have, and move lists between scopes. See schema sync for how documents, scopes and pruning work.
# See what a sync would change, then apply it
jsonpad sync-schema --dry-run
jsonpad sync-schema --wait
# Write a schema document for lists you already have
jsonpad export-schema --tagged recipe-app --out jsonpad-schema.json
# Move lists to another scope
jsonpad move-lists recipes ratings --to cookbook-app
# Rebuild an index whose last build failed
jsonpad rebuild-index recipes title --waitThey're also available as jsonpad schema sync, jsonpad schema export and jsonpad schema move, and rebuild-index as jsonpad indexes rebuild.
Store your token as a secret, and pass it in JSONPAD_TOKEN. When the output isn't a terminal, commands output JSON, deletes need --yes, and the exit code says what went wrong. For example, to check the schema in pull requests and sync it when they're merged, with GitHub Actions:
name: Sync JSONPad schema
on:
pull_request:
push:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
env:
JSONPAD_TOKEN: ${{ secrets.JSONPAD_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Check the schema
if: github.event_name == 'pull_request'
run: npx @basementuniverse/jsonpad-cli sync-schema --dry-run
- name: Sync the schema
if: github.event_name == 'push'
run: npx @basementuniverse/jsonpad-cli sync-schema --waitA rate limited request is retried after the delay the API asks for, up to 5 times. A request refused because the monthly quota has run out isn't retried. --verbose (-V) logs each request to stderr, and the rate limit and quota left afterwards.
jsonpad completion outputs a script that completes commands, options and their choices when you press Tab. Names from your account, like lists and items, aren't completed, because that would make a request every time.
# Add to ~/.bashrc
eval "$(jsonpad completion bash)"0: success1: an error, including a sync that was refused because a change has errors2: a sync was refused because it needs --allow-rebuild3: an index build failed, or didn't finish in time, while waiting4: a sync was refused because it needs --allow-destructive5: the command needs confirmation, so run it again with --yes6: not found7: the token isn't allowed to do this, or isn't valid8: rate limited (after retrying), or a plan limit or the monthly quota was reachedA dry run exits the same way the real sync would, so it can fail a pull request check. The schema commands and rebuild-index exit with 1 for every API error, rather than 6, 7 or 8.
Every command, with the global options and environment variables. Run jsonpad <command> --help to see a command's options, or read the full reference.
# Create and update lists and indexes to match a schema document
jsonpad sync-schema [options] [file]
# Write a schema document for existing lists
jsonpad export-schema [options]
# Move lists (by id or path name) to a scope, or release them from their scope
jsonpad move-lists [options] [list...]
# Rebuild an index whose last build failed, once the problem has been fixed
jsonpad rebuild-index [options] <list> <index>
# The same as jsonpad sync-schema, with the same arguments and options
jsonpad schema sync [options] [file]
# The same as jsonpad export-schema, with the same arguments and options
jsonpad schema export [options]
# The same as jsonpad move-lists, with the same arguments and options
jsonpad schema move [options] [list...]The schema commands used to be part of the JavaScript SDK, whose jsonpad command is deprecated and removed in version 2.0.0. The command line tool has the same commands, options, output and exit codes, so to switch, use @basementuniverse/jsonpad-cli in place of @basementuniverse/jsonpad-sdk.
# Before
npx @basementuniverse/jsonpad-sdk sync-schema --dry-run
# After
npx @basementuniverse/jsonpad-cli sync-schema --dry-run
# If you installed the SDK globally to get the command
npm uninstall -g @basementuniverse/jsonpad-sdk
npm install -g @basementuniverse/jsonpad-cliIf you installed the SDK globally to get the command, uninstall it first. Both packages provide a jsonpad command, so npm refuses to install the command line tool while the SDK is installed globally.