| name | cli-recipes |
| description | This skill should be used when the user asks about "payload migrate", "payload generate:types", "payload generate:importmap", "payload migrate:create", "payload migrate:down", "payload migrate:reset", "payload migrate:refresh", "payload migrate:status", "payload run", "payload jobs:run", "generate:db-schema", "Payload CLI commands", or needs to run the Payload command-line tool for schema migrations, codegen, one-off scripts, or job processing. |
PayloadCMS — CLI Recipes
The payload CLI ships as a binary in the payload npm package. Run it via the project's package manager so it picks up your payload.config.ts:
pnpm payload <command>
npx payload <command>
The scaffolder wires the most-used commands into package.json scripts:
{
"scripts": {
"generate:types": "payload generate:types",
"generate:importmap": "payload generate:importmap",
"migrate": "payload migrate",
"migrate:create": "payload migrate:create",
"migrate:down": "payload migrate:down",
"migrate:refresh": "payload migrate:refresh",
"migrate:reset": "payload migrate:reset",
"migrate:status": "payload migrate:status"
}
}
Code Generation
generate:types
Regenerates src/payload-types.ts from your collections, globals, and locales. Run after any schema change:
pnpm generate:types
Output path comes from payload.config.ts:
typescript: {
outputFile: path.resolve(dirname, 'payload-types.ts'),
declare: false,
}
Commit payload-types.ts — your app code imports from it.
generate:importmap
Builds src/app/(payload)/admin/importMap.js from string-path component references in your config. Required after adding any:
- Custom field component
- Custom view
- Custom admin component (
beforeDashboard, etc.)
- Plugin that registers components
pnpm generate:importmap
If the admin panel says "Could not resolve component X" — you forgot to run this. Commit importMap.js.
GraphQL schema — payload-graphql generate:schema
The payload bin has no generate:graphql-schema command in v3. GraphQL schema generation lives in the payload-graphql bin shipped with @payloadcms/graphql:
pnpm add @payloadcms/graphql
pnpm payload-graphql generate:schema
The output file is set via graphQL.schemaOutputFile in payload.config.ts (useful for graphql-codegen).
generate:db-schema
Generates the Drizzle schema file for SQL adapters (Postgres/SQLite):
pnpm payload generate:db-schema
Utility Commands
payload run
The documented way to execute one-off Local API scripts. Loads env exactly like Next.js (no dotenv wiring needed) and runs the TypeScript file via tsx:
pnpm payload run scripts/backfill-slugs.ts
Flags:
--use-swc — use @swc-node/register instead of tsx (faster startup; install it first).
--disable-transpile — skip transpilation for alternative runtimes, e.g. bunx --bun payload run src/seed.ts --disable-transpile.
Source: https://payloadcms.com/docs/local-api/outside-nextjs
payload info
Prints environment and version info — attach it to bug reports:
pnpm payload info
jobs:run and jobs:handle-schedules
Run queued jobs in a separate process — the recommended runner on dedicated servers, with no impact on API response times:
pnpm payload jobs:run --queue default --limit 10 --cron "*/5 * * * *" --handle-schedules --all-queues
--cron keeps the process alive and ticking; omit it for a single drain. --handle-schedules also enqueues due scheduled jobs; --all-queues processes every queue.
Enqueue scheduled jobs only (no execution):
pnpm payload jobs:handle-schedules --cron "*/5 * * * *"
See the jobs-queue skill for queue configuration, schedules, and the HTTP run endpoint.
Migrations
Migrations are SQL/Mongo scripts checked into src/migrations/. Required for Postgres/SQLite in production — db.push is dev-only.
migrate:create
Generate a new migration from your current code vs DB state:
pnpm migrate:create add-tags-collection
Writes two files:
src/migrations/<timestamp>_add-tags-collection.ts
src/migrations/<timestamp>_add-tags-collection.json (snapshot)
The generated file contains up and down functions. Inspect — and edit when needed — before committing.
migrate
Apply all pending migrations:
pnpm migrate
Run on deploy, before starting the app. Recommended deploy script:
pnpm migrate && pnpm build && pnpm start
migrate:status
List which migrations are pending vs. applied:
pnpm migrate:status
migrate:down
Roll back the most recently applied migration:
pnpm migrate:down
Useful when a deploy goes wrong. Each migration's down function must reverse the up function. Always test rollback in staging before production.
migrate:refresh
Roll back ALL applied migrations, then re-apply them. Destructive in production — typically only for dev resets:
pnpm migrate:refresh
migrate:reset
Roll back ALL applied migrations (without re-applying). Even more destructive:
pnpm migrate:reset
migrate:fresh
Drop the entire DB and rerun migrations. NEVER in prod:
pnpm migrate:fresh
Workflow Cheat Sheets
Adding a field
pnpm generate:types
pnpm migrate:create add-posts-published-at
git add src/migrations/ src/collections/Posts.ts src/payload-types.ts
git commit -m "feat(posts): add publishedAt"
pnpm migrate
Adding a custom admin component
pnpm generate:importmap
git add src/app/\(payload\)/admin/importMap.js src/components/CustomField.tsx
git commit -m "feat(admin): custom field component"
Bootstrapping a new dev machine
pnpm install
cp .env.example .env
pnpm migrate
pnpm generate:importmap
pnpm dev
Fixing a broken migration
pnpm migrate:status
pnpm migrate:down
pnpm migrate
CI Integration
GitHub Actions:
- name: Run migrations
run: pnpm migrate
env:
DATABASE_URI: ${{ secrets.DATABASE_URI }}
PAYLOAD_SECRET: ${{ secrets.PAYLOAD_SECRET }}
- name: Generate types
run: pnpm generate:types
- name: Verify import map is fresh
run: pnpm generate:importmap && git diff --exit-code src/app/\(payload\)/admin/importMap.js
The last step catches forgotten generate:importmap runs at PR time.
Custom CLI Scripts via Local API
Need to do a one-off task (data backfill, audit, export)? Write a script in scripts/ and execute it with payload run — it loads env like Next.js and handles TypeScript for you:
import { getPayload } from 'payload'
import config from '../src/payload.config'
import slugify from 'slugify'
async function run() {
const payload = await getPayload({ config })
const { docs } = await payload.find({
collection: 'posts',
where: { slug: { exists: false } },
limit: 10000,
})
for (const doc of docs) {
await payload.update({
collection: 'posts',
id: doc.id,
data: { slug: slugify(doc.title, { lower: true, strict: true }) },
})
console.log('Slugged', doc.id)
}
process.exit(0)
}
run().catch( {
.(err)
process.()
})
Run it:
pnpm payload run scripts/backfill-slugs.ts
Add as a package script when reusable. Use this pattern for any "do X to every document" job that doesn't deserve a migration.
Notes
payload run executes scripts via tsx and loads env like Next.js — no manual dotenv or loader setup needed (--use-swc and --disable-transpile cover other runtimes).
- Migration files are TypeScript by default. Compile-time errors stop the migration.
- On Postgres,
migrate runs in a transaction per migration. SQLite has the same behavior with transactionOptions.
- MongoDB migrations are schemaless transformations — write your own data normalization in
up/down.
See Also
- The
adapters skill — push vs migrations decision.
- The
setup skill — scaffolder-installed scripts.
- The
troubleshoot skill — common migration errors.