claude-plugin-wordpress-manager 1.8.0 → 1.9.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.
Files changed (28) hide show
  1. package/.claude-plugin/plugin.json +5 -3
  2. package/CHANGELOG.md +27 -0
  3. package/agents/wp-site-manager.md +26 -0
  4. package/docs/plans/2026-02-28-multisite-v1.9.0-design.md +258 -0
  5. package/docs/plans/2026-02-28-multisite-v1.9.0.md +1604 -0
  6. package/package.json +5 -3
  7. package/servers/wp-rest-bridge/build/tools/index.d.ts +260 -0
  8. package/servers/wp-rest-bridge/build/tools/index.js +6 -0
  9. package/servers/wp-rest-bridge/build/tools/multisite-network.d.ts +132 -0
  10. package/servers/wp-rest-bridge/build/tools/multisite-network.js +157 -0
  11. package/servers/wp-rest-bridge/build/tools/multisite-sites.d.ts +150 -0
  12. package/servers/wp-rest-bridge/build/tools/multisite-sites.js +160 -0
  13. package/servers/wp-rest-bridge/build/types.d.ts +13 -0
  14. package/servers/wp-rest-bridge/build/wordpress.d.ts +19 -0
  15. package/servers/wp-rest-bridge/build/wordpress.js +10 -0
  16. package/servers/wp-rest-bridge/build/wpcli.d.ts +23 -0
  17. package/servers/wp-rest-bridge/build/wpcli.js +72 -0
  18. package/skills/wordpress-router/references/decision-tree.md +4 -2
  19. package/skills/wp-multisite/SKILL.md +92 -0
  20. package/skills/wp-multisite/references/domain-mapping.md +70 -0
  21. package/skills/wp-multisite/references/migration-multisite.md +76 -0
  22. package/skills/wp-multisite/references/network-plugins.md +66 -0
  23. package/skills/wp-multisite/references/network-setup.md +69 -0
  24. package/skills/wp-multisite/references/site-management.md +67 -0
  25. package/skills/wp-multisite/references/user-roles.md +73 -0
  26. package/skills/wp-multisite/scripts/multisite_inspect.mjs +160 -0
  27. package/skills/wp-security/SKILL.md +4 -0
  28. package/skills/wp-wpcli-and-ops/SKILL.md +4 -0
