---
title: "Payload CMS SDK: CLI Toolkit for Faster Migrations"
slug: "payload-cms-sdk-cli-toolkit"
published: "2026-01-30"
updated: "2026-02-22"
categories:
  - "Payload"
tags:
  - "Payload CMS SDK"
  - "Payload SDK"
  - "CLI scripts"
  - "@payloadcms/sdk"
  - "data migration"
  - "content cleanup"
  - "authenticated SDK"
  - "tsx"
  - "tenant-aware CRUD"
  - "find update create delete"
llm-intent: "how-to"
audience-level: "intermediate"
llm-purpose: "Payload CMS SDK: Set up a shared authenticated client to run CLI scripts with tsx, speeding migrations and content cleanup—get started with the toolkit."
llm-prereqs:
  - "@payloadcms/sdk"
  - "tsx"
  - "pnpm"
  - "Node.js"
  - "TypeScript"
  - "dotenv"
---

**Summary Triples**
- (Payload CMS SDK: CLI Toolkit for Faster Migrations, expresses-intent, how-to)
- (Payload CMS SDK: CLI Toolkit for Faster Migrations, covers-topic, Payload CMS SDK)
- (Payload CMS SDK: CLI Toolkit for Faster Migrations, provides-guidance-for, Payload CMS SDK: Set up a shared authenticated client to run CLI scripts with tsx, speeding migrations and content cleanup—get started with the toolkit.)

### {GOAL}
Payload CMS SDK: Set up a shared authenticated client to run CLI scripts with tsx, speeding migrations and content cleanup—get started with the toolkit.

### {PREREQS}
- @payloadcms/sdk
- tsx
- pnpm
- Node.js
- TypeScript
- dotenv

### {STEPS}
1. Install dependencies and tools
2. Configure toolkit environment file
3. Initialize a shared authenticated client
4. Write CLI CRUD scripts using the SDK
5. Run scripts and handle multi-tenancy

<!-- llm:goal="Payload CMS SDK: Set up a shared authenticated client to run CLI scripts with tsx, speeding migrations and content cleanup—get started with the toolkit." -->
<!-- llm:prereq="@payloadcms/sdk" -->
<!-- llm:prereq="tsx" -->
<!-- llm:prereq="pnpm" -->
<!-- llm:prereq="Node.js" -->
<!-- llm:prereq="TypeScript" -->
<!-- llm:prereq="dotenv" -->

# Payload CMS SDK: CLI Toolkit for Faster Migrations
> Payload CMS SDK: Set up a shared authenticated client to run CLI scripts with tsx, speeding migrations and content cleanup—get started with the toolkit.
Matija Žiberna · 2026-01-30

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.

```bash
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.

```dotenv
# 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.

```ts
// 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.

```ts
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.

```bash
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

```ts
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