Home › PocketBase › PocketBase backend AGENTS.md
PocketBase backend AGENTS.md
AGENTS.md for PocketBase apps: migrations for schema, collection API rules, JS hooks or Go extensions, safe filters in the JS SDK, realtime subscriptions, and auth.
AGENTS.mdPocketBase
How to use
Save this as AGENTS.md in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
Note: Review and test before use. Provided as is, without warranty. See Terms.
AGENTS.mdDownload # AGENTS.md: PocketBase
## Commands
- Run: `./pocketbase serve` (admin dashboard at `/_/`), or `go run . serve` when extended with Go.
- Schema changes are migrations in `pb_migrations/` (JS) or `migrations/` (Go). Create with `./pocketbase migrate create <name>` or let automigrate generate them from dashboard changes in dev, then commit them. Never change production schema only in the dashboard.
- Check the PocketBase version before using hook/migration APIs; they changed between major versions.
## Access rules
- Every collection has explicit API rules (list, view, create, update, delete). Empty rule = public; `null` (locked) = superusers only. Default to locked and open deliberately.
- Write ownership rules with request context: `@request.auth.id != "" && owner = @request.auth.id`. Protect fields users must not set with `@request.body.<field>:isset = false` (or the version's equivalent).
- Use `hidden` fields for data never returned by the API.
## Server logic
- JS hooks live in `pb_hooks/*.pb.js` (e.g. `onRecordCreateRequest`, `routerAdd`); each handler calls `e.next()` to continue the chain. Go extensions register hooks on `app.OnRecordCreate(...)` etc.
- Validate in hooks and return proper errors (`BadRequestError`, `ForbiddenError`); don't rely on the client.
- Custom routes require auth middleware unless deliberately public.
## Client (JS SDK)
- One `PocketBase` client instance; auth state in `pb.authStore`. Refresh with `authRefresh()` on app start.
- Build filters with parameters: `pb.filter('title ~ {:q} && status = {:s}', { q, s })`. Never concatenate user input into filter strings.
- Request only needed data with `fields` and `expand`; paginate with `getList(page, perPage)` instead of `getFullList` on large collections.
- Realtime: `pb.collection('x').subscribe('*', cb)` and always `unsubscribe()` on unmount.
- Files via the record's file fields and `pb.files.getURL(record, filename, { thumb })`.
## Done when
Migrations committed and applied cleanly on a fresh `pb_data`, API rules tested as anonymous, owner and other user.