WP Plugin Development
When to use
Use this skill for plugin work such as:
- creating or refactoring plugin structure (bootstrap, includes, namespaces/classes)
- adding hooks/actions/filters
- activation/deactivation/uninstall behavior and migrations
- adding settings pages / options / admin UI (Settings API)
- security fixes (nonces, capabilities, sanitization/escaping, SQL safety)
- packaging a release (build artifacts, readme, assets)
Inputs required
- Repo root + target plugin(s) (path to plugin main file if known).
- Where this plugin runs: single site vs multisite; WP.com conventions if applicable.
- Target WordPress + PHP versions (affects available APIs).
Procedure
0) Triage and locate plugin entrypoints
- Identify the main plugin file (contains
Plugin Name: header)
- Check for existing structure (includes/, admin/, public/ directories)
- Note any existing hooks or class patterns
1) Follow a predictable architecture
Guidelines:
- Keep a single bootstrap (main plugin file with header).
- Avoid heavy side effects at file load time; load on hooks.
- Prefer a dedicated loader/class to register hooks.
- Keep admin-only code behind
is_admin() (or admin hooks) to reduce frontend overhead.
Read:
2) Hooks and lifecycle (activation/deactivation/uninstall)
Activation hooks are fragile; follow guardrails:
- Register activation/deactivation hooks at top-level, not inside other hooks
- Flush rewrite rules only when needed and only after registering CPTs/rules
- Uninstall should be explicit and safe (
uninstall.php or register_uninstall_hook)
Read:
3) Settings and admin UI (Settings API)
Prefer Settings API for options:
register_setting(), add_settings_section(), add_settings_field()
- Sanitize via
sanitize_callback
Read:
references/settings-api.md
4) Security baseline (always)
Before shipping:
- Validate/sanitize input early; escape output late.
- Use nonces to prevent CSRF and capability checks for authorization.
- Avoid directly trusting
$_POST / $_GET; use wp_unslash() and specific keys.
- Use
$wpdb->prepare() for SQL; avoid building SQL with string concatenation.
Read:
5) Custom Post Types and REST API (if needed)
- Register CPTs/taxonomies on
init with show_in_rest for Gutenberg support.
- Follow REST API conventions: proper permission callbacks, schema, prepared statements.
Read:
6) Hooks and extensibility
- Add action hooks at key lifecycle points for extensibility.
- Use filters for modifiable output.
- Prefix all hook names with plugin slug.
Read:
7) Cron and scheduled tasks (if needed)
- Schedule on activation, clear on deactivation.
- Critical: Never use same name for cron hook and internal
do_action().
- Process large datasets in batches.
Read:
8) Internationalization
- Use proper text domain matching plugin slug.
- Load textdomain on
plugins_loaded.
- Use translation functions:
__(), _e(), _x(), _n().
Verification
- Plugin activates with no fatals/notices.
- Settings save and read correctly (capability + nonce enforced).
- Uninstall removes intended data (and nothing else).
- Run repo lint/tests (PHPUnit/PHPCS if present).
- Passes Plugin Check plugin (no errors).
Failure modes / debugging
- Activation hook not firing:
- Hook registered incorrectly (not in main file scope), wrong main file path, or plugin is network-activated
- Settings not saving:
- Settings not registered, wrong option group, missing capability, nonce failure
- Security regressions:
- Nonce present but missing capability checks; or sanitized input not escaped on output
- Cron infinite recursion:
- Same name used for cron hook and internal
do_action() call
Read:
Escalation
For canonical detail, consult the Plugin Handbook and security guidelines before inventing patterns.
1---2name: wp-plugin-development3description: Use when developing WordPress plugins: architecture and hooks, activation/deactivation/uninstall, admin UI and Settings API, data storage, cron/tasks, security (nonces/capabilities/sanitization/escaping), and release packaging.4---5
6# WP Plugin Development
7
8## When to use
9
10Use this skill for plugin work such as:
11
12- creating or refactoring plugin structure (bootstrap, includes, namespaces/classes)
13- adding hooks/actions/filters
14- activation/deactivation/uninstall behavior and migrations
15- adding settings pages / options / admin UI (Settings API)
16- security fixes (nonces, capabilities, sanitization/escaping, SQL safety)
17- packaging a release (build artifacts, readme, assets)
18
19## Inputs required
20
21- Repo root + target plugin(s) (path to plugin main file if known).
22- Where this plugin runs: single site vs multisite; WP.com conventions if applicable.
23- Target WordPress + PHP versions (affects available APIs).
24
25## Procedure
26
27### 0) Triage and locate plugin entrypoints
28
291. Identify the main plugin file (contains `Plugin Name:` header)
302. Check for existing structure (includes/, admin/, public/ directories)
313. Note any existing hooks or class patterns
32
33### 1) Follow a predictable architecture
34
35Guidelines:
36
37- Keep a single bootstrap (main plugin file with header).
38- Avoid heavy side effects at file load time; load on hooks.
39- Prefer a dedicated loader/class to register hooks.
40- Keep admin-only code behind `is_admin()` (or admin hooks) to reduce frontend overhead.
41
42Read:
43- `references/structure.md`
44
45### 2) Hooks and lifecycle (activation/deactivation/uninstall)
46
47Activation hooks are fragile; follow guardrails:
48
49- Register activation/deactivation hooks at top-level, not inside other hooks
50- Flush rewrite rules only when needed and only after registering CPTs/rules
51- Uninstall should be explicit and safe (`uninstall.php` or `register_uninstall_hook`)
52
53Read:
54- `references/lifecycle.md`
55
56### 3) Settings and admin UI (Settings API)
57
58Prefer Settings API for options:
59
60- `register_setting()`, `add_settings_section()`, `add_settings_field()`
61- Sanitize via `sanitize_callback`
62
63Read:
64- `references/settings-api.md`
65
66### 4) Security baseline (always)
67
68Before shipping:
69
70- Validate/sanitize input early; escape output late.
71- Use nonces to prevent CSRF *and* capability checks for authorization.
72- Avoid directly trusting `$_POST` / `$_GET`; use `wp_unslash()` and specific keys.
73- Use `$wpdb->prepare()` for SQL; avoid building SQL with string concatenation.
74
75Read:
76- `references/security.md`
77
78### 5) Custom Post Types and REST API (if needed)
79
80- Register CPTs/taxonomies on `init` with `show_in_rest` for Gutenberg support.
81- Follow REST API conventions: proper permission callbacks, schema, prepared statements.
82
83Read:
84- `references/rest-api.md`
85
86### 6) Hooks and extensibility
87
88- Add action hooks at key lifecycle points for extensibility.
89- Use filters for modifiable output.
90- Prefix all hook names with plugin slug.
91
92Read:
93- `references/hooks.md`
94
95### 7) Cron and scheduled tasks (if needed)
96
97- Schedule on activation, clear on deactivation.
98- **Critical:** Never use same name for cron hook and internal `do_action()`.
99- Process large datasets in batches.
100
101Read:
102- `references/cron.md`
103
104### 8) Internationalization
105
106- Use proper text domain matching plugin slug.
107- Load textdomain on `plugins_loaded`.
108- Use translation functions: `__()`, `_e()`, `_x()`, `_n()`.
109
110## Verification
111
112- Plugin activates with no fatals/notices.
113- Settings save and read correctly (capability + nonce enforced).
114- Uninstall removes intended data (and nothing else).
115- Run repo lint/tests (PHPUnit/PHPCS if present).
116- Passes Plugin Check plugin (no errors).
117
118## Failure modes / debugging
119
120- Activation hook not firing:
121 - Hook registered incorrectly (not in main file scope), wrong main file path, or plugin is network-activated
122- Settings not saving:
123 - Settings not registered, wrong option group, missing capability, nonce failure
124- Security regressions:
125 - Nonce present but missing capability checks; or sanitized input not escaped on output
126- Cron infinite recursion:
127 - Same name used for cron hook and internal `do_action()` call
128
129Read:
130- `references/debugging.md`
131
132## Escalation
133
134For canonical detail, consult the Plugin Handbook and security guidelines before inventing patterns.
135
136- [Plugin Developer Handbook](https://developer.wordpress.org/plugins/)
137- [Security Best Practices](https://developer.wordpress.org/plugins/security/)
138- [Settings API](https://developer.wordpress.org/plugins/settings/settings-api/)