prepare-wordpress
Prepare WordPress Project
Section titled “Prepare WordPress Project”When to use
Section titled “When to use”Use this skill when:
- Bootstrapping a new WordPress plugin or theme repo with standard tooling.
- Backfilling missing tooling in an existing project after drift or partial setup.
- Running a selective, phase-based setup flow with dry-run then confirmed apply.
Inputs required
Section titled “Inputs required”- Repo root (current working directory).
- Whether this is a new or existing project (auto-detected).
- Plugin metadata (prompted during execution).
Determinism checklist
Section titled “Determinism checklist”Apply DETERMINISM-CHECKLIST.md for this skill run.
Procedure
Section titled “Procedure”0) Detect existing project state
Section titled “0) Detect existing project state”Run the detection script to discover what already exists:
node skills/prepare-wordpress/scripts/detect_project.mjsThis outputs JSON with booleans for each component. Use it to skip phases that are already configured. Report to the user what will be added and what will be skipped.
Completion criterion: Detection JSON was produced and a phase-by-phase add/skip summary was shown to the user.
0b) Choose feature flags and execution mode
Section titled “0b) Choose feature flags and execution mode”Before changing files, ask which phases to run. Defaults: all phases enabled, dry-run first.
Hard gate: Do not run any --apply command until dry-run output is shown and the user confirms the selected phases.
plugin— create plugin bootstrap filereadme— createreadme.txtinit— initialize repo/package/composer basicsskills— install agent skillscomposer— install PHP dev deps and merge scriptsconfig— create/merge.editorconfigand.gitignorevitest— install and scaffold Vitesti18n— scaffold i18n files/scriptscleanup— remove strayyarn.lock
Use the planner script to preview actions:
node skills/prepare-wordpress/scripts/plan_setup.mjs --dry-runFeature flags:
# Run only selected phasesnode skills/prepare-wordpress/scripts/plan_setup.mjs --dry-run --only=init,composer,config
# Skip selected phasesnode skills/prepare-wordpress/scripts/plan_setup.mjs --dry-run --skip=skills,vitestApply safe shell commands from the plan (manual file merges are still called out as notes):
node skills/prepare-wordpress/scripts/plan_setup.mjs --apply --only=init,skills,composerMachine-readable dry-run output for automation:
node skills/prepare-wordpress/scripts/plan_setup.mjs --json --only=init,composerMachine-readable apply output with command execution results:
node skills/prepare-wordpress/scripts/plan_setup.mjs --json --apply --only=cleanupCompletion criterion: Selected phases and execution mode are explicit, dry-run output is shown, and user confirmation is captured before apply mode.
1) Gather plugin metadata
Section titled “1) Gather plugin metadata”Derive the plugin slug from the current folder name (e.g. ~/Projects/my-plugin → my-plugin). Use this as the default for the text domain.
Ask the user for the following (show defaults in parentheses):
- Plugin Name: Human-readable name (default: slug with hyphens replaced by spaces and title-cased, e.g.
My Plugin) - Plugin URI: URL for the plugin (default: empty)
- Description: Short description (default: empty)
- Author: Author name (default: empty)
- Author URI: Author URL (default: empty)
- License: License identifier (default:
GPL-2.0-or-later) - Text Domain: (default: folder name / plugin slug)
- Requires at least: Minimum WordPress version (default:
6.8) - Tested up to: Highest WordPress version tested (default:
7.0) - Requires PHP: Minimum PHP version (default:
8.3)
Store these values — they are used in Phase 1b (plugin.php), Phase 1b-2 (readme.txt), Phase 3 (composer.json), and Phase 6 (i18n scripts).
Also ask:
- Create readme.txt?: Whether to create a WordPress.org-style
readme.txt(default: yes) - Git remote URL: URL for the remote repository (e.g.
https://github.com/user/my-pluginorgit@github.com:user/my-plugin.git). Leave empty to skip.
Completion criterion: Every metadata field is filled (or intentionally empty), including readme and remote decisions.
1b) Create plugin.php
Section titled “1b) Create plugin.php”Skip if a PHP file with a Plugin Name: header already exists in the project root.
Create <plugin-slug>.php (using the folder name) with the standard WordPress plugin header:
<?php/** * Plugin Name: {Plugin Name} * Plugin URI: {Plugin URI} * Description: {Description} * Version: 0.1.0 * Author: {Author} * Author URI: {Author URI} * License: {License} * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: {Text Domain} * Domain Path: /languages * Requires at least: {Requires at least} * Tested up to: {Tested up to} * Requires PHP: {Requires PHP} */
declare(strict_types=1);
defined( 'ABSPATH' ) || exit;See: references/plugin-bootstrap.md
Completion criterion: Either an existing plugin header file was detected and preserved, or <plugin-slug>.php was created with the required header fields.
1b-2) Create readme.txt
Section titled “1b-2) Create readme.txt”Skip if the user answered no, or if readme.txt already exists.
Create readme.txt using the plugin metadata collected in Phase 1:
=== {Plugin Name} ===Contributors: {author-slug}Tags:Requires at least: {Requires at least}Tested up to: {Tested up to}Requires PHP: {Requires PHP}Stable tag: 0.1.0License: {License}License URI: https://www.gnu.org/licenses/gpl-2.0.html
{Description}
== Description ==
{Description}
== Installation ==
1. Upload the plugin files to `/wp-content/plugins/{plugin-slug}/`, or install through the WordPress plugins screen.2. Activate the plugin through the 'Plugins' screen in WordPress.
== Changelog ==
= 0.1.0 =* Initial release.See: references/readme-txt.md
Completion criterion: readme.txt exists in valid WordPress.org format, or skip reason is recorded.
1c) Initialize package files (if needed)
Section titled “1c) Initialize package files (if needed)”If package.json does not exist:
npm init -yIf composer.json does not exist, create it using the plugin metadata:
composer init --no-interaction --name=<author>/<plugin-slug> --description="{Description}" --license={License}If .git/ does not exist:
git initIf the user provided a Git remote URL, add it as the origin remote:
git remote add origin <remote-url>If .git/ already exists and has no origin remote but the user provided a URL, add it. If origin already exists, skip.
Completion criterion: Required init artifacts exist (package.json, composer.json, .git) and remote handling result is reported.
2) Install agent skills
Section titled “2) Install agent skills”Install the following skills. Skip any that already exist under ~/.copilot/skills/ or ~/.agents/skills/.
npx skills add https://github.com/automattic/agent-skills --skill wp-plugin-developmentnpx skills add https://github.com/automattic/agent-skills --skill wp-block-developmentnpx skills add https://github.com/automattic/agent-skills --skill wordpress-routernpx skills add https://github.com/automattic/agent-skills --skill wp-performancenpx skills add https://github.com/automattic/agent-skills --skill wp-wpcli-and-opsCompletion criterion: Each listed skill is installed or explicitly skipped because it already exists.
3) Composer dependencies and scripts
Section titled “3) Composer dependencies and scripts”Install all PHP dev dependencies in a single command:
composer require --dev phpunit/phpunit wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer pestphp/pestThen merge these scripts into composer.json (do not overwrite existing scripts).
Replace <plugin-slug> with the actual plugin slug (folder name / text domain).
{ "scripts": { "test": "phpunit", "lint": "phpcs --standard=WordPress --extensions=php .", "check": "wp plugin check <plugin-slug> --format=text" }}Note: The
checkscript requires Plugin Check (PCP) installed and activated in WordPress, and WP-CLI available. Install withwp plugin install plugin-check --activate.
See: references/composer-setup.md
Completion criterion: Composer dev dependencies are installed and scripts.test, scripts.lint, and scripts.check exist without overwriting unrelated scripts.
4) Config files
Section titled “4) Config files”.editorconfig — Skip if it already exists. Create with WordPress-standard settings.
See: references/config-files.md
.gitignore — If it exists, merge missing entries. If not, create it.
See: references/config-files.md
Completion criterion: .editorconfig and .gitignore are present, and existing .gitignore entries were merged non-destructively.
5) Vitest setup
Section titled “5) Vitest setup”Skip if vitest.config.js already exists.
npm install --save-dev vitest jsdomCreate vitest.config.js and tests/setup.js.
Merge a test:js script into package.json:
{ "scripts": { "test:js": "vitest run" }}See: references/vitest-setup.md
Completion criterion: vitest.config.js, tests/setup.js, and scripts.test:js are present, or a skip reason is recorded.
6) i18n scaffolding
Section titled “6) i18n scaffolding”Skip if i18n-map.json already exists.
Use the text domain collected in Phase 1.
Ask the user:
- Block paths: List any block directories that contain translatable JS strings (e.g.
blocks/my-block). If none yet, leave empty and updatei18n-map.jsonlater.
Then:
- Create
i18n-map.jsonwith the provided block paths. For each block path, mapblocks/<name>/save.js→build/blocks/<name>/index.js. If no block paths given, create an empty{}placeholder. - Merge i18n npm scripts into
package.json, using the provided text domain for the.potfilename and--domainflag. - Create
languages/directory.
See: references/i18n-setup.md
Completion criterion: i18n-map.json, languages/, and i18n npm scripts are present (or explicit skip/defer rationale is recorded).
7) Cleanup
Section titled “7) Cleanup”Remove any stray yarn.lock file that may have been created by npx commands:
rm -f yarn.lockOnly remove it if it did not exist before the skill ran (check the detection output).
Completion criterion: yarn.lock was removed only when it was created during this run.
8) Final summary
Section titled “8) Final summary”Print a status table showing each phase as ✅ installed, ⏭ skipped, or 🔀 merged.
Remind the user to:
- Run
composer installandnpm install.
Completion criterion: Final report includes per-phase status, skipped reasons, and verification outcomes.
Verification
Section titled “Verification”- All config files exist and are well-formed.
composer validatepasses.npm lsshows no missing peer dependencies for vitest.- Agent skills are present under
~/.copilot/skills/or~/.agents/skills/.
Failure modes / debugging
Section titled “Failure modes / debugging”composer requirefails: PHP version too old, or Composer not installed. Checkphp -vandcomposer --version.npx skills addfails: Node.js < 18 or network issue. Checknode -v.- Pest install fails with conflict: PHPUnit version mismatch. Let Composer resolve dependency tree.
Escalation
Section titled “Escalation”If a specific tool or dependency fails, install it manually and re-run the detection script to continue from where you left off.
📦 Source: soderlind/skills · Edit on GitHub