# Webiny Cms Bulk Actions

Authoring a custom Headless CMS bulk action (EntriesBulkAction) that Webiny runs as a...

- Repository: https://github.com/webiny/webiny-js (8051 stars)
- Category: Design
- License: see repository
- Last updated: 2026-10-30
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add webiny/webiny-js --skill webiny-cms-bulk-actions -g -a claude-code -y`
Codex: `npx skills add webiny/webiny-js --skill webiny-cms-bulk-actions -g -a codex -y`
Cursor: `npx skills add webiny/webiny-js --skill webiny-cms-bulk-actions -g -a cursor -y`
Gemini CLI: `npx skills add webiny/webiny-js --skill webiny-cms-bulk-actions -g -a gemini-cli -y`

## Description

Authoring a custom Headless CMS bulk action (EntriesBulkAction) that Webiny runs as a background task, plus the Admin-side button that triggers it. Use this skill when the developer wants to add a bulk action to the content-entry list (e.g. apply a discount, generate content, bulk-transform entries), understand loadData/processData, make the task converge, filter by custom fields, or trigger the action from the Admin UI. Requires Webiny 6.5.0 or newer.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Custom Headless CMS bulk actions

## TL;DR

A bulk action is a class implementing `EntriesBulkAction.Interface` with two methods, `loadData` (which entries) and `processData` (what to do to each). Register it with
`export default EntriesBulkAction.createImplementation({...})` via `<Api.Extension src>`.
For every registered bulk action, Webiny **automatically generates** a list background
task, a process background task, and a GraphQL mutation. On the Admin side, add a
`ContentEntryListConfig.Browser.BulkAction` button that calls `BulkActionFeature`'s
`useCase.execute({ model, action, where, data })`.

Available from **Webiny 6.5.0** (`webiny/api/cms/entry`).

## Backend, the bulk action

```typescript
// extensions/myBulkAction/api/MyBulkAction.ts
import {
  EntriesBulkAction,
  ListLatestEntriesUseCase,
  UpdateEntryUseCase
} from "webiny/api/cms/entry";

class MyBulkActionImpl implements EntriesBulkAction.Interface {
  // PascalCased into the task ids + GraphQL enum value, so "applyDiscount" →
  // tasks hcmsBulk(List|Process)ApplyDiscountEntries and frontend action "ApplyDiscount".
  readonly name = "applyDiscount";
  // Optional: restrict which models get the mutation/button.
  readonly modelIds = ["product"];
  // Optional: entries processed per batch (defaults to the configured batchSize).
  // readonly batchSize = 50;

  constructor(
    private listEntries: ListLatestEntriesUseCase.Interface,
    private updateEntry: UpdateEntryUseCase.Interface
  ) {}

  // Runs in the "list" task, with pagination (params.where/search/after/limit).
  async loadData(model, params) {
    const result = await this.listEntries.execute(model, params);
    return result.value; // { entries, meta }
  }

  // Runs in the "process" task, once per entry, in batches.
  async processData(model, params) {
    // params.id is a revision id ("<entryId>#0001"); params.data carries whatever the
    // Admin action sent.
    // ...update / transform the entry here...
  }
}

The rest: https://github.com/webiny/webiny-js/blob/HEAD/skills/user-skills/api/cms-bulk-actions/SKILL.md
