Reference

CLI reference

berth is one Python 3 file with no dependencies. Every command is a thin wrapper over the HTTP API. The examples below run in order against a fresh app named $APP.

Install and global options

curl -fsSL https://atberth.com/install.sh | sh
Option or variableWhat it does
--jsonprint the raw JSON response, for scripts and jq
--api URLAPI base URL, default https://api.atberth.com/v1
BERTH_CONFIGconfig file path, default ~/.config/berth/config.json (mode 600)
BERTH_APIsame as --api
BERTH_TOKENuse this key instead of the saved one
BERTH_APPdefault for --app

Failures print the error message and exit nonzero, so set -e scripts stop on the first problem.

Signing in and account

berth status

API version and health. No login needed.

berth status

berth signup, berth login

Emails you a code and saves an account key. Pass --email and --code to skip the prompts. berth login --token saves an existing key, for CI.

berth signup --email you@example.com
berth login --email you@example.com --code 123456
berth login --token "$BERTH_ACCOUNT_KEY"

berth whoami

berth whoami

berth account show

Email, limits, and usage.

berth account show

berth account keys

berth account keys list
KEY_ID=$(berth account keys create ci --json | jq -er .key.id)
berth account keys revoke "$KEY_ID"

berth account delete

Deletes the account and every app in it. You must type the account email.

berth account delete --confirm you@example.com

berth logout

Forgets the saved account key on this machine. It does not revoke it. --all also forgets saved app keys.

berth logout
berth login --token "$BERTH_ACCOUNT_KEY"

Apps

berth apps create

Creates the app, its database and role, and prints a secret and a publishable key once.

berth apps create "$APP"

berth apps list, show, usage

berth apps list
berth apps show "$APP"
berth apps usage "$APP"

berth use

Sets the default app, so --app can be left out. These docs keep --app so each line stands alone.

berth use "$APP"

berth apps config

Sets allowed browser origins. Repeat --cors for more than one.

berth apps config "$APP" --cors https://notes.example.com --cors http://localhost:5173

berth apps export, restore

Export writes a pg_dump file. Restore creates a new app from one.

berth apps export "$APP" -o backup.dump
berth apps restore "${APP}_copy" backup.dump

berth apps delete

berth apps delete "${APP}_copy" --yes

App keys

berth keys list --app "$APP"
PUBLISHABLE_KEY=$(berth keys create --app "$APP" --type publishable --name web --json | jq -er .secret)
KEY_ID=$(berth keys create --app "$APP" --type secret --name old-worker --json | jq -er .key.id)
berth keys revoke --app "$APP" "$KEY_ID"

Tables

Columns are name:type with optional :notnull and :unique. Types: text, integer, bigint, numeric, double, boolean, date, timestamptz, uuid, jsonb, text[], integer[]. Quote array types in zsh.

berth tables create

berth tables create --app "$APP" notes title:text:notnull slug:text:unique done:boolean 'tags:text[]' --updated-at
berth tables create --app "$APP" events name:text meta:jsonb --no-timestamps --read authenticated --write authenticated

berth tables list, show

berth tables list --app "$APP"
berth tables show --app "$APP" notes

berth tables rename, policy, drop

berth tables rename --app "$APP" events activity
berth tables policy --app "$APP" activity --read owner --write owner
berth tables drop --app "$APP" activity --yes

Columns

berth columns add --app "$APP" notes priority:integer --default 0 --not-null
berth tables create --app "$APP" profiles display_name:text
berth columns add --app "$APP" notes profile_id:uuid --references profiles.id --on-delete set-null
berth columns rename --app "$APP" notes priority rank
berth columns alter --app "$APP" notes rank --type bigint --drop-default --nullable
berth columns drop --app "$APP" notes rank --yes

Indexes

berth indexes create --app "$APP" notes done created_at --name notes_done_created
berth indexes list --app "$APP" notes
berth indexes drop --app "$APP" notes notes_done_created

Rows

berth rows add

Values are name=value, converted to each column's type. null means SQL null. Use --data for JSON, or --file to read it from a file.

ROW_ID=$(berth rows add --app "$APP" notes title="Buy milk" slug=milk done=false --json | jq -er .row.id)
berth rows add --app "$APP" notes --data '{"title":"Fix the sink","slug":"sink","tags":["home"]}'
berth rows add --app "$APP" notes --data '[{"title":"Read","slug":"read"},{"title":"Run","slug":"run"}]'

berth rows list

berth rows list --app "$APP" notes --where done.eq=false --select id,title --order created_at.desc --limit 2 --count
berth rows list --app "$APP" notes --limit 1 --offset 1
berth rows list --app "$APP" notes --limit 2 --all

--cursor takes the next_cursor from a previous --json page.

berth rows get, update, upsert

