Skip to content

Commit c0c5f61

Browse files
henryperkinsclaude
andcommitted
[wp-env][wordpress-router]: correct wp-env against @wordpress/env 11.16.0 and route to it
Upstream's wp-env skill (WordPress#38) follows the @wordpress/env README, which lags the package code in several places. Checked against the 11.16.0 tarball (published 2026-09-23) and, where behavior mattered, run: - `composer` is not a `wp-env run` container. The package removed it (and `phpunit`), and validate-run-container.js throws on both. The list is now mysql, wordpress, cli, phpmyadmin (only when enabled), plus the tests-* containers. - `wp-env run cli "wp rewrite structure /%postname%/"` fails. run() hands argv to `docker compose exec` with no shell, so the quoted string is looked up as one executable name ("executable file not found in $PATH", reproduced with docker exec). The command is now unquoted, with a short explanation. - `wp-env run mysql mysql ...` fails: the database service is mariadb:lts (12.3.3 today), which ships `mariadb` and no `mysql`. - `npx wp-env` resolves the unscoped `wp-env` npm package when the local install is missing (a third-party "Security PoC" package), and npm assumes --yes in a non-interactive shell. Replaced with the README's own `npm exec --no -- wp-env`. - `cleanup` and `destroy` block on a confirmation prompt unless `--force`; the skill now says to get the user's go-ahead and pass it. - Override files merge `config`, `mappings`, and `lifecycleScripts` (merge-configs.js), not only the first two. - The invalid-source error is `Invalid or unrecognized source: "<value>"`, and a relative path without a leading `.` is parsed as a GitHub repo. - The tests environment still starts by default on 8889 but is deprecated with a startup warning; the skill names the `"testsEnvironment": false` opt-out and the `--config` replacement. - `--auto-port` is ignored when CI is set. Fork conventions: the 6.9 floor per docs/compatibility-policy.md (wp-env covers no 7.0-only API), the license field, a wp-playground boundary in the description, and "verified against @wordpress/env 11.16.0" in prose. @wordpress/env is not a drift-registry upstream, so it carries no `verified through:` marker. Registration: docs/skill-set-v1.md lists 22 skills. The router sends wp-env / .wp-env.json requests to wp-env (upstream still routes wp-env to the planned wp-testing skill) and WordPress#105's WebMCP / Playground MCP terms to wp-playground's website.md. wp-playground's escalation now names the wp-env skill. assertWpEnvPrecision pins the corrections and the fork-only router entry. It fails on upstream's original SKILL.md, and each of its six exclusions matches a line in that original. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 77ec1b9 commit c0c5f61

5 files changed

Lines changed: 74 additions & 22 deletions

File tree

‎docs/skill-set-v1.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# WordPress skill set (v1)
22

3-
This repository ships 21 skills. The list below is the complete inventory of
3+
This repository ships 22 skills. The list below is the complete inventory of
44
`skills/*` and is enforced against the filesystem by
55
`assertRemediationRelease191()` in `eval/harness/release-conformance.mjs`, so it
66
cannot drift from what is actually installed.
@@ -15,6 +15,7 @@ cannot drift from what is actually installed.
1515
- `wp-ai-plugin`
1616
- `wp-block-development`
1717
- `wp-block-themes`
18+
- `wp-env`
1819
- `wp-interactivity-api`
1920
- `wp-patterns`
2021
- `wp-performance`

‎eval/harness/release-conformance.mjs‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,43 @@ export function assertAbilitiesApiMcpPrecision(repoRoot) {
12451245
]);
12461246
}
12471247

