wordpress-agent-kit 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wp-playground
3
- description: "Use for WordPress Playground workflows: fast disposable WP instances in the browser or locally via @wp-playground/cli (server, run-blueprint, build-snapshot), auto-mounting plugins/themes, switching WP/PHP versions, blueprints, and debugging (Xdebug)."
3
+ description: "Use for WordPress Playground workflows: fast disposable WP instances in the browser or locally via @wp-playground/cli (server, run-blueprint, build-snapshot), auto-mounting plugins/themes, switching WP/PHP versions, blueprints, PHPUnit testing, E2E Playwright testing, programmatic runCLI API, and debugging (Xdebug)."
4
4
  license: GPL-2.0-or-later
5
5
  compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Playground CLI requires Node.js 20.18+; runs WP in WebAssembly with SQLite."
6
6
  ---
@@ -14,6 +14,9 @@ compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Playground CLI requires No
14
14
  - Build a reproducible snapshot of a site for sharing or CI.
15
15
  - Switch WP/PHP versions quickly to reproduce issues.
16
16
  - Debug plugin/theme code with Xdebug in an isolated Playground.
17
+ - Run PHPUnit tests without a local database (no Docker, no MySQL).
18
+ - Write E2E Playwright tests against a real WordPress instance.
19
+ - Automate Playground in CI/CD pipelines via the programmatic `runCLI` API.
17
20
 
18
21
  ## Inputs required
19
22
 
@@ -82,6 +85,134 @@ npx @wp-playground/cli@latest build-snapshot --blueprint=<file> --outfile=./site
82
85
  - Query: `https://playground.wordpress.net/?blueprint-url=<public-url-or-zip>`
83
86
  - Use the live Blueprint Editor (playground.wordpress.net) to author blueprints with schema help; paste JSON and copy a shareable link.
84
87
 