berth rows get --app "$APP" notes "$ROW_ID"
berth rows update --app "$APP" notes "$ROW_ID" done=true
berth rows update --app "$APP" notes --where slug.eq=sink done=true
berth rows upsert --app "$APP" notes --on-conflict slug slug=milk title="Buy oat milk"

berth rows rm, delete

berth rows rm --app "$APP" notes "$ROW_ID"
berth rows delete --app "$APP" notes --where done.eq=true --yes

berth import

CSV with a header row, or NDJSON. All or nothing.

printf 'title,slug\nPlan trip,trip\nPay rent,rent\n' > notes.csv
berth import --app "$APP" notes notes.csv
printf '%s\n' '{"title":"Book flights","slug":"flights"}' > notes.ndjson
berth import --app "$APP" notes notes.ndjson

berth watch

Prints row events as they happen, until Ctrl+C.

berth watch --app "$APP" notes --events insert,update,delete

End-user auth

berth auth signup --app "$APP" --email ada@example.com --password 'correct horse battery'
berth auth login --app "$APP" --email ada@example.com --password 'correct horse battery' --key "$PUBLISHABLE_KEY"
berth auth users list --app "$APP"
USER_ID=$(berth auth users create --app "$APP" grace@example.com --password 'another long password' --json | jq -er .user.id)
berth auth users show --app "$APP" "$USER_ID"
berth auth users ban --app "$APP" "$USER_ID"
berth auth users ban --app "$APP" "$USER_ID" --unban
berth auth users delete --app "$APP" "$USER_ID" --yes

Storage

berth storage buckets create --app "$APP" files --read authenticated --write owner --max-file-size 5000000
berth storage buckets list --app "$APP"
echo "hello" > hello.txt
berth storage upload --app "$APP" files hello.txt
berth storage upload --app "$APP" files hello.txt docs/hello.txt --content-type text/plain
berth storage ls --app "$APP" files --prefix docs/
berth storage download --app "$APP" files docs/hello.txt -o hello-copy.txt
berth storage sign --app "$APP" files docs/hello.txt --expires 3600
berth storage rm --app "$APP" files docs/hello.txt
berth storage buckets delete --app "$APP" files --force

Functions

cat > hello.ts <<'EOF'
export default (req: Request) => Response.json({ hello: "world", method: req.method });
EOF
berth functions deploy --app "$APP" hello hello.ts --verify key --timeout-ms 5000 --memory-mb 128
berth functions list --app "$APP"
berth functions show --app "$APP" hello
berth functions invoke --app "$APP" hello --data '{"name":"Ada"}' --method POST
berth functions logs --app "$APP" hello
berth functions delete --app "$APP" hello

--schedule CRON also runs the function on a cron schedule in UTC (five fields, or @hourly, @daily, @weekly, @monthly). A redeploy without the flag keeps the schedule; --no-schedule removes it. See Schedules.

berth functions deploy --app "$APP" hello hello.ts --schedule "*/15 * * * *"
berth functions deploy --app "$APP" hello hello.ts --no-schedule
berth functions delete --app "$APP" hello

Env vars

berth env set --app "$APP" GREETING=Hello STRIPE_MODE=test
berth env list --app "$APP"
berth env unset --app "$APP" STRIPE_MODE

Webhooks

WEBHOOK_ID=$(berth webhooks add --app "$APP" https://example.com/berth-webhook --table notes --events insert,update --json | jq -er .webhook.id)
berth webhooks list --app "$APP"
berth webhooks show --app "$APP" "$WEBHOOK_ID"
berth webhooks update --app "$APP" "$WEBHOOK_ID" --events insert,update,delete --disable
berth webhooks update --app "$APP" "$WEBHOOK_ID" --url https://example.com/berth-webhook-2 --enable
berth webhooks test --app "$APP" "$WEBHOOK_ID"
berth webhooks deliveries --app "$APP" "$WEBHOOK_ID"
berth webhooks remove --app "$APP" "$WEBHOOK_ID"

SQL, rpc, and logs

berth rpc calls a Postgres function by name. Arguments are name=value (parsed as JSON when they can be), or --data with a JSON object.

berth sql --app "$APP" 'select title from notes where slug = $1' --param trip
berth sql --app "$APP" 'create function add_nums(a integer, b integer) returns integer language sql as $$ select a + b $$'
berth rpc --app "$APP" add_nums a=2 b=3
berth rpc --app "$APP" add_nums --data '{"a": 40, "b": 2}'
berth sql --app "$APP" --read-only --timeout-ms 2000 'select count(*) from notes'
echo 'select slug, title from notes order by slug' > report.sql
berth sql --app "$APP" -f report.sql
berth logs --app "$APP" --limit 5

Shell completion

berth completion bash > berth.bash
berth completion zsh > _berth

Source berth.bash from ~/.bashrc, or put _berth in a folder on your zsh fpath.

Delete the app

berth apps delete "$APP" --yes