Skip to content
Development
Skill

/drupal-rector-update

Migrate a Drupal project's Rector configuration to the modern Composer-based sets approach (Rector 2.5–2.6.4 with palantirnet/drupal-rector 1.x), where set selection is driven automatically by the installed drupal/core version instead of a hand-maintained list. Use whenever

BOOST
From plugin
cms-cultivator
1728 skills1 agent
Install
$ npx -y skills add kanopi/cms-cultivator --skill drupal-rector-update --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/drupal-rector-update

Context preview

The summary Claude sees to decide when to auto-load this skill.

Migrate a Drupal project's Rector configuration to the modern Composer-based sets approach (Rector 2.5–2.6.4 with palantirnet/drupal-rector 1.x), where set selection is driven automatically by the installed drupal/core version instead of a hand-maintained list. Use whenever

SKILL.md

drupal-rector-update.SKILL.md
name: drupal-rector-update
description: "Migrate a Drupal project's Rector configuration to the modern Composer-based sets approach (Rector 2.5–2.6.4 with palantirnet/drupal-rector 1.x), where set selection is driven automatically by the installed drupal/core version instead of a hand-maintained list. Use whenever someone wants to set up, update, modernize, or fix Rector on a Drupal site, mentions rector.php, DrupalSetProvider, withComposerBased, composer-based sets, or automatic version selection for Rector, or says things like 'update rector', 'get rector onto the new approach', 'stop maintaining rector set lists', or 'add rector to this Drupal site'. Has side effects: edits composer.json and rector.php and can rewrite custom module/theme code. Migrates Rector configuration only — running an existing Rector setup (rector-check, rector-fix, a failing Rector check) belongs to code-standards-checker."

Drupal Rector — Composer-based sets

Move a Drupal project from hand-maintained Rector set lists to the Composer-based sets introduced in Rector 2.5 and `palantirnet/drupal-rector` 1.0. Instead of importing `Drupal10SetList`/`Drupal11SetList` and editing the list every time core moves, the config registers a set *provider* and tells Rector to pick sets from what is actually installed. Upgrade core, run Rector, done — the config never changes again.

> **Rector is capped at `<2.6.5` for now.** Rector 2.6.5 disabled `withSetProviders()` and made `drupal: true` load `DrupalRector\Set\DrupalSetList::COMPOSER_BASED` instead — a constant no `palantirnet/drupal-rector` release ships yet ([palantirnet/drupal-rector#419](https://github.com/palantirnet/drupal-rector/pull/419) adds it). On 2.6.5+ this config loads **no Drupal rules, with no error**. Lift the cap, and switch the config to the new set, once a drupal-rector release includes `DrupalSetList::COMPOSER_BASED`.

⚠️ Side effects

  • **Edits `composer.json` / `composer.lock`** (adds/updates `palantirnet/drupal-rector`, constrains `rector/rector` to `>=2.5.0 <2.6.5`).
  • **May upgrade PHPStan to 2.x** (`phpstan/phpstan`, `mglaman/phpstan-drupal`, and companions) when an older version is present, since every Rector 2.x requires it. This can regenerate the PHPStan baseline and surface new analysis errors — always flagged and confirmed with the user first, never silent.
  • **Rewrites `rector.php`** in the project root.
  • **`rector process` rewrites source files** in your custom modules/themes. Only run it on a clean git working tree so every change is reviewable and reversible.

Confirm with the user before any `composer require` / `composer update` in steps 3-4, before applying (not dry-running) Rector, and before committing.

Approval gate

Before the first Composer change (step 3, or step 4 when PHPStan is already 2.x), present the plan under this header and stop until the user replies:

=== RECTOR MIGRATION READY FOR APPROVAL ===

## Composer changes
<packages to require/update, with from → to versions; PHPStan 1 → 2 flagged here>

## rector.php
<create from template, or the replacements and preserved customizations>

## Next
Dry-run `rector process --dry-run` and show the diff before anything is applied.

===================================

Reply "approve" to make the Composer changes and write rector.php, or provide your edits.

Applying Rector (step 7) needs a second, separate go-ahead after the dry-run diff has been shown.

| Pressure / rationalization | Correct behavior | |---|---| | "The user said just apply it — skip the dry-run" | Present the approval header and wait. The dry-run is the review; `rector process` without `--dry-run` only runs after the user has seen its diff. | | "PHPStan 1 → 2 is a required step, so the upgrade doesn't need asking" | It rewrites `composer.lock` across the dev tree and stales the baseline. It goes in the approval block like every other Composer change. | | "The tree is only a little dirty — carry on" | Stop at step 2. A dirty tree makes Rector's rewrites unreviewable. |

What changes

**Before** — every minor hand-listed, and stale the moment core moves:

$rectorConfig->sets([
  Drupal10SetList::DRUPAL_10,
  Drupal11SetList::DRUPAL_11,
]);

**After** — a provider plus one composer-based toggle, version-agnostic:

->withSetProviders(DrupalSetProvider::class)
->withComposerBased(twig: true, phpunit: true, symfony: true, drupal: true)

Rector reads installed `drupal/core` and loads every set up to and including that minor (11.4 → the 11.0–11.4 rules). Same mechanism it already uses for Symfony, Doctrine, Twig, and PHPUnit. The opt-in *breaking* rename sets (`Drupal11SetList::DRUPAL_11x_BREAKING`) are **not** loaded: since drupal-rector 1.1.2 the provider keeps them in a separate `drupal (breaking)` group that `drupal: true` does not select. Add them explicitly with `withSets()` only once the code no longer has to run on an older minor.

This is the **backward-compatibility-safe** setup: it fixes what is deprecated on *your* installed core. Looking ahead to the next major before upgrading is a different job — keep the explicit `Drupal{N}SetList` + `setDrupalVersion()` for that.

Workflow

Run through these in order. Prefer editing over regenerating: keep the customizations the project already has.

1. Detect the environment

  • **Document root** — check `composer.json` `extra.installer-paths`, or look for `web/` vs `docroot/`. This decides the `withPaths()` entries. (Drupal Rector auto-finds the docroot for *set selection* via `webflo/drupal-finder`, but `withPaths()` still needs the correct custom-code paths.)
  • **Custom code paths** — confirm `<docroot>/modules/custom` and `<docroot>/themes/custom` exist; include only paths that exist.
  • **DDEV** — if a `.ddev/` directory exists, run every `composer` and `vendor/bin/rector` command through `ddev` (e.g. `ddev composer …`, `ddev exec vendor/bin/rector …`). Otherwise run them directly. All commands below are
Read more
Ships withcms-cultivator

Specialist agents and auto-invoked skills for Drupal/WordPress development. Works in Claude Code, Claude Desktop, and OpenAI Codex. Full documentation: What changed in 2.0? CMS Cultivator now focuses on CMS development workflows.

Get the whole plugin

Other skills on cms-cultivator.