Introducing the PocketBase Cloud CLI: run PocketBase locally, deploy, and manage production
PocketBase is one binary, and that's a big part of why people like it. The workflow around it usually isn't: you build locally in the dashboard, copy your collections across by hand, upload hooks somewhere, and then click through a second dashboard to change anything in production.
The PocketBase Cloud CLI, pbc, keeps that whole loop in one terminal. This post follows a small shop backend from an empty folder to production: run PocketBase on your laptop, model the data, test a hook, deploy the same folder, and manage it live.
The 80-second version
Install. On macOS and Linux:
curl -fsSL https://raw.githubusercontent.com/pocketbasecloud/cli/main/scripts/install.sh | sh
==> Installing pbc 0.9.9
==> Detected platform: macOS (Apple Silicon)
==> Resolved version: 0.9.9
==> Downloading pbc
==> Installing standalone package to /usr/local/bin/pbc
==> /usr/local/bin is already on PATH
pbc 0.9.9 installed successfully.
On Windows, unzip the win32 build from the latest release onto your PATH. Either way, pbc self upgrade keeps it current.
1. Run PocketBase locally
mkdir acme-shop && cd acme-shop && pbc local init
Downloaded pocketbase 0.41.1 (darwin/arm64) → /Users/ada/acme-shop/pocketbase
created /Users/ada/acme-shop/pb_hooks/main.pb.js
created /Users/ada/acme-shop/README.md
created /Users/ada/acme-shop/pb_migrations
created /Users/ada/acme-shop/.gitignore
updated /Users/ada/acme-shop/pbc.json (pocketbaseVersion: 0.41.1)
Start PocketBase with: ./pocketbase serve
That's a real PocketBase binary for your platform, plus the folder layout the cloud expects: pb_hooks, pb_migrations and a pbc.json that remembers the PocketBase version.
Add a superuser and start it:
./pocketbase superuser upsert a**@example.com 'kiwi-Pebble-42'
./pocketbase serve
Server started at http://127.0.0.1:8090
> Dashboard: http://127.0.0.1:8090/_/
> REST API: http://127.0.0.1:8090/api/
2. Model the data
pbc admin talks to any PocketBase over its API. Log in to the local one and save it as a profile called local:
pbc admin login --url http://127.0.0.1:8090 --name local
Then describe the collection in JSON. orders.json:
{
"name": "orders",
"type": "base",
"fields": [
{ "name": "customer", "type": "text", "required": true },
{ "name": "qty", "type": "number" },
{ "name": "price", "type": "number" },
{ "name": "total", "type": "number" },
{ "name": "status", "type": "text" }
]
}
pbc admin collections create "$(cat orders.json)"
Created collection orders (pbc_2456927940).
The collection shows up in the dashboard, and because PocketBase is running locally with serve, it writes the migration for you: pb_migrations/1794446332_created_orders.js. That file is what carries the schema to production later.
3. Add a hook and test it
A hook that fills in each order's total, in pb_hooks/orders.pb.js:
/// <reference path="../pb_data/types.d.ts" />
onRecordCreateRequest((e) => {
const qty = e.record.getInt("qty")
const price = e.record.getFloat("price")
e.record.set("total", qty * price)
e.next()
}, "orders")
Create a test order from the terminal:
pbc admin records create orders '{"customer":"Mara Quinn","qty":2,"price":64}'
Created record k2v9x81m0qz4tdp.
Open the record in the dashboard: total is 128. The hook works, on your laptop, before anything is deployed.
4. Deploy
pbc login
pbc deploy
Detected a PocketBase instance (pb_hooks/) - running `pbc pocketbase deploy`.
✓ Connecting to PocketBase Cloud Environment: production - new PocketBase acme-shop
✓ Packaged 3 file(s), 2.4 KB.
✓ Uploaded data.zip 4s
✓ acme-shop is running 12s
https://acme-shop.pocketbasecloud.com
https://acme-shop.pocketbasecloud.com/_/ (admin)
✓ Reachable.
pbc deploy looks at the folder and works out what it is. Here it sees pb_hooks/ and runs the PocketBase deploy: hooks, migrations and public files go up, the migration creates the orders collection on the cloud instance, and it's live with its own URL. The same command deploys a frontend or a backend when the folder holds one.
The deploy is recorded in pbc.json, so the next one needs no flags.
5. Manage production from the terminal
The admin commands you used locally work on production too. Log in to the cloud instance as a second profile:
pbc admin login --url https://acme-shop.pocketbasecloud.com --name cloud
pbc admin records ls orders --fields customer,total,status
ID CUSTOMER TOTAL STATUS
r8m2kq7v1xw4tzn Theo Lindqvist 42.5 paid
c5y9pd3h0ja6lbe Ines Okafor 310 shipped
w1n4fs8u2go7rkq June Albers 76.4 paid
Page 1/1 - 30 per page, 3 total.
Lock down who can list orders:
pbc admin rules set orders --list-rule "@request.auth.id != ''"
Updated rules on orders.
pbc admin profiles lists the local and cloud logins side by side. Switch with pbc admin use local, or pass --profile cloud to a single command, without logging in again. And pbc admin isn't tied to PocketBase Cloud: point it at a PocketBase on your own server and the same commands work there.
6. Deploy on every push
pbc ci init
Wrote /Users/ada/acme-shop/.github/workflows/deploy.yml - deploys this PocketBase instance on every push to main.
The workflow it writes:
name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pocketbasecloud/cli/action@v0.9.9
with:
token: ${{ secrets.PBC_TOKEN }}
kind: pb
Copy the CLI access token from the Deploy From CI card on your Account page in the portal and add it as a PBC_TOKEN repository secret. Commit the workflow, push, and from then on every push to main deploys.
The whole loop
| Step | Command |
|---|---|
| Run PocketBase locally | pbc local init |
| Model the data | pbc admin collections create |
| Test with real records | pbc admin records create |
| Ship it | pbc deploy |
| Manage production | pbc admin login --name cloud, pbc admin rules set |
| Deploy on every push | pbc ci init |
One folder from start to finish: the thing you test on your laptop is the thing that goes live.
Install and the full command reference: Installing the CLI. The source is on GitHub.
Where do you test PocketBase changes before production today: a local instance, a staging copy, or straight to live? I'm curious what people's setup looks like.
Comments
No comments yet. Start the discussion.