PocketBase Migrations
SkillFiles & storagePocketBase Migrations is a skill that gives an AI agent working knowledge of schema migrations and versioning for PocketBase. It helps when creating migrations, managing schema versions, syncing collections between environments, or creating collections programmatically, covering migrate commands, migration file format, snapshot imports, and the _migrations tracking table.
Use PocketBase Migrations in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add PocketBase Migrations and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the PocketBase Migrations skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
No other account needed.
Have a PocketBase project whose schema you want to change or version.
What your AI can do with it
- Create migrations for PocketBase schema changes
- Manage schema versions with the _migrations tracking table
- Sync collections between environments
- Use the automigrate workflow
- Create collections programmatically
- Import snapshots and follow the migration file format
Getting started
- Have a PocketBase project whose schema you want to change or version.
- Add the PocketBase Migrations skill to your agent setup.
- Ask the agent to create a migration or sync collections between environments.
- Review the generated migration files and apply them with the migrate commands.
What this skill tells your AI
The instructions your AI receives, as published by davila7/claude-code-templates in cli-tool/components/skills/pocketbase/pb-migrations/SKILL.md and read by ahel’s review.
Overview
PocketBase supports two approaches to schema management:
- Auto-migrate (default in dev) — Dashboard changes auto-generate migration files in
pb_migrations/ - Manual migrations — write migration files by hand for full control
CLI Commands
# Create a new empty migration file
./pocketbase migrate create "add_posts_collection"
# Creates: pb_migrations/1234567890_add_posts_collection.js
# Apply all pending migrations
./pocketbase migrate up
# Revert the last applied migration
./pocketbase migrate down
# Generate a full snapshot of all current collections
./pocketbase migrate collections
# Creates a migration file that recreates all collections from scratch
# Sync migration history with actual DB state (mark all as applied)
./pocketbase migrate history-sync
Auto-migrate Mode
Enabled by default. When you change collections in the Dashboard, PocketBase auto-generates migration files in pb_migrations/.
# Start with auto-migrate (default)
./pocketbase serve
# Disable auto-migrate (production)
./pocketbase serve --automigrate=0
Workflow:
- Develop with auto-migrate ON — use Dashboard to design schema
- Migration files are auto-generated in
pb_migrations/ - Commit these files to git
- Deploy: migrations run automatically on
servestart - In production: use
--automigrate=0to prevent Dashboard changes from generating new migrations
Migration File Format
// pb_migrations/1234567890_add_posts_collection.js
migrate(
// UP — apply migration
function(app) {
var collection = new Collection({
name: "posts",
type: "base",
fields: [
{ name: "title", type: "text", required: true },
{ name: "body", type: "editor" },
{ name: "author", type: "relation", collectionId: "USERS_COLLECTION_ID", cascadeDelete: false, maxSelect: 1, required: true },
{ name: "status", type: "select", values: ["draft", "published", "archived"] },
{ name: "published_at", type: "date" },
{ name: "tags", type: "relation", collectionId: "TAGS_COLLECTION_ID", maxSelect: 0 }
],
indexes: [
"CREATE INDEX idx_posts_author ON posts (author)",
"CREATE INDEX idx_posts_status ON posts (status)",
"CREATE UNIQUE INDEX idx_posts_title ON posts (title)"
],
listRule: "", // WARNING: "" means public access — use a filter or null to restrict
viewRule: "", // WARNING: "" means public access — use a filter or null to restrict
createRule: "@request.auth.id != ''",
updateRule: "author = @request.auth.id",
deleteRule: "author = @request.auth.id"
})
app.save(collection)
},
// DOWN — revert migration
function(app) {
var collection = app.findCollectionByNameOrId("posts")
app.delete(collection)
}
)
Important: the app inside migrations is a transactional instance. If any error occurs, the entire migration is rolled back.
Creating Collections Programmatically
Base collection
var collection = new Collection({
name: "posts",
type: "base",
fields: [
{ name: "title", type: "text", required: true, min: 3, max: 200 },
{ name: "slug", type: "text", required: true, autogenerate: { pattern: "slugify(title)" } },
{ name: "body", type: "editor" },
{ name: "cover", type: "file", maxSelect: 1, maxSize: 5242880, mimeTypes: ["image/jpeg", "image/png", "image/webp"] },
{ name: "views", type: "number", min: 0 },
{ name: "metadata", type: "json", maxSize: 2000000 },
{ name: "featured", type: "bool" },
{ name: "published_at", type: "date" }
]
})
app.save(collection)
Auth collection
var collection = new Collection({
name: "users",
type: "auth",
fields: [
{ name: "name", type: "text", required: true },
{ name: "avatar", type: "file", maxSelect: 1, maxSize: 5242880 },
{ name: "role", type: "select", values: ["user", "editor", "admin"], required: true }
],
passwordAuth: { enabled: true, identityFields: ["email", "username"] },
oauth2: { enabled: true },
otp: { enabled: false },
mfa: { enabled: false },
authToken: { duration: 604800 } // 7 days
})
app.save(collection)
View collection
var collection = new Collection({
name: "posts_stats",
type: "view",
viewQuery: "SELECT p.id, p.title, COUNT(c.id) as comments_count, p.views FROM posts p LEFT JOIN comments c ON c.post = p.id GROUP BY p.id",
listRule: "",
viewRule: ""
})
app.save(collection)
Modifying Existing Collections
migrate(function(app) {
var collection = app.findCollectionByNameOrId("posts")
// Add a new field
collection.fields.add({
name: "subtitle",
type: "text",
max: 500
})
// Remove a field
collection.fields.removeByName("old_field")
// Update API rules
collection.listRule = "@request.auth.id != ''"
collection.viewRule = ""
// Add index
collection.indexes.push("CREATE INDEX idx_posts_subtitle ON posts (subtitle)")
app.save(collection)
}, function(app) {
var collection = app.findCollectionByNameOrId("posts")
collection.fields.removeByName("subtitle")
app.save(collection)
})
Raw SQL in Migrations
migrate(function(app) {
app.db().newQuery("ALTER TABLE posts ADD COLUMN legacy_id TEXT DEFAULT ''").execute()
app.db().newQuery("UPDATE posts SET legacy_id = id WHERE legacy_id = ''").execute()
}, function(app) {
app.db().newQuery("ALTER TABLE posts DROP COLUMN legacy_id").execute()
})
Warning: raw SQL bypasses PocketBase's schema cache. Run migrate collections afterward to re-sync if needed.
Settings & Superuser in Migrations
Initialize app settings
onBootstrap(function(e) {
var settings = e.app.settings()
settings.meta.appName = "My App"
settings.meta.appURL = "https://myapp.com"
settings.meta.senderName = "My App"
settings.meta.senderAddress = "noreply@myapp.com"
settings.smtp.enabled = true
settings.smtp.host = "smtp.example.com"
settings.smtp.port = 587
settings.smtp.username = $os.getenv("SMTP_USER")
settings.smtp.password = $os.getenv("SMTP_PASS")
e.app.save(settings)
return e.next()
})
Create superuser in migration
migrate(function(app) {
var superusers = app.findCollectionByNameOrId("_superusers")
var record = new Record(superusers)
// IMPORTANT: always set PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD env vars
var email = $os.getenv("PB_ADMIN_EMAIL")
var password = $os.getenv("PB_ADMIN_PASSWORD")
if (!email || !password) {
throw new Error("PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD env vars are required")
}
record.set("email", email)
record.set("password", password)
app.save(record)
})
Snapshot Migrations
./pocketbase migrate collections generates a complete snapshot — useful for:
- Bootstrapping a new environment
- Resetting migration history
- Reviewing full schema in one file
The generated file uses app.importCollections(collections) which supports two modes:
- Default (merge/extend): adds new collections and fields, updates existing ones, doesn't delete anything
- Delete missing:
app.importCollections(collections, true)— deletes collections/fields not in the snapshot
_migrations Table
PocketBase tracks applied migrations in the internal _migrations table:
id— auto-generatedfile— migration filenameapplied— timestamp
migrate history-sync marks all existing migration files as applied without running them — useful when importing an existing database.
Best Practices
- Dev: use auto-migrate + Dashboard for schema design, commit generated files
- Staging/Prod: deploy with
--automigrate=0, migrations run on startup - Always write DOWN migrations — reversibility saves you when things go wrong
- One concern per migration — don't mix unrelated schema changes
- Test migrations: apply on a copy of production data before deploying
- Use
migrate collectionsperiodically to snapshot current state for documentation - Never edit applied migrations — create a new migration to fix issues
- Seed data: prefer a dedicated migration for one-time initial data; if using
onBootstrap, make the seed logic idempotent (existence checks/upserts) because bootstrap runs on every app start
Signals
- GitHub stars
- 32k
- Forks
- 4k
- Last commit
- Oct 2026
Questions
- When should this skill be used?
- Use it when creating migrations, managing schema versions, syncing collections between environments, using automigrate, or creating collections programmatically.
- Does it cover the _migrations table?
- Yes, it covers the _migrations tracking table along with migrate commands, the migration file format, and snapshot imports.
Advanced
- Item type
- skill
- Key
pocketbase-migrations- Source
- github.com/davila7/claude-code-templates
github.com/davila7/claude-code-templates
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptpptx
Skill · anthropics
More in Files & storagedocx
Skill · anthropics
More in Files & storageresearch
Skill · mattpocock
More in Files & storageto-tickets
Skill · mattpocock
More in Files & storage