AgentSkillsCN

pocketbase-schema

PocketBase架构技能——生成迁移样板,检查实时架构,并验证迁移操作。

SKILL.md
--- frontmatter
name: pocketbase-schema
description: PocketBase schema skill — generate migration boilerplate, inspect live schema, and validate migrations.

Skill: PocketBase Schema

Tooling for authoring, inspecting, and validating PocketBase schema migrations. Use this skill during schema and feature work. For server lifecycle operations (init, dev, stop, reset), see the pocketbase skill.

Invocation: Use these operations whenever you need to create or modify PocketBase collections.

Prerequisites

  • PocketBase project already initialized (via pocketbase skill's PB Init)
  • Go 1.23+ installed and on PATH
  • For Inspect: PocketBase server must be running (via pb-dev.sh or pb-reset.sh)

Operations

OperationScriptDescription
Migrate Createbash .github/skills/pocketbase-schema/pb-migrate-create.sh <description> [type]Generate a timestamped migration file with boilerplate
Schema Inspectbash .github/skills/pocketbase-schema/pb-schema-inspect.sh [collection-name]Dump live schema as JSON (all collections or one)
Schema Validatebash .github/skills/pocketbase-schema/pb-schema-validate.shWipe data and dry-run all migrations to check for errors

Migrate Create

Generates a new migration file in pb/pb_migrations/ with the correct timestamp and boilerplate.

bash
# Create a new collection
bash .github/skills/pocketbase-schema/pb-migrate-create.sh create_posts create

# Modify an existing collection
bash .github/skills/pocketbase-schema/pb-migrate-create.sh add_featured_to_posts modify

# Seed data into a collection
bash .github/skills/pocketbase-schema/pb-migrate-create.sh seed_categories seed

The type argument selects the boilerplate template:

  • create (default): new Collection(...) skeleton with commented field examples
  • modify: findCollectionByNameOrId() skeleton with add/remove/modify examples
  • seed: Record insertion skeleton

After generating, edit the file to fill in collection name and fields.

Schema Inspect

Requires the server to be running.

bash
# Dump all collections
bash .github/skills/pocketbase-schema/pb-schema-inspect.sh

# Dump a specific collection
bash .github/skills/pocketbase-schema/pb-schema-inspect.sh posts

Schema Validate

Stops the server, wipes pb_data, and runs all migrations to check for errors. Does NOT restart the server — run pb-reset.sh or pb-dev.sh afterward.

bash
bash .github/skills/pocketbase-schema/pb-schema-validate.sh

Workflow

Follow this loop when adding or modifying collections:

  1. Inspect current schema to understand what exists
    bash
    bash .github/skills/pocketbase-schema/pb-schema-inspect.sh
    
  2. Generate a migration boilerplate
    bash
    bash .github/skills/pocketbase-schema/pb-migrate-create.sh create_posts create
    
  3. Edit the generated file — fill in collection name, fields, rules, and indexes
  4. Validate — dry-run all migrations to catch errors
    bash
    bash .github/skills/pocketbase-schema/pb-schema-validate.sh
    
  5. Reset & verify — start fresh server and check admin dashboard
    bash
    bash .github/skills/pocketbase/pb-reset.sh
    

Migration Authoring Rules

These rules prevent the most common agent mistakes. Follow them strictly.

Relations: Always Look Up Collection IDs

Never hardcode a collectionId. Always resolve it at migration time:

javascript
migrate((app) => {
  const users = app.findCollectionByNameOrId("users")

  const collection = new Collection({
    name: "posts",
    type: "base",
    fields: [
      new RelationField({
        name: "author",
        collectionId: users.id,     // CORRECT: resolved at runtime
        maxSelect: 1,
        cascadeDelete: false,
      }),
    ],
  })
  app.save(collection)
})

Migration Ordering

  • Files run in filename order (lexicographic by timestamp prefix)
  • A migration that references another collection must come after the migration that creates it
  • Use pb-migrate-create.sh to get correct timestamps — do NOT manually set timestamps

Always Write DOWN Migrations

Every migrate() call takes two callbacks: UP and DOWN. Always implement both:

javascript
migrate((app) => {
  // UP: create or modify
}, (app) => {
  // DOWN: reverse the UP changes
})

Auth Collections

Auth collections get system fields automatically (email, emailVisibility, verified, password, tokenKey). Do not re-declare them. Only add your custom fields:

javascript
const collection = new Collection({
  type: "auth",
  name: "users",
  fields: [
    new TextField({ name: "displayName", max: 100 }),
    // email, password, etc. are added automatically
  ],
  passwordAuth: { enabled: true },
})

View Collections

View collections are read-only and backed by a SQL SELECT:

javascript
const collection = new Collection({
  type: "view",
  name: "posts_with_authors",
  viewQuery: "SELECT p.id, p.title, u.displayName as author FROM posts p JOIN users u ON p.author = u.id",
  // listRule / viewRule apply; create/update/delete rules are ignored
})

Common Mistakes

MistakeFix
Hardcoded collectionId: "abc123"Use app.findCollectionByNameOrId("name").id
Migration references a collection that doesn't exist yetEnsure the creating migration has an earlier timestamp
Re-declaring email, password on auth collectionsThese are system fields — they exist automatically
Missing DOWN migrationAlways implement the second callback to migrate()
Using $app instead of appThe callback parameter is app, not $app
Setting rules to undefined or omitting themUse null (superuser only), "" (public), or a filter string
new Field(...) instead of new TextField(...)Use the specific constructor: TextField, NumberField, etc.
Manually naming migration filesAlways use pb-migrate-create.sh for correct timestamps

Field Types Quick Reference

ConstructorKey Options
TextFieldrequired, min, max, pattern
NumberFieldrequired, min, max, onlyInt
BoolFieldrequired
EmailFieldrequired, onlyDomains, exceptDomains
URLFieldrequired, onlyDomains, exceptDomains
DateFieldrequired
AutodateFieldonCreate, onUpdate
SelectFieldvalues (required), maxSelect
FileFieldmaxSelect, maxSize, mimeTypes, thumbs, protected
RelationFieldcollectionId (required), maxSelect, cascadeDelete
JSONFieldrequired (nullable unlike other fields)
EditorFieldrequired, maxSize, convertURLs
PasswordFieldrequired, min, max, cost
GeoPointFieldrequired

API Rules Quick Reference

ValueMeaning
nullSuperuser only (locked)
""Public access (no auth required)
"@request.auth.id != ''"Any authenticated user
"author = @request.auth.id"Owner only
"@request.auth.verified = true"Verified users only

Rules support: =, !=, >, >=, <, <=, ~ (contains), !~, &&, ||

For multi-value relation checks use ?=: "members ?= @request.auth.id"

For the full JS Migration API reference, see the pocketbase skill's JS Migration Reference section.