@@ -0,0 +1,76 @@
1
+ # Migration: Single-site to Multisite and Back
2
+
3
+ Migrating between single-site and multisite WordPress installations requires careful planning due to database structure differences.
4
+
5
+ ## Single-site to Multisite
6
+
7
+ ### Prerequisites
8
+ - WordPress installed at domain root (not a subdirectory)
9
+ - All plugins deactivated
10
+ - Permalink structure using "pretty permalinks" (not plain)
11
+ - Full database and file backup
12
+
13
+ ### Procedure
14
+
15
+ 1. **Backup**: Full database dump + wp-content directory
16
+ 2. **Deactivate all plugins** via wp-admin or wp-cli
17
+ 3. **Enable multisite**: Add `define('WP_ALLOW_MULTISITE', true);` to wp-config.php
18
+ 4. **Network Setup**: Navigate to Tools > Network Setup, choose sub-directory or sub-domain
19
+ 5. **Apply configuration**: Copy generated code to wp-config.php and .htaccess
20
+ 6. **Re-login**: WordPress redirects to login — sign in as Super Admin
21
+ 7. **Re-activate plugins**: One by one, test each plugin for multisite compatibility
22
+ 8. **Verify**: Check permalink structure, media uploads, and user roles
23
+
24
+ ### What Changes in the Database
25
+
26
+ | Component | Before | After |
27
+ |-----------|--------|-------|
28
+ | Tables | `wp_posts`, `wp_options`, ... | Same (become site 1) |
29
+ | New tables | — | `wp_blogs`, `wp_site`, `wp_sitemeta`, `wp_registration_log`, `wp_signups` |
30
+ | Options | `wp_options` | `wp_options` (site 1) + `wp_sitemeta` (network) |
31
+
32
+ ## Multisite to Single-site
33
+
34
+ This migration is more complex because you need to extract one sub-site from the network.
35
+
36
+ ### Procedure (extract sub-site)
37
+
38
+ 1. **Backup**: Full database dump + wp-content directory
39
+ 2. **Export content**: Use WordPress Export (Tools > Export) on the target sub-site
40
+ 3. **Fresh WordPress install**: Install a clean single-site WordPress
41
+ 4. **Import content**: Use WordPress Importer plugin
42
+ 5. **Copy uploads**: Copy `wp-content/uploads/sites/{blog_id}/` to `wp-content/uploads/`
43
+ 6. **Activate theme and plugins**: Install and activate the same theme and plugins
44
+ 7. **Verify**: Check media URLs, internal links, shortcodes
45
+
46
+ ### Alternative: Direct Database Extraction
47
+
48
+ For large sites where export/import is impractical:
49
+
50
+ 1. Export tables with prefix `wp_{blog_id}_` (e.g., `wp_2_posts`, `wp_2_options`)
51
+ 2. Rename tables to standard prefix (e.g., `wp_2_posts` → `wp_posts`)
52
+ 3. Update `siteurl` and `home` in `wp_options`
53
+ 4. Search-replace old URLs in content
54
+ 5. Remove multisite constants from wp-config.php
55
+ 6. Update .htaccess to standard WordPress rules
56
+
57
+ ## WP-CLI Migration Commands
58
+
59
+ ```bash
60
+ # Export single site from multisite
61
+ wp db export site-backup.sql --url=subsite.example.com
62
+
63
+ # Search-replace URLs after migration
64
+ wp search-replace 'subsite.example.com' 'newdomain.com' --all-tables
65
+
66
+ # Export content as WXR
67
+ wp export --url=subsite.example.com --dir=/tmp/exports/
68
+ ```
69
+
70
+ ## Tips and Gotchas
71
+
72
+ - **Media paths**: Multisite stores uploads in `uploads/sites/{blog_id}/`. After migration to single-site, media URLs need search-replace.
73
+ - **User roles**: Users may have different roles on different sub-sites. When extracting, only the target site's role assignments transfer.
74
+ - **Plugins**: Some plugins store network-wide options in `wp_sitemeta`. These are lost when extracting to single-site.
75
+ - **Test first**: Always perform migration on a staging environment before production.
76
+ - **Backup twice**: Keep backups of both the source (multisite) and target (single-site) before starting.
@@ -0,0 +1,66 @@
1
+ # Network Plugins and Themes
2
+
3
+ In WordPress Multisite, plugins and themes can be managed at the network level (Super Admin) or at the individual site level (Site Admin). Understanding the activation modes prevents conflicts.
4
+
5
+ ## MCP Tools
6
+
7
+ | Tool | Usage |
8
+ |------|-------|
9
+ | `ms_list_network_plugins` | List all plugins with network activation status |
10
+ | `ms_network_activate_plugin` | Activate a plugin across the entire network |
11
+ | `ms_network_deactivate_plugin` | Deactivate a plugin from the entire network |
12
+
13
+ ## Plugin Activation Modes
14
+
15
+ | Mode | Who Controls | Scope | Use Case |
16
+ |------|-------------|-------|----------|
17
+ | Network-activated | Super Admin | All sites | Security plugins, caching, essential functionality |
18
+ | Per-site activated | Site Admin | One site | Site-specific features |
19
+ | Must-use (mu-plugins) | Developer | All sites, always on | Core business logic, cannot be deactivated |
20
+
21
+ ## Procedures
22
+
23
+ ### Network-Activate a Plugin
24
+
25
+ 1. `ms_network_activate_plugin` with the plugin slug
26
+ 2. The plugin immediately activates on ALL sub-sites
27
+ 3. Site Admins cannot deactivate a network-activated plugin
28
+
29
+ ### Network-Deactivate a Plugin
30
+
31
+ 1. `ms_network_deactivate_plugin` with the plugin slug
32
+ 2. The plugin deactivates on ALL sub-sites simultaneously
33
+ 3. Per-site activation state is lost
34
+
35
+ ### Check Plugin Status
36
+
37
+ 1. `ms_list_network_plugins` — returns all plugins with their status
38
+ 2. Look for `network_only: true` in the response for network-activated plugins
39
+
40
+ ## Theme Management
41
+
42
+ Themes in multisite work differently from plugins:
43
+
44
+ | Action | Level | Effect |
45
+ |--------|-------|--------|
46
+ | Network Enable | Super Admin | Theme becomes available for site admins to activate |
47
+ | Network Disable | Super Admin | Theme removed from site admin's theme list |
48
+ | Activate | Site Admin | Theme becomes active for that specific site |
49
+
50
+ A theme must be **network-enabled** before any site admin can use it.
51
+
52
+ ## Must-Use Plugins
53
+
54
+ - Location: `wp-content/mu-plugins/`
55
+ - Always active on ALL sites — cannot be deactivated via UI
56
+ - Loaded before regular plugins
57
+ - No activation hooks (code runs immediately)
58
+ - Useful for: custom login, security rules, performance optimizations
59
+
60
+ ## Tips and Gotchas
61
+
62
+ - **Network activation is immediate**: No confirmation dialog. All sites are affected instantly.
63
+ - **Plugin conflicts**: A network-activated plugin may conflict with per-site plugins. Test thoroughly.
64
+ - **Updates**: Plugin updates on multisite affect all sites. Test in staging first.
65
+ - **Memory**: Each network-activated plugin increases memory usage across all sites.
66
+ - **Drop-in replacements**: `object-cache.php`, `advanced-cache.php`, `db.php` are shared across all sites.
@@ -0,0 +1,69 @@
1
+ # Network Setup
2
+
3
+ WordPress Multisite allows a single WordPress installation to host multiple websites (sub-sites) sharing the same codebase and database. Understanding the setup options is critical for architecture decisions.
4
+
5
+ ## MCP Tools
6
+
7
+ | Tool | Usage |
8
+ |------|-------|
9
+ | `ms_get_network_settings` | View current network configuration |
10
+
11
+ ## Sub-directory vs Sub-domain
12
+
13
+ | Mode | URL Pattern | Example | Requirements |
14
+ |------|------------|---------|-------------|
15
+ | Sub-directory | `example.com/site1/` | `example.com/blog/` | Default, works everywhere |
16
+ | Sub-domain | `site1.example.com` | `blog.example.com` | Wildcard DNS (`*.example.com`), wildcard SSL |
17
+
18
+ Decision factors:
19
+ - **Sub-directory**: simpler DNS, single SSL cert, better for related sites
20
+ - **Sub-domain**: each site feels independent, better for unrelated brands
21
+
22
+ ## wp-config.php Constants
23
+
24
+ Required constants for multisite (set during network installation):
25
+
26
+ ```php
27
+ define('WP_ALLOW_MULTISITE', true); // Step 1: enables Network Setup menu
28
+ define('MULTISITE', true); // Step 2: after network creation
29
+ define('SUBDOMAIN_INSTALL', false); // true for sub-domain, false for sub-directory
30
+ define('DOMAIN_CURRENT_SITE', 'example.com');
31
+ define('PATH_CURRENT_SITE', '/');
32
+ define('SITE_ID_CURRENT_SITE', 1);
33
+ define('BLOG_ID_CURRENT_SITE', 1);
34
+ ```
35
+
36
+ ## Installation Procedure
37
+
38
+ 1. Start with a fresh single-site WordPress installation
39
+ 2. Add `define('WP_ALLOW_MULTISITE', true);` to wp-config.php
40
+ 3. Navigate to Tools > Network Setup in wp-admin
41
+ 4. Choose sub-directory or sub-domain
42
+ 5. WordPress generates the remaining constants and .htaccess rules
43
+ 6. Add the generated code to wp-config.php and .htaccess
44
+ 7. Log in again — Network Admin menu appears
45
+
46
+ ## .htaccess Rules (sub-directory mode)
47
+
48
+ ```apache
49
+ RewriteEngine On
50
+ RewriteBase /
51
+ RewriteRule ^index\.php$ - [L]
52
+
53
+ # add a trailing slash to /wp-admin
54
+ RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
55
+
56
+ RewriteCond %{REQUEST_FILENAME} -f [OR]
57
+ RewriteCond %{REQUEST_FILENAME} -d
58
+ RewriteRule ^ - [L]
59
+ RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
60
+ RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
61
+ RewriteRule . index.php [L]
62
+ ```
63
+
64
+ ## Tips and Gotchas
65
+
66
+ - **Cannot switch modes**: You cannot change from sub-directory to sub-domain (or vice versa) after network creation without a fresh install or complex migration.
67
+ - **Existing content**: If the single site already has content, sub-directory mode may conflict with existing page slugs.
68
+ - **SSL**: Sub-domain mode requires wildcard SSL (`*.example.com`). Let's Encrypt supports wildcard via DNS-01 challenge.
69
+ - **WP_ALLOW_MULTISITE vs MULTISITE**: `WP_ALLOW_MULTISITE` enables the setup UI; `MULTISITE` activates the network. They are different constants.
@@ -0,0 +1,67 @@
1
+ # Site Management
2
+
3
+ Sub-site lifecycle in a WordPress Multisite network: creating, configuring, activating/deactivating, and deleting sites.
4
+
5
+ ## MCP Tools
6
+
7
+ | Tool | Usage |
8
+ |------|-------|
9
+ | `ms_list_sites` | List all sub-sites with status |
10
+ | `ms_get_site` | Get details of a specific sub-site |
11
+ | `ms_create_site` | Create a new sub-site |
12
+ | `ms_activate_site` | Activate or deactivate a sub-site |
13
+ | `ms_delete_site` | Permanently delete a sub-site |
14
+
15
+ ## Sub-site Lifecycle
16
+
17
+ ```
18
+ Create → Active → [Deactivate → Archived/Spam/Deleted]
19
+ → [Delete permanently]
20
+ ```
21
+
22
+ ## Common Procedures
23
+
24
+ ### List All Sub-sites
25
+
26
+ 1. `ms_list_sites` — returns blog_id, url, registered date, status for all sites
27
+ 2. Review the `archived`, `spam`, `deleted` flags for each
28
+
29
+ ### Create a New Sub-site
30
+
31
+ 1. `ms_create_site` with slug, title, admin email
32
+ 2. WordPress creates the sub-site with default theme and plugins
33
+ 3. The specified email becomes the sub-site admin
34
+
35
+ ### Deactivate a Sub-site
36
+
37
+ 1. `ms_activate_site` with `active: false` and the target blog_id
38
+ 2. Deactivated sites return a "This site has been archived" message to visitors
39
+ 3. Content and settings are preserved
40
+
41
+ ### Delete a Sub-site
42
+
43
+ 1. `ms_delete_site` with blog_id and `confirm: true`
44
+ 2. **Permanent**: removes all content, settings, and uploads for that sub-site
45
+ 3. Database tables for the sub-site are dropped
46
+
47
+ ## Site Properties
48
+
49
+ | Property | Description |
50
+ |----------|-------------|
51
+ | `blog_id` | Unique numeric identifier |
52
+ | `domain` | Domain name of the sub-site |
53
+ | `path` | URL path (e.g., `/blog/` in sub-directory mode) |
54
+ | `registered` | Creation timestamp |
55
+ | `last_updated` | Last modification timestamp |
56
+ | `public` | Whether the site appears in search results |
57
+ | `archived` | Manually archived by network admin |
58
+ | `spam` | Marked as spam |
59
+ | `deleted` | Soft-deleted (not permanently removed) |
60
+
61
+ ## Tips and Gotchas
62
+
63
+ - **Blog ID 1**: The main site always has `blog_id: 1`. Do not delete it.
64
+ - **Uploads**: Each sub-site has its own uploads directory under `wp-content/uploads/sites/{blog_id}/`.
65
+ - **Database tables**: Each sub-site gets its own set of tables with prefix `wp_{blog_id}_` (e.g., `wp_2_posts`, `wp_2_options`).
66
+ - **Default content**: New sub-sites get a "Hello World" post and sample page, similar to a fresh WordPress install.
67
+ - **Themes**: Sub-sites can only use themes that are network-enabled or network-activated. See `network-plugins.md`.
@@ -0,0 +1,73 @@
1
+ # User Roles in Multisite
2
+
3
+ WordPress Multisite adds a Super Admin role above the standard role hierarchy. Users can have different roles on different sub-sites within the same network.
4
+
5
+ ## MCP Tools
6
+
7
+ | Tool | Usage |
8
+ |------|-------|
9
+ | `ms_list_super_admins` | List all Super Admin users in the network |
10
+
11
+ ## Role Hierarchy
12
+
13
+ | Role | Scope | Key Capabilities |
14
+ |------|-------|-----------------|
15
+ | Super Admin | Entire network | All capabilities on all sites, network settings, site CRUD |
16
+ | Administrator | Single site | Full control of one sub-site (cannot install plugins/themes) |
17
+ | Editor | Single site | Manage and publish all posts on one site |
18
+ | Author | Single site | Publish own posts |
19
+ | Contributor | Single site | Write drafts, cannot publish |
20
+ | Subscriber | Single site | Read-only access |
21
+
22
+ ## Super Admin vs Administrator (Multisite)
23
+
24
+ | Capability | Super Admin | Site Administrator |
25
+ |-----------|-------------|-------------------|
26
+ | Install plugins | Yes | No |
27
+ | Install themes | Yes | No |
28
+ | Create/delete sub-sites | Yes | No |
29
+ | Network activate plugins | Yes | No |
30
+ | Edit wp-config.php | Yes | No |
31
+ | Manage network settings | Yes | No |
32
+ | Edit files (theme/plugin editor) | Yes | No (disabled by default) |
33
+ | Manage site users | Yes | Yes (own site only) |
34
+ | Manage site options | Yes | Yes (own site only) |
35
+
36
+ ## User Registration Modes
37
+
38
+ Network-wide setting (Network Admin > Settings):
39
+
40
+ | Mode | Description |
41
+ |------|-------------|
42
+ | Registration disabled | No one can register |
43
+ | User accounts may be registered | Users can register but not create sites |
44
+ | Logged-in users may register new sites | Existing users can create sub-sites |
45
+ | Both user accounts and sites can be registered | Open registration for users and sites |
46
+
47
+ ## Common Operations
48
+
49
+ ### List Super Admins
50
+ 1. `ms_list_super_admins` — returns usernames with super admin status
51
+
52
+ ### Add Super Admin (via wp-cli)
53
+ ```bash
54
+ wp super-admin add username
55
+ ```
56
+
57
+ ### Remove Super Admin (via wp-cli)
58
+ ```bash
59
+ wp super-admin remove username
60
+ ```
61
+
62
+ ### Add User to Sub-site (via wp-cli)
63
+ ```bash
64
+ wp user set-role username editor --url=site1.example.com
65
+ ```
66
+
67
+ ## Tips and Gotchas
68
+
69
+ - **Super Admin bypass**: Super Admins bypass all capability checks. Use this role sparingly.
70
+ - **User exists once**: A user account exists once in the network but can have different roles on different sub-sites.
71
+ - **Cannot demote yourself**: The last Super Admin cannot remove their own super admin status.
72
+ - **wp-admin vs network-admin**: Super Admins see both site-level wp-admin and network-level wp-admin/network/.
73
+ - **Plugin capability checks**: Plugins using `current_user_can()` should work correctly with multisite, but some older plugins may not distinguish Super Admin from site Administrator.
@@ -0,0 +1,160 @@
1
+ /**
2
+ * multisite_inspect.mjs — Detect WordPress Multisite configuration.
3
+ *
4
+ * Scans for multisite indicators: wp-config.php constants, WP_SITES_CONFIG flags,
5
+ * sunrise.php (domain mapping), .htaccess multisite rewrite rules.
6
+ *
7
+ * Usage:
8
+ * node multisite_inspect.mjs [--cwd=/path/to/check]
9
+ *
10
+ * Exit codes:
11
+ * 0 — multisite indicators found
12
+ * 1 — no multisite indicators found
13
+ */
14
+
15
+ import { readFileSync, existsSync } from 'node:fs';
16
+ import { join, resolve } from 'node:path';
17
+ import { argv, env, stdout, exit } from 'node:process';
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Helpers
21
+ // ---------------------------------------------------------------------------
22
+
23
+ function readFileSafe(filePath) {
24
+ try { return readFileSync(filePath, 'utf-8'); } catch { return null; }
25
+ }
26
+
27
+ function existsSafe(filePath) {
28
+ try { return existsSync(filePath); } catch { return false; }
29
+ }
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Detectors
33
+ // ---------------------------------------------------------------------------
34
+
35
+ function detectWpConfig(cwd) {
36
+ const paths = [
37
+ join(cwd, 'wp-config.php'),
38
+ join(cwd, '../wp-config.php'), // wp-config one level up (common setup)
39
+ ];
40
+
41
+ for (const p of paths) {
42
+ const content = readFileSafe(p);
43
+ if (!content) continue;
44
+
45
+ const multisite = /define\s*\(\s*['"]MULTISITE['"]\s*,\s*true\s*\)/i.test(content);
46
+ const subdomain = content.match(/define\s*\(\s*['"]SUBDOMAIN_INSTALL['"]\s*,\s*(true|false)\s*\)/i);
47
+ const domain = content.match(/define\s*\(\s*['"]DOMAIN_CURRENT_SITE['"]\s*,\s*['"]([^'"]+)['"]\s*\)/i);
48
+ const pathMatch = content.match(/define\s*\(\s*['"]PATH_CURRENT_SITE['"]\s*,\s*['"]([^'"]+)['"]\s*\)/i);
49
+
50
+ if (multisite) {
51
+ return {
52
+ found: true,
53
+ path: p,
54
+ subdomain_install: subdomain ? subdomain[1] === 'true' : null,
55
+ domain_current_site: domain ? domain[1] : null,
56
+ path_current_site: pathMatch ? pathMatch[1] : null,
57
+ };
58
+ }
59
+ }
60
+ return null;
61
+ }
62
+
63
+ function detectSitesConfig() {
64
+ const sitesJson = env.WP_SITES_CONFIG;
65
+ if (!sitesJson) return null;
66
+ try {
67
+ const sites = JSON.parse(sitesJson);
68
+ const msSites = sites.filter(s => s.is_multisite === true);
69
+ const cliSites = sites.filter(s => s.wp_path);
70
+ return {
71
+ multisite_sites: msSites.map(s => ({
72
+ id: s.id,
73
+ wp_path: s.wp_path || null,
74
+ ssh_host: s.ssh_host || null,
75
+ has_wpcli: !!s.wp_path,
76
+ })),
77
+ cli_ready_sites: cliSites.map(s => s.id),
78
+ count: msSites.length,
79
+ };
80
+ } catch { return null; }
81
+ }
82
+
83
+ function detectSunrise(cwd) {
84
+ const paths = [
85
+ join(cwd, 'wp-content/sunrise.php'),
86
+ join(cwd, 'sunrise.php'),
87
+ ];
88
+ for (const p of paths) {
89
+ if (existsSafe(p)) {
90
+ return { found: true, path: p };
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+
96
+ function detectHtaccessMultisite(cwd) {
97
+ const content = readFileSafe(join(cwd, '.htaccess'));
98
+ if (!content) return null;
99
+
100
+ // WordPress multisite .htaccess has specific rewrite rules
101
+ const hasMultisiteRules = /RewriteRule\s+\.\s+index\.php/i.test(content) &&
102
+ (/upload/.test(content) || /files/.test(content) || /blogs\.dir/.test(content));
103
+
104
+ return hasMultisiteRules ? { found: true } : null;
105
+ }
106
+
107
+ // ---------------------------------------------------------------------------
108
+ // Main
109
+ // ---------------------------------------------------------------------------
110
+
111
+ function main() {
112
+ const cwdArg = argv.find(a => a.startsWith('--cwd='));
113
+ const cwd = cwdArg ? resolve(cwdArg.split('=')[1]) : process.cwd();
114
+
115
+ const wpConfig = detectWpConfig(cwd);
116
+ const sitesConfig = detectSitesConfig();
117
+ const sunrise = detectSunrise(cwd);
118
+ const htaccess = detectHtaccessMultisite(cwd);
119
+
120
+ const signals = [];
121
+ if (wpConfig) signals.push('wp_config_multisite');
122
+ if (sitesConfig?.count > 0) signals.push('sites_config_multisite');
123
+ if (sunrise) signals.push('sunrise_domain_mapping');
124
+ if (htaccess) signals.push('htaccess_multisite_rules');
125
+
126
+ const report = {
127
+ tool: 'multisite_inspect',
128
+ version: '1.0.0',
129
+ timestamp: new Date().toISOString(),
130
+ cwd,
131
+ found: signals.length > 0,
132
+ signals,
133
+ details: {
134
+ wp_config: wpConfig || undefined,
135
+ sites_config: sitesConfig || undefined,
136
+ sunrise: sunrise || undefined,
137
+ htaccess: htaccess || undefined,
138
+ },
139
+ recommendations: [],
140
+ };
141
+
142
+ if (wpConfig && !sitesConfig?.count) {
143
+ report.recommendations.push('Multisite detected in wp-config.php but no site in WP_SITES_CONFIG has is_multisite: true');
144
+ }
145
+ if (sitesConfig?.count > 0) {
146
+ const noCli = sitesConfig.multisite_sites.filter(s => !s.has_wpcli);
147
+ if (noCli.length > 0) {
148
+ report.recommendations.push(`Sites without wp_path (no wp-cli access): ${noCli.map(s => s.id).join(', ')}`);
149
+ }
150
+ report.recommendations.push(`${sitesConfig.count} multisite network(s) configured — 10 ms_* tools available`);
151
+ }
152
+ if (sunrise) {
153
+ report.recommendations.push('sunrise.php detected — domain mapping is active');
154
+ }
155
+
156
+ stdout.write(JSON.stringify(report, null, 2) + '\n');
157
+ exit(signals.length > 0 ? 0 : 1);
158
+ }
159
+
160
+ main();
@@ -177,3 +177,7 @@ After hardening, verify the security posture:
177
177
  ## Recommended Agent
178
178
 
179
179
  For implementing hardening fixes and incident response, use the **`wp-security-hardener`** agent. For read-only security audits, use the **`wp-security-auditor`** agent.
180
+
181
+ ### Multisite Security
182
+
183
+ For Super Admin capabilities and multisite-specific security considerations, see the `wp-multisite` skill (`references/user-roles.md`).
@@ -129,3 +129,7 @@ See:
129
129
  - If you cannot confirm environment safety, do not run write operations.
130
130
  - If the repo uses containerized tooling (Docker/wp-env) but you can’t access it, ask for the intended command runner or CI job.
131
131
  - If working with a local dev environment (Studio/LocalWP/wp-env), route to the `wp-local-env` skill for environment-specific WP-CLI setup.
132
+
133
+ ### Multisite Operations
134
+
135
+ For WordPress Multisite network management (sub-sites, network plugins, Super Admin), see the `wp-multisite` skill which provides 10 dedicated MCP tools.