88
+ ### 8) PHPUnit testing (no database required)
89
+
90
+ Run PHPUnit inside Playground — every run starts with a clean WordPress install, fully isolated.
91
+
92
+ Plugin:
93
+ ```bash
94
+ npx @wp-playground/cli@latest php \
95
+ --auto-mount \
96
+ -- \
97
+ /wordpress/wp-content/plugins/MY_PLUGIN/vendor/bin/phpunit \
98
+ -c /wordpress/wp-content/plugins/MY_PLUGIN/phpunit.xml.dist
99
+ ```
100
+
101
+ Theme (replace `plugins/` with `themes/`):
102
+ ```bash
103
+ npx @wp-playground/cli@latest php \
104
+ --auto-mount \
105
+ -- \
106
+ /wordpress/wp-content/themes/MY_THEME/vendor/bin/phpunit \
107
+ -c /wordpress/wp-content/themes/MY_THEME/phpunit.xml.dist
108
+ ```
109
+
110
+ - Requires PHPUnit installed via Composer in the project (`composer require --dev phpunit/phpunit`).
111
+ - `--auto-mount` maps the current directory to the correct WP content path automatically.
112
+ - Use `--php=8.1 --wp=6.5` flags to test against specific versions (PHP 7.4–8.5 supported).
113
+ - Explicit mount: `--mount=.:/wordpress/wp-content/plugins/MY_PLUGIN`.
114
+
115
+ ### 9) E2E testing with Playwright
116
+
117
+ Use `runCLI` from `@wp-playground/cli` to start a Playground server programmatically in Playwright tests. No Docker, no database.
118
+
119
+ Install:
120
+ ```bash
121
+ npm install --save-dev @playwright/test @wp-playground/cli
122
+ npx playwright install chromium
123
+ ```
124
+
125
+ Minimal `playwright.config.ts`:
126
+ ```ts
127
+ import { defineConfig } from '@playwright/test';
128
+ export default defineConfig({
129
+ testDir: './tests/e2e',
130
+ fullyParallel: false,
131
+ workers: 1, // prevent port conflicts
132
+ timeout: 120_000, // WP boot takes time
133
+ expect: { timeout: 30_000 },
134
+ use: { screenshot: 'only-on-failure', trace: 'on-first-retry' },
135
+ });
136
+ ```
137
+
138
+ First test (`tests/e2e/plugin.spec.ts`):
139
+ ```ts
140
+ import { test, expect } from '@playwright/test';
141
+ import { runCLI } from '@wp-playground/cli';
142
+
143
+ let cli: Awaited<ReturnType<typeof runCLI>>;
144
+
145
+ test.beforeAll(async () => {
146
+ cli = await runCLI({
147
+ command: 'server',
148
+ blueprint: {
149
+ preferredVersions: { php: '8.3', wp: 'latest' },
150
+ login: true,
151
+ },
152
+ });
153
+ });
154
+
155
+ test.afterAll(async () => { await cli?.server?.close(); });
156
+
157
+ test('dashboard loads', async ({ page }) => {
158
+ await page.goto(`${cli.serverUrl}/wp-admin/`);
159
+ await expect(page.locator('#wpbody-content')).toBeVisible();
160
+ });
161
+ ```
162
+
163
+ Mount a local plugin:
164
+ ```ts
165
+ cli = await runCLI({
166
+ command: 'server',
167
+ mount: { './': '/wordpress/wp-content/plugins/my-plugin' },
168
+ blueprint: {
169
+ preferredVersions: { php: '8.3', wp: 'latest' },
170
+ login: true,
171
+ steps: [{ step: 'activatePlugin', pluginPath: 'my-plugin/my-plugin.php' }],
172
+ },
173
+ });
174
+ ```
175
+
176
+ Locator priority (most to least preferred):
177
+ 1. `page.getByRole()` — buttons, headings, links, inputs
178
+ 2. `page.getByLabel()` — labeled form fields
179
+ 3. `page.getByText()` — visible text
180
+ 4. `page.getByTestId()` — your own `data-testid` attributes
181
+ 5. `page.locator()` — CSS/XPath last resort (WP core layout elements like `#wpadminbar`)
182
+
183
+ Version matrix pattern:
184
+ ```ts
185
+ const matrix = [{ php: '8.1', wp: '6.5' }, { php: '8.3', wp: 'latest' }];
186
+ for (const { php, wp } of matrix) {
187
+ test.describe(`PHP ${php} + WP ${wp}`, () => {
188
+ // ... beforeAll/afterAll with those versions
189
+ });
190
+ }
191
+ ```
192
+
193
+ CI (GitHub Actions): see `references/e2e-playwright.md`.
194
+
195
+ ### 10) Programmatic `runCLI` API (scripts / Vitest integration)
196
+
197
+ ```ts
198
+ import { runCLI } from '@wp-playground/cli';
199
+
200
+ const server = await runCLI({
201
+ command: 'server',
202
+ php: '8.3',
203
+ wp: 'latest',
204
+ login: true,
205
+ mount: [{ hostPath: './my-plugin', vfsPath: '/wordpress/wp-content/plugins/my-plugin' }],
206
+ blueprint: { steps: [{ step: 'activatePlugin', pluginPath: 'my-plugin/plugin.php' }] },
207
+ });
208
+
209
+ // server.serverUrl — the base URL
210
+ // server.server — the HTTP server instance (call .close() in afterEach)
211
+ // server[Symbol.asyncDispose]() — cleanup in Vitest afterEach
212
+ ```
213
+
214
+ Use `wordpressInstallMode: 'do-not-attempt-installing'` + `skipSqliteSetup: true` when testing pure PHP with no WordPress overhead.
215
+
85
216
  ## Verification
86
217
 
87
218
  - Verify mounted code is active (plugin listed/active; theme selected).
