BuildWithMatija
Get In Touch
  1. Home
  2. Blog
  3. Payload
  4. Payload CMS SDK: CLI Toolkit for Faster Migrations

Payload CMS SDK: CLI Toolkit for Faster Migrations

Set up an authenticated Payload CMS SDK client and run CLI scripts with tsx to speed migrations, content cleanup, and…

30th January 2026·Updated on:22nd February 2026·MŽMatija Žiberna·
Payload
Payload CMS SDK: CLI Toolkit for Faster Migrations

Need Help Making the Switch?

Moving to Next.js and Payload CMS? I offer advisory support on an hourly basis.

Book Hourly Advisory

Related Posts:

  • •Payload CMS Cookie Auth: 7 Troubleshooting Secrets for Next.js
  • •Payload CMS for Ecommerce: Architect the Content Split
  • •Payload CMS for Sales Teams: Turn Website into Sales Engine

During a recent migration from WordPress to Payload CMS, I ran into a familiar problem. Getting the data across was only half the work. The real time sink was all the small fixes afterward. Tweaking titles, correcting fields, cleaning up content. Doing all of that through the Admin UI quickly became slow and error prone.

Payload gives you several ways to input and modify data, but what helped me most during this phase was the SDK. Especially for targeted, one off changes, having a way to run authenticated scripts from the terminal was a huge productivity boost.

In this article, I will show how I set up a small SDK based toolkit for CLI scripts. It lets you run find, create, update, and delete operations directly against Payload without opening the Admin UI. This approach works particularly well during migrations, cleanups, and ongoing maintenance.

Step 1: Install dependencies and confirm the SDK is available

The toolkit relies on @payloadcms/sdk and runs scripts with tsx, so you need dependencies installed before anything else.

pnpm install

Once that completes, you’re ready to configure the SDK client used by all scripts in this folder.

Step 2: Configure the toolkit environment

The shared client loads credentials from a local .env.toolkit file so you can authenticate from the CLI.

# File: scripts/toolkit/.env.toolkit
PAYLOAD_URL=http://localhost:80/api
# OR set NEXT_PUBLIC_SERVER_URL and it will append /api
# NEXT_PUBLIC_SERVER_URL=http://localhost:80

PAYLOAD_EMAIL=you@example.com
PAYLOAD_PASSWORD=your-password

This file gives the SDK a base URL and login credentials. The client reads it automatically before it initializes, so every script can rely on the same configuration.

Step 3: Use the shared SDK client

All scripts should import the shared client from scripts/toolkit/client.ts. If you need authenticated access, call getAuthenticatedSdk() to get a JWT-backed SDK instance.

// File: scripts/toolkit/fix-titles.ts
import { getAuthenticatedSdk } from "./client";

async function run() {
  const sdk = await getAuthenticatedSdk();

  const pages = await sdk.find({ collection: "page", limit: 5 });
  if (pages.docs[0]) {
    await sdk.update({
      collection: "page",
      id: pages.docs[0].id,
      data: { title: "Updated from CLI" },
    });
  }
}

run().catch(console.error);

This example logs in, queries a few pages, and updates one document. The key idea is that authentication happens once in getAuthenticatedSdk(), and the returned SDK carries the JWT for all subsequent requests.

Example: find, update, create, delete

Use the SDK for quick CRUD tasks while staying within Payload permissions.

import { getAuthenticatedSdk } from "./client";

async function run() {
  const sdk = await getAuthenticatedSdk();

  // Find
  const pages = await sdk.find({ collection: "page", limit: 5 });
  console.log("Found:", pages.totalDocs);

  // Update
  if (pages.docs[0]) {
    await sdk.update({
      collection: "page",
      id: pages.docs[0].id,
      data: { title: "Updated from CLI" },
    });
  }

  // Create (remember tenant, see below)
  await sdk.create({
    collection: "page",
    data: {
      title: "CLI Page",
      // tenant: 1,
    },
  });

  // Delete
  // await sdk.delete({ collection: 'page', id: pages.docs[0].id })
}