1248+
/**
1249+
* wp-env guidance verified against @wordpress/env 11.16.0.
1250+
*
1251+
* Upstream's skill (#38) followed the package README, which lags the code.
1252+
* Each exclusion below is a command 11.16.0 rejects: the `composer` container
1253+
* was removed, `wp-env run` hands argv to `docker compose exec` without a
1254+
* shell (so one quoted command string is looked up as a single executable
1255+
* name), the `mariadb:lts` image has no `mysql` binary, and `npx wp-env`
1256+
* resolves the unrelated unscoped `wp-env` npm package when the local install
1257+
* is missing. The router entry is fork-only, so a later upstream merge must
1258+
* not drop it silently.
1259+
*/
1260+
export function assertWpEnvPrecision(repoRoot) {
1261+
requireIncludes(repoRoot, "skills/wp-env/SKILL.md", [
1262+
"verified against @wordpress/env 11.16.0",
1263+
"npm exec --no -- wp-env",
1264+
"wp-env run cli wp rewrite structure /%postname%/",
1265+
"wp-env run mysql mariadb --",
1266+
"`tests-cli`",
1267+
'"testsEnvironment": false',
1268+
"wp-env destroy --force",
1269+
"`lifecycleScripts` are **merged**",
1270+
"Invalid or unrecognized source",
1271+
]);
1272+
requireExcludes(repoRoot, "skills/wp-env/SKILL.md", [
1273+
"`cli`, `composer`",
1274+
'wp-env run cli "wp rewrite structure',
1275+
"wp-env run mysql mysql",
1276+
"# Then use: npx wp-env",
1277+
"run via `npx wp-env`",
1278+
"Could not find a valid source",
1279+
]);
1280+
requireIncludes(repoRoot, "skills/wordpress-router/references/decision-tree.md", [
1281+
"Route → `wp-env`",
1282+
]);
1283+
}
1284+
12481285
/**
12491286
* The 1.9.1 remediation record.
12501287
*
@@ -1297,6 +1334,7 @@ export function runReleaseConformance(repoRoot) {
12971334
assertAiClientConnectorPrecision(repoRoot);
12981335
assertAiPluginPrecision(repoRoot);
12991336
assertAbilitiesApiMcpPrecision(repoRoot);
1337+
assertWpEnvPrecision(repoRoot);
13001338
assertRemediationRelease191(repoRoot);
13011339
assert(
13021340
IMMEDIATE_UNWATCH_PATTERN.test("const unwatch = watch( () => { return cleanup; } );\n// Dispose later.\nunwatch();"),

‎skills/wordpress-router/references/decision-tree.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ Route by intent even if repo kind is broad (like `wp-site`):
4343
- Route → `blueprint`.
4444
- **@wp-playground/cli / server / run-blueprint / build-snapshot / auto-mount / Xdebug**
4545
- Route → `wp-playground`, then read `references/cli.md` or `references/debugging.md`.
46-
- **playground.wordpress.net / Blueprint Editor / share links / browser-only Playground**
46+
- **playground.wordpress.net / Blueprint Editor / share links / browser-only Playground / WebMCP site tools / Playground MCP / `window.playgroundSites`**
4747
- Route → `wp-playground`, then read `references/website.md`.
48+
- **wp-env / @wordpress/env / .wp-env.json / Docker-based local WordPress / `wp-env run`**
49+
- Route → `wp-env`. For a quick, disposable local site without Docker, route → `wp-playground` instead.
4850
- **Blocks / block.json / registerBlockType / attributes / save serialization**
4951
- Route → `wp-block-development`.
5052
- **Block patterns / patterns/*.php / register_block_pattern / starter page or template patterns**
@@ -59,8 +61,8 @@ Route by intent even if repo kind is broad (like `wp-site`):
5961
- Route → `wp-wpcli-and-ops`.
6062
- **Build tooling / @wordpress/scripts / webpack / Vite / npm scripts**
6163
- Route → `wp-build-tooling` (planned).
62-
- **Testing / PHPUnit / wp-env / Playwright**
63-
- Route → `wp-testing` (planned).
64+
- **Testing / PHPUnit / Playwright**
65+
- Route → `wp-testing` (planned). To run PHPUnit inside a wp-env environment, route → `wp-env`.
6466
- **PHPStan / static analysis / phpstan.neon / phpstan-baseline.neon**
6567
- Route → `wp-phpstan`.
6668
- **Performance / caching / query profiling / editor slowness**

‎skills/wp-env/SKILL.md‎

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
---
22
name: wp-env
3-
description: "Use when setting up, configuring, or troubleshooting local WordPress development environments with @wordpress/env (wp-env). Triggers on mentions of wp-env, local WordPress development, Docker-based WordPress, or requests to start/stop/configure a local WordPress instance."
4-
compatibility: "Targets WordPress 7.0+ (PHP 7.4.0+). Requires Docker and Node.js 18.12+."
3+
description: "Use when setting up, configuring, or troubleshooting local WordPress development environments with @wordpress/env (wp-env). Triggers on mentions of wp-env, local WordPress development, Docker-based WordPress, or requests to start/stop/configure a local WordPress instance. For a quick, disposable local site without Docker, use wp-playground instead."
4+
compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Requires Docker (default runtime) and Node.js 18.12+; verified against @wordpress/env 11.16.0."
5+
license: GPL-2.0-or-later
56
---
67

78
# @wordpress/env (wp-env)
89

910
Zero-config, Docker-based local WordPress development environment for plugins, themes, and core.
1011

12+
Verified against `@wordpress/env` 11.16.0. When exact flags matter, check `wp-env --version` and `wp-env <command> --help`.
13+
1114
## When to use
1215

1316
- User asks to set up a local WordPress development environment
@@ -43,9 +46,11 @@ npm -g install @wordpress/env
4346

4447
# Or project-local
4548
npm i @wordpress/env --save-dev
46-
# Then use: npx wp-env start
49+
# Then use: npm exec --no -- wp-env start
4750
```
4851

52+
Run a project-local install with `npm exec --no -- wp-env` (or a `package.json` script), not `npx wp-env`. If the local install is missing, `npx wp-env` fetches the unscoped `wp-env` package from the registry, which is not `@wordpress/env`, and a non-interactive shell installs it without asking. `--no` makes npm fail instead.
53+
4954
### 2. Start the environment
5055

5156
```sh
@@ -61,7 +66,9 @@ Common start options:
6166
- `wp-env start --update` -- pull latest sources and reconfigure
6267
- `wp-env start --xdebug` -- enable Xdebug (debug mode)
6368
- `wp-env start --xdebug=profile,trace` -- multiple Xdebug modes
64-
- `wp-env start --auto-port` -- find available ports when defaults are busy
69+
- `wp-env start --auto-port` -- find available ports when defaults are busy (ignored when `CI` is set)
70+
71+
By default `start` also creates a separate tests environment (port 8889, `tests-*` containers) and prints a deprecation warning. Add `"testsEnvironment": false` to `.wp-env.json` to start only the development environment; for an isolated test site, run a second environment from its own config file with `wp-env start --config=<file>`.
6572

6673
### 3. Auto-detection (no config file)
6774

@@ -112,11 +119,11 @@ Place at the project root. All fields are optional.
112119
| ZIP URL | `"https://downloads.wordpress.org/plugin/akismet.zip"` |
113120
| Git SSH | `"ssh://user@host/repo.git#ref"` |
114121

115-
**GOTCHA:** WordPress.org plugin/theme slugs (bare names like `"akismet"`) do NOT work. Use the full ZIP URL.
122+
**GOTCHA:** WordPress.org plugin/theme slugs (bare names like `"akismet"`) do NOT work. Use the full ZIP URL. Relative local paths must start with `.` (`"."`, `"./path"`, `"../path"`): `"plugins/my-plugin"` is parsed as the GitHub repository `plugins/my-plugin`.
116123

117124
#### Local overrides with `.wp-env.override.json`
118125

119-
Create `.wp-env.override.json` next to `.wp-env.json` for personal settings (gitignored). Only `config` and `mappings` are **merged** -- all other fields (including `plugins` and `themes` arrays) **fully replace** the base.
126+
Create `.wp-env.override.json` next to `.wp-env.json` for personal settings (gitignored). `config`, `mappings`, and `lifecycleScripts` are **merged** key by key -- all other fields (including `plugins` and `themes` arrays) **fully replace** the base.
120127

121128
### 5. Run commands in containers
122129

@@ -125,7 +132,7 @@ Create `.wp-env.override.json` next to `.wp-env.json` for personal settings (git
125132
wp-env run cli wp user list
126133
wp-env run cli wp plugin list
127134
wp-env run cli wp option update blogname "My Site"
128-
wp-env run cli "wp rewrite structure /%postname%/"
135+
wp-env run cli wp rewrite structure /%postname%/
129136

130137
# Run commands in a specific directory
131138
wp-env run cli --env-cwd=wp-content/plugins/my-plugin composer install
@@ -137,10 +144,12 @@ wp-env run cli --env-cwd=wp-content/plugins/my-plugin vendor/bin/phpunit
137144
wp-env run cli php -- --version
138145

139146
# MySQL access
140-
wp-env run mysql mysql -- --user=root --password=password wordpress
147+
wp-env run mysql mariadb -- --user=root --password=password wordpress
141148
```
142149

143-
Available containers: `mysql`, `wordpress`, `cli`, `composer`, `phpmyadmin`.
150+
`wp-env run` hands each argument straight to `docker compose exec` without a shell. Never wrap the whole command in one quoted string: `wp-env run cli "wp user list"` fails with `executable file not found in $PATH`. Quote only individual arguments that contain spaces. The database image is `mariadb:lts`, which ships a `mariadb` client but no `mysql` binary.
151+
152+
Available containers: `mysql`, `wordpress`, `cli`, and `phpmyadmin` (only when enabled), plus `tests-mysql`, `tests-wordpress`, and `tests-cli` while the tests environment is on. The `composer` and `phpunit` containers were removed; run those tools in `cli`.
144153

145154
### 6. Manage the environment
146155

@@ -152,10 +161,12 @@ wp-env logs # Stream PHP/Docker logs
152161
wp-env logs --no-watch # Print logs and exit
153162
wp-env status # Show URLs, ports, config
154163
wp-env status --json # Machine-readable status
155-
wp-env cleanup # Remove containers/volumes (keep images)
156-
wp-env destroy # Remove everything including images
164+
wp-env cleanup --force # Remove containers/volumes (keep images)
165+
wp-env destroy --force # Remove everything including images
157166
```
158167

168+
`cleanup` and `destroy` delete the site's database and content. Without `--force` they wait for an interactive confirmation that a non-interactive agent shell cannot answer, so get the user's go-ahead first and then pass `--force`.
169+
159170
### 7. Xdebug setup
160171

161172
```sh
@@ -200,13 +211,13 @@ IDE listens on port **9003**. VS Code `launch.json` needs:
200211
| "Cannot connect to Docker daemon" | Docker not running | Start Docker Desktop |
201212
| "Port 8888 already in use" | Port conflict | Use `--auto-port` or set custom `port` in `.wp-env.json` |
202213
| Plugin not appearing | Missing `Plugin Name:` header in main PHP file | Add standard plugin header comment |
203-
| "Could not find a valid source" | Invalid source string in config | Use full ZIP URL for wp.org plugins, not bare slugs |
204-
| Stale environment after source changes | Cached Docker volumes | `wp-env start --update` or `wp-env destroy && wp-env start` |
205-
| White screen / PHP errors | Corrupted database | `wp-env reset all && wp-env start` |
206-
| Override not taking effect | Wrong merge behavior | `plugins`/`themes` in override **replace** base arrays; only `config`/`mappings` merge |
207-
| Tests environment not accessible | Wrong port | Test environment runs on port 8889 by default |
214+
| `Invalid or unrecognized source: "<value>"` | Bare wp.org slug, or a relative path without a leading `.` | Use the full ZIP URL for wp.org plugins; prefix local paths with `./` |
215+
| Stale environment after source changes | Cached Docker volumes | `wp-env start --update`; if that fails and the user accepts losing local data, `wp-env destroy --force` then `wp-env start` |
216+
| White screen / PHP errors | PHP fatal in the code under development, or a corrupted database | Check `wp-env logs --no-watch` first; if the database is the cause, `wp-env reset all && wp-env start` (deletes all site content) |
217+
| Override not taking effect | Wrong merge behavior | `plugins`/`themes` in override **replace** base arrays; only `config`/`mappings`/`lifecycleScripts` merge |
218+
| Tests environment not accessible | Wrong port, or `"testsEnvironment": false` | It runs on port 8889 unless disabled; the separate tests environment is deprecated, so prefer a second config started with `--config` |
208219
| Xdebug not connecting | IDE not listening or wrong port | Ensure IDE listens on port 9003 with correct `pathMappings` |
209-
| npm global install permission error | Node installed to a system path | Use `nvm`, or install locally: `npm i -D @wordpress/env` and run via `npx wp-env` |
220+
| npm global install permission error | Node installed to a system path | Use `nvm`, or install locally: `npm i -D @wordpress/env` and run via `npm exec --no -- wp-env` |
210221

211222
## Escalation
212223

‎skills/wp-playground/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ This is a thin routing wrapper. Use it to pick the right Playground workflow, th
5050

5151
## Escalation
5252

53-
- If the task needs native PHP extensions, external database access, persistence, or production-like infrastructure that Playground cannot provide, use a full WordPress stack such as wp-env, Docker, or the project-provided environment.
53+
- If the task needs native PHP extensions, external database access, persistence, or production-like infrastructure that Playground cannot provide, use a full WordPress stack such as wp-env (see the `wp-env` skill), Docker, or the project-provided environment.

0 commit comments

Comments
 (0)