Skip to content
Development
Skill

/wordpress-plugin-core

WordPress plugin development with hooks, security, REST API, custom post types. Use for plugin creation, $wpdb queries, Settings API, or encountering SQL injection, XSS, CSRF, nonce errors.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill wordpress-plugin-core --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/wordpress-plugin-core

Context preview

The summary Claude sees to decide when to auto-load this skill.

WordPress plugin development with hooks, security, REST API, custom post types. Use for plugin creation, $wpdb queries, Settings API, or encountering SQL injection, XSS, CSRF, nonce errors.

SKILL.md

wordpress-plugin-core.SKILL.md
name: wordpress-plugin-core
description: "WordPress plugin development with hooks, security, REST API, custom post types. Use for plugin creation, $wpdb queries, Settings API, or encountering SQL injection, XSS, CSRF, nonce errors."

metadata:
  keywords:
    - wordpress plugin development
    - wordpress security
    - wordpress hooks
    - wordpress filters
    - wordpress database
    - wpdb prepare
    - sanitize_text_field
    - esc_html
    - wp_nonce
    - custom post type
    - register_post_type
    - settings api
    - rest api
    - admin-ajax
    - wordpress sql injection
    - wordpress xss
    - wordpress csrf
    - plugin header
    - activation hook
    - deactivation hook
    - wordpress coding standards
    - wordpress plugin architecture

license: MIT

WordPress Plugin Development (Core)

**Status**: Production Ready **Last Updated**: 2026-08-03 **Dependencies**: None (WordPress 6.0+, PHP 8.0+) **Latest Versions**: WordPress 7.0+, PHP 8.3+ recommended

---

Quick Start (10 Minutes)

1. Choose Plugin Structure

Three architecture patterns available (see `references/plugin-architectures.md` for detailed examples):

  • **Simple** (functions only) - Small plugins <5 functions
  • **OOP** - Medium plugins with related functionality
  • **PSR-4** (Namespaced + Composer) - Modern standard (2025), most maintainable

2. Create Plugin Header

Every plugin MUST have a header comment in the main file:

<?php
/**
 * Plugin Name:       My Awesome Plugin
 * Description:       Brief description.
 * Version:           1.0.0
 * Requires at least: 6.0
 * Requires PHP:      8.0
 * Text Domain:       my-plugin
 */

if ( ! defined( 'ABSPATH' ) ) exit;

**CRITICAL**: Plugin Name is required, Text Domain must match plugin slug exactly.

3. Security Foundation (5 Essentials)

// 1. Unique Prefix (4-5 chars)
function mypl_init() { /* code */ }
add_action( 'init', 'mypl_init' );

// 2. ABSPATH Check (every file)
if ( ! defined( 'ABSPATH' ) ) exit;

// 3. Nonces for Forms
wp_nonce_field( 'mypl_action', 'mypl_nonce' );

// 4. Sanitize Input, Escape Output
$clean = sanitize_text_field( $_POST['input'] );
echo esc_html( $output );

// 5. Prepared Statements
$wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}table WHERE id = %d", $id ) );

---

The 5-Step Security Foundation

Step 1: Use Unique Prefix for Everything

**Rules**: 4-5 chars minimum, apply to functions, classes, constants, options, transients, meta keys. Avoid `wp_`, `__`, `_`.

// GOOD
function mypl_init() {}
class MyPL_Settings {}
add_option( 'mypl_option', 'value' );

// BAD - Will conflict
function init() {}
class Settings {}

Step 2: Check Capabilities, Not Admin Status

// WRONG
if ( is_admin() ) { /* SECURITY HOLE */ }

// CORRECT
if ( current_user_can( 'manage_options' ) ) { /* Secure */ }

**Common Capabilities**: `manage_options` (Admin), `edit_posts` (Editor), `publish_posts` (Author)

Step 3: The Security Trinity

**Input → Processing → Output** (Sanitize → Validate → Escape):

// SANITIZATION (Input)
$name = sanitize_text_field( $_POST['name'] );
$email = sanitize_email( $_POST['email'] );
$url = esc_url_raw( $_POST['url'] );
$html = wp_kses_post( $_POST['content'] );

// VALIDATION (Logic)
if ( ! is_email( $email ) ) wp_die( 'Invalid email' );

// ESCAPING (Output)
echo esc_html( $name );
echo '<a href="' . esc_url( $url ) . '">' . esc_html( $text ) . '</a>';

**Rule**: Sanitize INPUT, escape OUTPUT. Never trust user data.

Step 4: Nonces (CSRF Protection)

One-time tokens proving requests came from your site.

// Form
<form method="post">
    <?php wp_nonce_field( 'mypl_action', 'mypl_nonce' ); ?>
    <input type="text" name="data" />
</form>

// Verify
if ( ! wp_verify_nonce( $_POST['mypl_nonce'], 'mypl_action' ) ) wp_die( 'Security check failed' );

// AJAX
check_ajax_referer( 'mypl-ajax-nonce', 'nonce' );

Step 5: Prepared Statements for Database

**CRITICAL**: Always use `$wpdb->prepare()` for user input.

// WRONG - SQL Injection
$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}table WHERE id = {$_GET['id']}" );

// CORRECT
$wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}table WHERE id = %d", $_GET['id'] ) );

**Placeholders**: `%s` (String), `%d` (Integer), `%f` (Float)

**LIKE Queries**: Use `$wpdb->esc_like()` before adding wildcards:

$search = '%' . $wpdb->esc_like( $term ) . '%';
$wpdb->get_results( $wpdb->prepare( "... WHERE title LIKE %s", $search ) );

---

Critical Rules

Always Do

✅ **Use unique prefix** (4-5 chars) for all global code (functions, classes, options, transients) ✅ **Add ABSPATH check** to every PHP file: `if ( ! defined( 'ABSPATH' ) ) exit;` ✅ **Check capabilities** (`current_user_can()`) not just `is_admin()` ✅ **Verify nonces** for all forms and AJAX requests ✅ **Use $wpdb->prepare()** for all database queries with user input ✅ **Sanitize input** with `sanitize_*()` functions before saving ✅ **Escape output** with `esc_*()` functions before displaying ✅ **Flush rewrite rules** on activation when registering custom post types ✅ **Use uninstall.php** for permanent cleanup (not deactivation hook) ✅ **Follow WordPress Coding Standards** (tabs for indentation, Yoda conditions)

Never Do

❌ **Never use extract()** - Creates security vulnerabilities ❌ **Never trust $_POST/$_GET** without sanitization ❌ **Never concatenate user input into SQL** - Always use prepare() ❌ **Never use `is_admin()` alone** for permission checks ❌ **Never output unsanitized data** - Always escape ❌ **Never use generic function/class names** - Always prefix ❌ **Never use short PHP tags** `<?` or `<?=` - Use `<?php` only ❌ **Never delete user data on deactivation** - Only on uninstall ❌ **Never register uninstall hook repeatedly** - Only once on activation ❌ **Never use `register_uninstall_hook()` in main flow** - Use uninstall.php instead

---

Kno

Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.