@@ -0,0 +1,115 @@
1
+ # E2E Testing with Playwright + WordPress Playground
2
+
3
+ ## Install
4
+
5
+ ```bash
6
+ npm install --save-dev @playwright/test @wp-playground/cli
7
+ npx playwright install chromium
8
+ ```
9
+
10
+ ## playwright.config.ts
11
+
12
+ ```ts
13
+ import { defineConfig } from '@playwright/test';
14
+ export default defineConfig({
15
+ testDir: './tests/e2e',
16
+ fullyParallel: false,
17
+ forbidOnly: !!process.env.CI,
18
+ retries: process.env.CI ? 2 : 0,
19
+ workers: 1,
20
+ reporter: 'html',
21
+ timeout: 120_000,
22
+ expect: { timeout: 30_000 },
23
+ use: { screenshot: 'only-on-failure', trace: 'on-first-retry' },
24
+ });
25
+ ```
26
+
27
+ ## Server lifecycle
28
+
29
+ **Shared** (faster, tests can affect each other — use for read-only tests):
30
+ ```ts
31
+ test.beforeAll(async () => { cli = await runCLI({ command: 'server', blueprint }); });
32
+ test.afterAll(async () => { await cli?.server?.close(); });
33
+ ```
34
+
35
+ **Per-test** (isolated, slower — use when tests modify state):
36
+ ```ts
37
+ test.beforeEach(async () => { cli = await runCLI({ command: 'server', blueprint }); });
38
+ test.afterEach(async () => { await cli?.server?.close(); });
39
+ ```
40
+
41
+ ## Blueprint fixtures
42
+
43
+ Installing from wordpress.org:
44
+ ```ts
45
+ steps: [{ step: 'installPlugin', pluginData: { resource: 'wordpress.org/plugins', slug: 'contact-form-7' } }]
46
+ ```
47
+
48
+ Creating content:
49
+ ```ts
50
+ steps: [{ step: 'runPHP', code: `<?php require '/wordpress/wp-load.php'; wp_insert_post([...]);` }]
51
+ ```
52
+
53
+ ## WordPress-specific locator guidance
54
+
55
+ - `page.getByRole('button', { name: 'Save Changes' })` — works for standard WP buttons
56
+ - `page.getByLabel('API Key')` — works for labeled form fields
57
+ - `page.locator('#wpadminbar')` — CSS required for WP core layout elements (no ARIA)
58
+ - Add `data-testid` to your own plugin markup for stable selectors
59
+ - Run `npx playwright codegen localhost:9400/wp-admin/` to auto-generate locators
60
+
61
+ ## Page Object Model
62
+
63
+ ```ts
64
+ // tests/e2e/pages/plugin-settings.ts
65
+ export class PluginSettingsPage {
66
+ constructor(readonly page: Page) {}
67
+ async goto(baseUrl: string) { await this.page.goto(`${baseUrl}/wp-admin/options-general.php?page=my-plugin`); }
68
+ async setApiKey(key: string) {
69
+ await this.page.getByLabel('API Key').fill(key);
70
+ await this.page.getByRole('button', { name: 'Save Changes' }).click();
71
+ }
72
+ async expectSaved() { await expect(this.page.getByText('Settings saved')).toBeVisible(); }
73
+ }
74
+ ```
75
+
76
+ ## GitHub Actions CI
77
+
78
+ ```yaml
79
+ name: E2E Tests
80
+ on:
81
+ push: { branches: [main] }
82
+ pull_request: { branches: [main] }
83
+ jobs:
84
+ e2e:
85
+ runs-on: ubuntu-latest
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ - uses: actions/setup-node@v4
89
+ with: { node-version: 20, cache: 'npm' }
90
+ - run: npm ci
91
+ - uses: actions/cache@v4
92
+ id: playwright-cache
93
+ with:
94
+ path: ~/.cache/ms-playwright
95
+ key: playwright-${{ hashFiles('package-lock.json') }}
96
+ - if: steps.playwright-cache.outputs.cache-hit != 'true'
97
+ run: npx playwright install chromium --with-deps
98
+ - run: npx playwright test
99
+ - uses: actions/upload-artifact@v4
100
+ if: ${{ !cancelled() }}
101
+ with: { name: playwright-report, path: playwright-report/, retention-days: 30 }
102
+ ```
103
+
104
+ ## Troubleshooting
105
+
106
+ - **Timeout errors** — increase `timeout` in config; CI needs 120–180s
107
+ - **Port conflicts** — don't hardcode ports; use `cli.serverUrl`
108
+ - **Browser not found** — run `npx playwright install chromium`
109
+ - **Passes locally, fails CI** — increase timeouts, ensure `workers: 1`
110
+ - **Debug** — `npx playwright test --debug` or `--ui` for interactive mode
111
+
112
+ ## Docs
113
+
114
+ - https://wordpress.github.io/wordpress-playground/guides/e2e-testing-with-playwright
115
+ - https://wordpress.github.io/wordpress-playground/guides/programmatic-playground-cli
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: wp-wpengine
3
+ description: "Optional: Use for WP Engine hosting workflows — SSH-based git push to WP Engine environments, managing installs/domains/cache/backups via the wpe-labs Claude Code skills, and WP Engine API access. Requires WPE_USERNAME and WPE_PASSWORD env vars."
4
+ license: GPL-2.0-or-later
5
+ optional: true
6
+ ---
7
+
8
+ # WP Engine
9
+
10
+ ## When to use
11
+
12
+ - Deploy WordPress code to a WP Engine environment via `git push`.
13
+ - Manage WP Engine installs, domains, cache, backups, or users through natural language.
14
+ - Generate monthly usage/bandwidth reports across WP Engine accounts.
15
+ - Manage LargeFS media offload configuration.
16
+
17
+ ## Prerequisites
18
+
19
+ - SSH key for WP Engine git push stored in 1Password (`Employee` vault, item `wpengine_ed25519`).
20
+ - WP Engine API credentials in 1Password (`Employee` vault, item `WP Engine API`).
21
+ - `op` CLI authenticated (`op whoami` works).
22
+ - The `wpe-labs` Claude Code skills installed (`~/.claude/skills/wpe-labs:*`).
23
+
24
+ ## Procedure
25
+
26
+ ### 1) First-time SSH setup on a new machine
27
+
28
+ Pull the private key from 1Password and configure SSH:
29
+
30
+ ```bash
31
+ op read "op://Employee/wpengine_ed25519/private key" > ~/.ssh/wpengine_ed25519
32
+ chmod 600 ~/.ssh/wpengine_ed25519
33
+ ssh-keyscan git.wpengine.com >> ~/.ssh/known_hosts
34
+ ```
35
+
36
+ Add to `~/.ssh/config` (before any `Host *` block):
37
+ ```
38
+ Host git.wpengine.com
39
+ User git
40
+ IdentityFile ~/.ssh/wpengine_ed25519
41
+ IdentitiesOnly yes
42
+ ```
43
+
44
+ Verify:
45
+ ```bash
46
+ ssh git@git.wpengine.com info
47
+ # Expected: hello <username> / R W <install-name>
48
+ ```
49
+
50
+ The public key is already registered on WP Engine — no portal action needed on new machines.
51
+
52
+ ### 2) Add a WP Engine git remote
53
+
54
+ Find the remote URL on the WP Engine portal: `https://my.wpengine.com/installs/<ENV>/git_push`
55
+
56
+ ```bash
57
+ git remote add wpengine git@git.wpengine.com:<install-name>.git
58
+ # Example for staging:
59
+ git remote add wpengine-staging git@git.wpengine.com:<install-name>stg.git
60
+ ```
61
+
62
+ ### 3) Deploy via git push
63
+
64
+ ```bash
65
+ git push wpengine main
66
+ ```
67
+
68
+ - WP Engine deploys the pushed branch automatically.
69
+ - Only the WordPress files are pushed (not `node_modules`, build artifacts, etc.).
70
+ - After push, WP Engine may take 1–2 min to propagate the deploy.
71
+
72
+ ### 4) wpe-labs skills (natural language management)
73
+
74
+ Load API credentials, then use any `/wpe-labs:*` skill:
75
+
76
+ ```bash
77
+ # Load credentials from 1Password for the session
78
+ eval $(op run --env-file ~/.config/op-ssh/.env.1pass -- env | grep ^WPE | sed 's/^/export /')
79
+ ```
80
+
81
+ Available skills:
82
+
83
+ | Skill | What it does | Risk |
84
+ |---|---|---|
85
+ | `/wpe-labs:account-usage` | Bandwidth, visits, storage across accounts | 🟢 Read-only |
86
+ | `/wpe-labs:monthly-report` | Client-ready monthly usage report | 🟢 Read-only |
87
+ | `/wpe-labs:backups` | On-demand backups + progress monitoring | 🟡 Write |
88
+ | `/wpe-labs:cache` | Purge object/page/CDN cache | 🟡 Write |
89
+ | `/wpe-labs:users` | List, invite, update roles, remove users | 🟡/🔴 |
90
+ | `/wpe-labs:domains` | Manage domains, DNS, SSL | 🟡/🔴 |
91
+ | `/wpe-labs:installs` | List, create, copy WordPress installs | 🟡/🔴 |
92
+ | `/wpe-labs:offload` | LargeFS media offload config | 🟡 Write |
93
+
94
+ Example prompts:
95
+ ```
96
+ /wpe-labs:account-usage which accounts are closest to their bandwidth limit?
97
+ /wpe-labs:cache purge all cache for uofdev production
98
+ /wpe-labs:backups back up uofdev production before deployment
99
+ /wpe-labs:installs copy uofdev production to staging
100
+ /wpe-labs:monthly-report last month
101
+ ```
102
+
103
+ ### 5) Re-installing wpe-labs skills
104
+
105
+ ```bash
106
+ curl -fsSL https://raw.githubusercontent.com/wpengine/wpe-labs-platform-skills/main/install.sh | bash
107
+ ```
108
+
109
+ ## Verification
110
+
111
+ - SSH: `ssh git@git.wpengine.com info` — should return `hello <username> / R W <install>`
112
+ - API: `op run --env-file ~/.config/op-ssh/.env.1pass -- bash -c 'curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" https://api.wpengineapi.com/v1/user | jq .email'`
113
+
114
+ ## Failure modes
115
+
116
+ - **SSH: Host key verification failed** — re-run `ssh-keyscan git.wpengine.com >> ~/.ssh/known_hosts`
117
+ - **SSH: Permission denied** — confirm the key is at `~/.ssh/wpengine_ed25519` with `chmod 600`
118
+ - **git push rejected** — verify the remote URL matches the install name exactly
119
+ - **wpe-labs: 401 Unauthorized** — regenerate API credentials at `https://my.wpengine.com/api_access` and update the `WP Engine API` item in 1Password
120
+ - **wpe-labs: storage shows zero** — ask Claude to "refresh storage" (async recalculation, ~30–60s)
121
+
122
+ ## References
123
+
124
+ - WP Engine git push portal: `https://my.wpengine.com/installs/<ENV>/git_push`
125
+ - WP Engine API access: `https://my.wpengine.com/api_access`
126
+ - wpe-labs skills source: `https://github.com/wpengine/wpe-labs-platform-skills`
127
+ - SSH setup log (first machine): gist `602d6a16ddfea438c0611a8e5cc31d5e`
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg?style=flat-square)](LICENSE)
4
4
  [![TypeScript](https://img.shields.io/badge/Written%20in-TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
5
- [![Version](https://img.shields.io/badge/version-0.3.2-blue?style=flat-square)](package.json)
5
+ [![Version](https://img.shields.io/badge/version-0.4.0-blue?style=flat-square)](package.json)
6
6
  [![Node](https://img.shields.io/badge/node-%3E%3D20.18-green?style=flat-square)](package.json)
7
7
  [![CI](https://img.shields.io/badge/CI-passing-brightgreen?style=flat-square)](.github/workflows/ci.yml)
8
8
 
9
- **WordPress-focused AI agent starter kit** for GitHub Copilot, Cursor, Claude, and Pi Coding Agent. Installs 13 specialized WordPress agent skills, an agent persona, workflow instructions, and AGENTS.md configuration — everything an AI coding agent needs to build WordPress plugins, themes, and blocks correctly.
9
+ **WordPress-focused AI agent starter kit** for GitHub Copilot, Cursor, Claude, and Pi Coding Agent. Installs 17 specialized WordPress agent skills (plus an optional WP Engine skill), an agent persona, workflow instructions, and AGENTS.md configuration — everything an AI coding agent needs to build WordPress plugins, themes, and blocks correctly.
10
10
 
11
11
  Maintained by [Kyle Brodeur](https://brodeur.me).
12
12
 
@@ -40,7 +40,7 @@ my-plugin/
40
40
  │ ├── instructions/
41
41
  │ │ └── wordpress-workflow.instructions.md
42
42
  │ ├── prompts/
43
- │ └── skills/ # 17 WordPress skills
43
+ │ └── skills/ # 17 WordPress skills + 1 optional
44
44
  │ ├── wp-project-triage/ # Project detection
45
45
  │ ├── wp-plugin-development/ # Plugin architecture
46
46
  │ ├── wp-block-development/ # Gutenberg blocks
@@ -51,9 +51,10 @@ my-plugin/
51
51
  │ ├── wp-performance/ # Performance profiling
52
52
  │ ├── wp-phpstan/ # Static analysis
53
53
  │ ├── wp-wpcli-and-ops/ # WP-CLI operations
54
- │ ├── wp-playground/ # Testing environments
54
+ │ ├── wp-playground/ # Testing environments (PHPUnit, Playwright, CI)
55
55
  │ ├── wpds/ # Design system
56
- └── wordpress-router/ # Repo classification
56
+ ├── wordpress-router/ # Repo classification
57
+ │ └── wp-wpengine/ # (optional) WP Engine hosting + git push
57
58
  └── .wp-agent-kit-manifest.github.json # Safe-update tracking
58
59
  ```
59
60
 
@@ -227,7 +228,7 @@ console.log(triage.data.project.primary); // "plugin"
227
228
 
228
229
  ## Skills Reference
229
230
 
230
- All 13 skills follow the [AgentSkills.io](https://agentskills.io) specification:
231
+ All 17 skills follow the [AgentSkills.io](https://agentskills.io) specification. Skills in `skills-custom/` are project-specific (not from upstream) and survive `sync-skills`:
231
232
 
232
233
  | Skill | When to Use |
233
234
  |-------|------------|
@@ -243,10 +244,12 @@ All 13 skills follow the [AgentSkills.io](https://agentskills.io) specification:
243
244
  | `wp-performance` | Profile and optimize WordPress performance |
244
245
  | `wp-phpstan` | Configure and run PHPStan static analysis |
245
246
  | `wp-wpcli-and-ops` | WP-CLI commands, automation, multisite operations |
246
- | `wp-playground` | Test in disposable WordPress Playground instances |
247
+ | `wp-playground` | Test with disposable Playground instances; PHPUnit, Playwright E2E, CI |
247
248
  | `blueprint` | Write and edit WordPress Playground blueprint JSON |
248
249
  | `wpds` | Build UIs with the WordPress Design System |
249
250
  | `wp-plugin-directory-guidelines` | GPL compliance, naming, slug rules for WP.org submission |
251
+ | `wordpress-router` | Route/classify repository type and select appropriate skills |
252
+ | **`wp-wpengine`** *(optional, custom)* | **WP Engine git push, install/domain/cache/backup management via wpe-labs skills** |
250
253
 
251
254
  ---
252
255
 
package/dist/lib/api.js CHANGED
@@ -264,6 +264,19 @@ export async function syncSkillsApi(options = {}) {
264
264
  fs.cpSync(sourceSkills, targetSkills, { recursive: true });
265
265
  skillsSynced = fs.readdirSync(targetSkills).length;
266
266
  }
267
+ // Merge custom skills (skills-custom/) — these are not part of the upstream
268
+ // WordPress/agent-skills repo and survive upstream syncs.
269
+ const customSkillsDir = path.join(PACKAGE_ROOT, 'skills-custom');
270
+ if (fs.existsSync(customSkillsDir)) {
271
+ for (const skillName of fs.readdirSync(customSkillsDir)) {
272
+ const src = path.join(customSkillsDir, skillName);
273
+ const dest = path.join(targetSkills, skillName);
274
+ if (fs.statSync(src).isDirectory()) {
275
+ fs.cpSync(src, dest, { recursive: true });
276
+ skillsSynced++;
277
+ }
278
+ }
279
+ }
267
280
  return { success: true, skillsSynced, method };
268
281
  });
269
282
  return formatter.success({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wordpress-agent-kit",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "WordPress-focused AGENTS.md + Agent Skills starter kit for AI coding agents.",
5
5
  "license": "GPL-2.0-or-later",
6
6
  "author": "Kyle Brodeur <kyle@brodeur.me> (https://brodeur.me)",
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: wp-wpengine
3
+ description: "Optional: Use for WP Engine hosting workflows — SSH-based git push to WP Engine environments, managing installs/domains/cache/backups via the wpe-labs Claude Code skills, and WP Engine API access. Requires WPE_USERNAME and WPE_PASSWORD env vars."
4
+ license: GPL-2.0-or-later
5
+ optional: true
6
+ ---
7
+
8
+ # WP Engine
9
+
10
+ ## When to use
11
+
12
+ - Deploy WordPress code to a WP Engine environment via `git push`.
13
+ - Manage WP Engine installs, domains, cache, backups, or users through natural language.
14
+ - Generate monthly usage/bandwidth reports across WP Engine accounts.
15
+ - Manage LargeFS media offload configuration.
16
+
17
+ ## Prerequisites
18
+
19
+ - SSH key for WP Engine git push stored in 1Password (`Employee` vault, item `wpengine_ed25519`).
20
+ - WP Engine API credentials in 1Password (`Employee` vault, item `WP Engine API`).
21
+ - `op` CLI authenticated (`op whoami` works).
22
+ - The `wpe-labs` Claude Code skills installed (`~/.claude/skills/wpe-labs:*`).
23
+
24
+ ## Procedure
25
+
26
+ ### 1) First-time SSH setup on a new machine
27
+
28
+ Pull the private key from 1Password and configure SSH:
29
+
30
+ ```bash
31
+ op read "op://Employee/wpengine_ed25519/private key" > ~/.ssh/wpengine_ed25519
32
+ chmod 600 ~/.ssh/wpengine_ed25519
33
+ ssh-keyscan git.wpengine.com >> ~/.ssh/known_hosts
34
+ ```
35
+
36
+ Add to `~/.ssh/config` (before any `Host *` block):
37
+ ```
38
+ Host git.wpengine.com
39
+ User git
40
+ IdentityFile ~/.ssh/wpengine_ed25519
41
+ IdentitiesOnly yes
42
+ ```
43
+
44
+ Verify:
45
+ ```bash
46
+ ssh git@git.wpengine.com info
47
+ # Expected: hello <username> / R W <install-name>
48
+ ```
49
+
50
+ The public key is already registered on WP Engine — no portal action needed on new machines.
51
+
52
+ ### 2) Add a WP Engine git remote
53
+
54
+ Find the remote URL on the WP Engine portal: `https://my.wpengine.com/installs/<ENV>/git_push`
55
+
56
+ ```bash
57
+ git remote add wpengine git@git.wpengine.com:<install-name>.git
58
+ # Example for staging:
59
+ git remote add wpengine-staging git@git.wpengine.com:<install-name>stg.git
60
+ ```
61
+
62
+ ### 3) Deploy via git push
63
+
64
+ ```bash
65
+ git push wpengine main
66
+ ```
67
+
68
+ - WP Engine deploys the pushed branch automatically.
69
+ - Only the WordPress files are pushed (not `node_modules`, build artifacts, etc.).
70
+ - After push, WP Engine may take 1–2 min to propagate the deploy.
71
+
72
+ ### 4) wpe-labs skills (natural language management)
73
+
74
+ Load API credentials, then use any `/wpe-labs:*` skill:
75
+
76
+ ```bash
77
+ # Load credentials from 1Password for the session
78
+ eval $(op run --env-file ~/.config/op-ssh/.env.1pass -- env | grep ^WPE | sed 's/^/export /')
79
+ ```
80
+
81
+ Available skills:
82
+
83
+ | Skill | What it does | Risk |
84
+ |---|---|---|
85
+ | `/wpe-labs:account-usage` | Bandwidth, visits, storage across accounts | 🟢 Read-only |
86
+ | `/wpe-labs:monthly-report` | Client-ready monthly usage report | 🟢 Read-only |
87
+ | `/wpe-labs:backups` | On-demand backups + progress monitoring | 🟡 Write |
88
+ | `/wpe-labs:cache` | Purge object/page/CDN cache | 🟡 Write |
89
+ | `/wpe-labs:users` | List, invite, update roles, remove users | 🟡/🔴 |
90
+ | `/wpe-labs:domains` | Manage domains, DNS, SSL | 🟡/🔴 |
91
+ | `/wpe-labs:installs` | List, create, copy WordPress installs | 🟡/🔴 |
92
+ | `/wpe-labs:offload` | LargeFS media offload config | 🟡 Write |
93
+
94
+ Example prompts:
95
+ ```
96
+ /wpe-labs:account-usage which accounts are closest to their bandwidth limit?
97
+ /wpe-labs:cache purge all cache for uofdev production
98
+ /wpe-labs:backups back up uofdev production before deployment
99
+ /wpe-labs:installs copy uofdev production to staging
100
+ /wpe-labs:monthly-report last month
101
+ ```
102
+
103
+ ### 5) Re-installing wpe-labs skills
104
+
105
+ ```bash
106
+ curl -fsSL https://raw.githubusercontent.com/wpengine/wpe-labs-platform-skills/main/install.sh | bash
107
+ ```
108
+
109
+ ## Verification
110
+
111
+ - SSH: `ssh git@git.wpengine.com info` — should return `hello <username> / R W <install>`
112
+ - API: `op run --env-file ~/.config/op-ssh/.env.1pass -- bash -c 'curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" https://api.wpengineapi.com/v1/user | jq .email'`
113
+
114
+ ## Failure modes
115
+
116
+ - **SSH: Host key verification failed** — re-run `ssh-keyscan git.wpengine.com >> ~/.ssh/known_hosts`
117
+ - **SSH: Permission denied** — confirm the key is at `~/.ssh/wpengine_ed25519` with `chmod 600`
118
+ - **git push rejected** — verify the remote URL matches the install name exactly
119
+ - **wpe-labs: 401 Unauthorized** — regenerate API credentials at `https://my.wpengine.com/api_access` and update the `WP Engine API` item in 1Password
120
+ - **wpe-labs: storage shows zero** — ask Claude to "refresh storage" (async recalculation, ~30–60s)
121
+
122
+ ## References
123
+
124
+ - WP Engine git push portal: `https://my.wpengine.com/installs/<ENV>/git_push`
125
+ - WP Engine API access: `https://my.wpengine.com/api_access`
126
+ - wpe-labs skills source: `https://github.com/wpengine/wpe-labs-platform-skills`
127
+ - SSH setup log (first machine): gist `602d6a16ddfea438c0611a8e5cc31d5e`