run().catch(console.error);

Step 4: Run the script from the terminal

With the script in place, run it using tsx so TypeScript executes without a build step.

npx tsx scripts/toolkit/fix-titles.ts

At this point you’re running real SDK operations from the CLI, with the same permissions your user has in Payload—just without the Admin UI.

Step 5: Multi-tenant note for this project

This repo supports multiple tenants (adart, making-light). When you create documents in tenant-aware collections, include the tenant field in data. Updates by id are safe because IDs are unique. If you need a tenant-aware example, review scripts/toolkit/example-bulk-update.ts.

Tenant-aware create example

import { getAuthenticatedSdk } from "./client";

async function run() {
  const sdk = await getAuthenticatedSdk();

  await sdk.create({
    collection: "page",
    data: {
      title: "CLI Page (AdArt)",
      tenant: 1,
    },
  });
}

run().catch(console.error);

Conclusion

The problem was simple but painful: CLI scripts were blocked by Admin-only workflows. By wiring a shared Payload SDK client and a local .env.toolkit, you can run authenticated operations directly from the terminal. You now know how to configure the SDK, write a script, and execute it in this repo without the Admin UI. Let me know in the comments if you have questions, and subscribe for more practical development guides.

Thanks, Matija

📚 Comprehensive Payload CMS Guides

Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.

No spam. Unsubscribe anytime.

📄View markdown version
0

Frequently Asked Questions

Comments

Leave a Comment

Your email will not be published

Stay updated! Get our weekly digest with the latest learnings on NextJS, React, AI, and web development tips delivered straight to your inbox.

10-2000 characters

• Comments are automatically approved and will appear immediately

• Your name and email will be saved for future comments

• Be respectful and constructive in your feedback

• No spam, self-promotion, or off-topic content

Matija Žiberna
Matija Žiberna
Full-stack developer, co-founder

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

You might be interested in

Payload CMS Cookie Auth: 7 Troubleshooting Secrets for Next.js
Payload CMS Cookie Auth: 7 Troubleshooting Secrets for Next.js

19th February 2026

Payload CMS for Ecommerce: Architect the Content Split
Payload CMS for Ecommerce: Architect the Content Split

15th February 2026

Payload CMS for Sales Teams: Turn Website into Sales Engine
Payload CMS for Sales Teams: Turn Website into Sales Engine

17th January 2026

Table of Contents

  • Step 1: Install dependencies and confirm the SDK is available
  • Step 2: Configure the toolkit environment
  • Step 3: Use the shared SDK client
  • Example: find, update, create, delete
  • Step 4: Run the script from the terminal
  • Step 5: Multi-tenant note for this project
  • Tenant-aware create example
  • Conclusion
On this page:
  • Step 1: Install dependencies and confirm the SDK is available
  • Step 2: Configure the toolkit environment
  • Step 3: Use the shared SDK client
  • Example: find, update, create, delete
  • Step 4: Run the script from the terminal
Build With Matija Logo

Build with Matija

Matija Žiberna

I turn scattered business knowledge into one usable system. End-to-end system architecture, AI integration, and development.

Quick Links

Projects
  • How I Work
  • Blog
  • RSS Feed
  • Services

    • Payload CMS Websites
    • Bespoke AI Applications
    • Advisory

    Payload

    • Payload CMS Websites
    • Payload CMS Developer
    • Audit
    • Migration
    • Pricing
    • Payload vs Sanity
    • Payload vs WordPress
    • Payload vs Strapi
    • Payload vs Contentful

    Industries

    • Manufacturing
    • Construction

    Get in Touch

    Have a project in mind? Let's discuss how we can help your business grow.

    Book a discovery callContact me →
    © 2026BuildWithMatija•Principal-led system architecture•All rights reserved