Initial skill library: 9 skills for delegate briefs

WordPress plugin rebrand/conventions/remote-CLI patterns, Gitea release
workflow, bastille jail provisioning, remote shell quoting safety, server
fleet map, delegate brief writing, and verification discipline -- all
derived from real incidents this session, plus two skills adapted (MIT
license, attributed) from obra/superpowers and andrej-karpathy-skills.
This commit is contained in:
iWP Claudy
2026-08-02 20:08:29 +02:00
parent 9382b1efdc
commit 39a637410c
11 changed files with 882 additions and 1 deletions
@@ -0,0 +1,123 @@
---
name: wordpress-plugin-conventions
description: Use when writing or modifying a WordPress plugin's PHP code. Baseline structural/security conventions to follow without being told each time.
---
# WordPress Plugin Conventions
Baseline conventions for first-party WordPress plugin code. Follow these
without needing to be told in every brief.
## File structure
```
plugin-slug/
plugin-slug.php — main file: header, constants, bootstrap class
includes/
class-<prefix>-*.php — one class per concern, class-based not procedural
admin/ — admin-only UI (settings pages, dashboards)
assets/{css,js}/
languages/ — .pot/.po/.mo if the plugin is translatable
```
## Main file skeleton
```php
<?php
/**
* Plugin Name: ...
* Plugin URI: ...
* Description: ...
* Version: 1.0.0
* Author: ...
* Author URI: ...
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: plugin-slug
* Requires PHP: 7.4
*/
if (!defined('ABSPATH')) {
exit;
}
define('PREFIX_VERSION', '1.0.0');
define('PREFIX_PATH', plugin_dir_path(__FILE__));
define('PREFIX_URL', plugin_dir_url(__FILE__));
require_once PREFIX_PATH . 'includes/class-prefix-thing.php';
class Prefix_Main {
private static $instance = null;
public static function instance() {
if (null === self::$instance) { self::$instance = new self(); }
return self::$instance;
}
private function __construct() { /* hook registration only */ }
public static function activate() { /* create tables/options/dirs */ }
public static function deactivate() { /* reverse activate() side effects */ }
}
register_activation_hook(__FILE__, ['Prefix_Main', 'activate']);
register_deactivation_hook(__FILE__, ['Prefix_Main', 'deactivate']);
add_action('plugins_loaded', ['Prefix_Main', 'instance']);
```
Every included file starts with `if (!defined('ABSPATH')) exit;` — never
`define('ABSPATH', ...) &&` or any variant, exactly the guard-and-exit
form, so the file can never be requested directly over HTTP.
## Every file must pass `php -l` before you consider a task done
Not optional, not "probably fine" — actually run it, on every changed
file, every time. This is the cheapest possible check and catches a
meaningful fraction of real mistakes (typos, mismatched braces from a
find/replace, etc.) before they ever reach a live site.
## Security baseline
- Nonces on every form/AJAX action: `wp_nonce_field()` /
`check_admin_referer()` / `check_ajax_referer()`.
- Capability checks before any privileged action:
`current_user_can('manage_options')` (or the narrowest capability that
actually applies — don't default to `manage_options` for things a
lower-privileged role should legitimately be able to do).
- Escape on output, every time, using the context-correct function:
`esc_html()`, `esc_attr()`, `esc_url()`, `esc_js()` — never raw-echo
anything that traces back to user input or the database without one of
these.
- Sanitize on input: `sanitize_text_field()`, `absint()`,
`sanitize_email()`, etc. — appropriate to the expected shape of the
data, applied at the point the `$_POST`/`$_GET` value is first read.
- `$wpdb->prepare()` for every query with a variable in it — no string-
interpolated SQL, ever, no exceptions.
## Database tables
If a plugin needs its own tables (not just options), use `dbDelta()`:
```php
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$wpdb->prefix}prefix_thing (...) {$charset};";
dbDelta($sql);
```
Track a `DB_VERSION` constant + a stored option so future plugin updates
can detect and re-run `dbDelta()` for schema changes.
## PHP 7.4 compatibility
Unless a specific brief says otherwise, target PHP 7.4+ (a large fraction
of real WordPress hosting is still on 7.4). Avoid PHP 8-only syntax
(named arguments, enums, readonly properties, `match`). If a codebase
needs `str_contains`/`str_starts_with`/`str_ends_with` (PHP 8.0+) on an
environment that might run 7.4, guard with `function_exists()`
polyfills rather than assuming they exist.
## Don't build what WordPress core already gives you
Before writing custom code for: cron scheduling (`wp_schedule_event`),
REST endpoints (`register_rest_route`), settings UI
(`register_setting`/`add_settings_field`/`woocommerce_admin_fields` if
WooCommerce context), object caching (`wp_cache_*` functions), HTTP
requests (`wp_remote_get`/`wp_remote_post`, not raw `curl`) — check
whether a core API already does it. Reinventing these is both wasted
effort and a common source of subtle bugs core already solved correctly.