plugin-structure
Skill4 starsChanged 4 months agoMITView on GitHub
Scaffold a WordPress plugin correctly — the main plugin file and header, activation/deactivation/uninstall hooks, directory layout, autoloading, avoiding global-namespace collisions, and choosing between a plugin and an mu-plugin. Use when the user wants to organize plugin code with namespaces or autoloading and avoid function, class, or constant name clashes with other plugins; the user needs to run setup or teardown code on plugin activation, deactivation, or uninstall (create tables, flush rewrites, remove options); the user is starting a new WordPress plugin and needs the main plugin file, header, and directory layout. Keywords: wordpress, plugin, plugin-structure, activation-hook, uninstall, autoloading, mu-plugin, namespace, input, security, scaffold.
14 other projects use a version of this.
Adopted by
Most recently taken up by
- shkodnik1917/claude-brainlabtheir own version, first seen Nov 8, 2026
- Vepricov/claude-brainlabtheir own version, first seen Nov 1, 2026
- davidanthonyn/claude-skillstheir own version, first seen Oct 20, 2026
- anthropics/claude-plugins-officialtheir own version, first seen Oct 13, 2026
- nek1987/auto-agent-harnesstheir own version, first seen Oct 11, 2026
- tstapler/dotfilestheir own version, first seen Oct 10, 2026
Used with
Projects with it also use results-report, daily-coding and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
Galaxy-DawnSkillresults-report
This skill should be used when the user asks to "write an experiment report", "summarize experimental results", "do experiment retrospection", "write a results report", "写实验总结报告", "写实验复盘", or mentions turning completed experiment artifacts into a structured, decision-oriented research report. It assumes strict analysis should come from `results-analysis` first.
Also in 3 projects that use this
Clay-HHKSkilldaily-coding
Daily coding assistant that auto-triggers when writing/modifying code, providing a core checklist.
Also in 3 projects that use this
Clay-HHKSkillkaggle-learner
This skill should be used when the user asks to "learn from Kaggle", "study Kaggle solutions", "analyze Kaggle competitions", or mentions Kaggle competition URLs. Provides access to extracted knowledge from winning Kaggle solutions across NLP, CV, time series, tabular, and multimodal domains.
Also in 3 projects that use this
kharlamenkodevSkillbug-detective
Also in 3 projects that use this
indranilbanerjeeSkillreview-response
Draft a reply to one customer review, voice-scored, with escalation flags. \"reply to this 1-star review\"
Also in 3 projects that use this
Google CloudSkillcitation-verification
Verify that citations in a document resolve to real records and that claimed titles match. Use before trusting a document's reference list.
Also in 3 projects that use this
- +2 more from Clay-HHK
Other versions14 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 14
- anthropics/claude-plugins-official★ 46ksame name
- Galaxy-Dawn/claude-scholar★ 5.9ksame name
- shkodnik1917/claude-brainlab★ 35same name
- Vepricov/claude-brainlab★ 35same name
- jorgeasaurus/agent-skills★ 14same name
- tstapler/dotfiles★ 8same name
- HK-hub/AgentSkills★ 6same name
- nek1987/auto-agent-harness★ 4same name
- kvivek0591/claude-code-skills★ 2same name
- Airmomo/skills★ 1same name
4 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository119 other files it gives its agents.
- strategy-bitrix-d7-incrementalSkill
- strategy-explicit-over-magicSkill
- strategy-framework-conventionsSkill
- strategy-legacy-safe-editsSkill
- strategy-minimal-diffSkill
- strategy-no-untested-refactorSkill
- strategy-preserve-public-apiSkill
- strategy-readonly-immutabilitySkill
- strategy-security-firstSkill
- strategy-test-drivenSkill
- openapiSkill
- paginationSkill
- rest-designSkill
- versioningSkill
- cqrsSkill
- dependency-inversionSkill
- hexagonalSkill
- repository-patternSkill
- service-layerSkill
- bitrixSkill
- findings-reportSkill
- laravelSkill
- performanceSkill
- phpSkill
- project-analysisSkill
- refactoringSkill
- roi-prioritizationSkill
- securitySkill
- stack-detectionSkill
- cache-layersSkill
- component-engineSkill
- d7-eventsSkill
- d7-loaderSkill
- d7-orm-queriesSkill
- iblock-elementsSkill
- kernel-main-moduleSkill
- localizationSkill
- controllersSkill
- ormSkill
- validationSkill
- controllersSkill
- query-builderSkill
- routingSkill
- autoload-psr4Skill
- dependency-managementSkill
- scriptsSkill
- connection-poolingSkill
- mysql-indexingSkill
- redisSkill
- transactionsSkill
- ci-github-actionsSkill
- deployment-strategiesSkill
- docker-phpSkill
- env-configSkill
- associationsSkill
- entities-mappingSkill
- orm-basicsSkill
- entity-apiSkill
- module-developmentSkill
- routing-controllersSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 7 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 14 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 78
Do not scaffold a full distributable plugin for a one-off single-site tweak.
- Distinctive: line 79
Do not build a plugin for theme-specific presentation such as templates, styles, or layout.
- Very specific: line 128
Create wp-content/mu-plugins/acme-platform.php.
- Distinctive: line 130
Verify: The file's code runs on every request and the mu-plugin shows under the "Must-Use" tab.
- Distinctive: line 134
Verify: Code in the subdirectory runs and stays organized under a namespace.
- Very specific: line 150
Create my-plugin/my-plugin.php with a Plugin Name: header block (name, version, Requires PHP, Text Domain) and defined('ABSPATH') || exit.
- Distinctive: line 153
Verify: The plugin appears on the Plugins screen and direct access to the file returns nothing.
- Very specific: line 154
Put classes under a namespace in src/, register a PSR-4 autoloader, and boot the plugin from a callback on plugins_loaded rather than at …
- Distinctive: line 156
Verify: Classes resolve without manual requires and the plugin boots after WordPress is loaded.
- Distinctive: line 160
Verify: Activation sets up data, deactivation is reversible, and deleting the plugin leaves no orphaned rows.
- Very specific: line 170
Keep the main plugin file to the header, constants, the autoloader include, and hook registration.
“Common” is measured: kept by at least 6 in 10 of the 14 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- generated: do not edit — source: knowledge/atoms/wordpress/plugin-structure/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->WordPress Plugin Structure
When to use
- The user wants to organize plugin code with namespaces or autoloading and avoid function, class, or constant name clashes with other plugins.
- The user needs to run setup or teardown code on plugin activation, deactivation, or uninstall (create tables, flush rewrites, remove options).
- The user is starting a new WordPress plugin and needs the main plugin file, header, and directory layout.
When NOT to use
- Do not scaffold a full distributable plugin for a one-off single-site tweak; a code snippet or a small mu-plugin is enough.
- Do not build a plugin for theme-specific presentation such as templates, styles, or layout; put that in the theme or a child theme.
Core guidance
- Guard every PHP file against direct access — At the top of every plugin PHP file add
defined('ABSPATH') || exit;so the file does nothing when requested directly over HTTP. - Namespace all code or prefix every global symbol — Wrap plugin code in a PHP namespace such as
namespace Acme\MyPlugin;, or if you must stay procedural, prefix every function, class, and constant with a unique vendor slug (for exampleacme_myplugin_init()). - Clean up persistent data on uninstall, not deactivation — Remove options, custom tables, and scheduled events in
uninstall.php(or aregister_uninstall_hookcallback), not in the deactivation hook.
Decision Engine
Walk this section before choosing an implementation path.
Is the code presentation tied to the theme, an always-on platform guardrail,
a distributed feature, or a one-off single-site tweak?
├── Must never be deactivated, no activation UI: → Ship an mu-plugin in `wp-content/mu-plugins` — it auto-loads, cannot be disabled
from the admin, but has no activation/deactivation hooks and no update UI.
├── User-facing feature, shipped or reusable: → Build a normal plugin with a full main-file header, activation/deactivation and
`uninstall.php` hooks, namespaced/autoloaded code, and an ABSPATH guard.
├── One hook, one site, never shipped: → Use a code snippet or a single-file mu-plugin — a full plugin skeleton (readme,
i18n, uninstall, autoloading) is overhead for one hook that never ships.
└── Templates, styles, layout for one theme: → Put it in the theme or a child theme, not a plugin — presentation should change
with the theme, and plugin features must survive a theme switch.
Full engine: references/decision-engine.md — Decision Tree, Priority Matrix, Decision Table.
Workflows
Workflow: Create Mu Plugin
Progress:
- [ ] Create `wp-content/mu-plugins/acme-platform.php`; a PHP file directly in
mu-plugins is auto-loaded on every request with no activation step
- [ ] Because WordPress only scans files directly in mu-plugins (not subfolders), have
the loader `require` your namespaced code from a subdirectory and boot it on
`plugins_loaded`- Create
wp-content/mu-plugins/acme-platform.php; a PHP file directly in mu-plugins is auto-loaded on every request with no activation step.- Verify: The file's code runs on every request and the mu-plugin shows under the "Must-Use" tab.
- Because WordPress only scans files directly in mu-plugins (not subfolders), have
the loader
requireyour namespaced code from a subdirectory and boot it onplugins_loaded.- Verify: Code in the subdirectory runs and stays organized under a namespace.
Workflow: Scaffold Plugin
Progress:
- [ ] Create `my-plugin/my-plugin.php` with a `Plugin Name:` header block (name,
version, `Requires PHP`, `Text Domain`) and `defined('ABSPATH') || exit;` on the
first line after the header
- [ ] Put classes under a namespace in `src/`, register a PSR-4 autoloader, and boot the
plugin from a callback on `plugins_loaded` rather than at file scope
- [ ] In the main file call `register_activation_hook(__FILE__, ...)` to create schema
and flush rewrites, `register_deactivation_hook(__FILE__, ...)` for reversible
teardown, and add `uninstall.php` to delete options and tables on removal- Create
my-plugin/my-plugin.phpwith aPlugin Name:header block (name, version,Requires PHP,Text Domain) anddefined('ABSPATH') || exit;on the first line after the header.- Verify: The plugin appears on the Plugins screen and direct access to the file returns nothing.
- Put classes under a namespace in
src/, register a PSR-4 autoloader, and boot the plugin from a callback onplugins_loadedrather than at file scope.- Verify: Classes resolve without manual requires and the plugin boots after WordPress is loaded.
- In the main file call
register_activation_hook(__FILE__, ...)to create schema and flush rewrites,register_deactivation_hook(__FILE__, ...)for reversible teardown, and adduninstall.phpto delete options and tables on removal.- Verify: Activation sets up data, deactivation is reversible, and deleting the plugin leaves no orphaned rows.
Best practices
- Ship a normal plugin (activatable, distributable) by default; use an mu-plugin
(
wp-content/mu-plugins) only for must-use infrastructure that admins must never disable and that has no activation UI - Load classes with a PSR-4 autoloader — Composer's
vendor/autoload.phpif you have dependencies, otherwise a smallspl_autoload_registermapping your namespace to thesrc/directory — instead of a wall ofrequirecalls - Keep the main plugin file to the header, constants, the autoloader include, and
hook registration; do the real work in classes loaded on
plugins_loadedorinit, not at file scope
Anti-patterns
| Anti-pattern | Why it fails | Do instead |
| Deleting user data in the deactivation hook | Deactivation is meant to be temporary and reversible; wiping data there destroys it on a routine deactivate/reactivate or during updates. | Keep deactivation reversible (unschedule events, flush rewrites) and put permanent<br>data removal in uninstall.php or a register_uninstall_hook callback. |
| Running plugin logic at file scope | File-scope code runs before WordPress is fully booted, so translations, other plugins, and the current user may be missing, and errors are hard to trace. | Register hooks in the main file and put the actual work in callbacks on<br>plugins_loaded or init. |
| A wall of require statements instead of autoloading | Manual includes load classes the request never uses, bloat the main file, and must be edited by hand for every new class. | Use a PSR-4 autoloader — Composer's vendor/autoload.php or a small<br>spl_autoload_register mapping your namespace to src/ — so classes load on demand. |
| Unprefixed global functions and classes | WordPress loads all plugins into one global scope, so a generic name fatally redeclares against another plugin or core. | Wrap code in a namespace (namespace Acme\MyPlugin;) or prefix every symbol with a<br>unique vendor slug. |
See references/anti-patterns.md.
Debugging
- Bundling Composer vendor without scoping — WordPress shares one PHP process, so the first plugin to autoload a class wins and the second plugin runs against an incompatible version, causing subtle failures or fatals. Fix: Scope bundled dependencies (for example with php-scoper) into your own namespace, or depend only on libraries unlikely to collide, so each plugin loads its own copy.
- Registering activation hook from the wrong file — WordPress matches the hook against the main plugin file path, so a wrong FILE means activation setup never runs. Fix: Register activation, deactivation, and uninstall hooks in the main plugin file so
__FILE__resolves to the file WordPress activated, or pass the main file path explicitly. - Calling flush_rewrite_rules on every request — Flushing rewrites is expensive and, run per-request, adds noticeable latency to the whole site. Fix: Register post types and rewrites on
init, but callflush_rewrite_rules()only inside the activation hook (and deactivation), never on the normal request path. - Loading the text domain too early — WordPress registers locale and translation infrastructure around init, so earlier calls no-op silently. Fix: Hook
load_plugin_textdomain()toinit(or later) so translations are loaded when they are ready.
Performance notes
- Calling flush_rewrite_rules on every request — Calling
flush_rewrite_rules()oninit(on every page load) instead of once in the activation hook rebuilds the rewrite rules on every request.
Production checklist
- Every PHP file starts with defined('ABSPATH') || exit; so it cannot run when hit directly.
- Classes are loaded through a PSR-4 autoloader rather than a list of require statements in the main file.
- Real work runs on plugins_loaded or init, not at file scope, so WordPress services are available.
- The main file declares Plugin Name, Version, Requires PHP, and a text domain in its header block.
- Activation sets up schema and flushes rewrites, deactivation is reversible, and uninstall.php removes persistent data.
- All functions, classes, and constants are namespaced or carry a unique vendor prefix to avoid collisions.
Version notes
- Requires PHP and Requires at least headers (PHP >=7.4) — The
Requires PHP:andRequires at least:header fields let WordPress block activation on unsupported PHP or core versions; both are honored on current WordPress (6.7–6.8) and are the safe floor for a plugin targeting PHP 7.4–8.3. - uninstall.php runs in a limited context (PHP >=7.4) —
uninstall.phpruns with the constantWP_UNINSTALL_PLUGINdefined but without the plugin's own code loaded, so it must be self-contained and guard on that constant; this behavior is stable across WordPress 6.x.
Security
- Block direct file access and keep secrets out of the tree — Guard every PHP file with
defined('ABSPATH') || exit;, never place API keys or credentials in files under the web-served plugin directory, and validate and sanitize any input read during activation or uninstall.
Testing
- Activation and decision behavior are verified in
eval/scenarios/wordpress/plugin-structure.yaml.
Additional resources
- references/anti-patterns.md
- references/core.md
- references/decision-engine.md
- references/examples.md
- references/pitfalls.md
- references/recipes.md
- references/version-differences.md
Knowledge graph
Related: wordpress/hooks-actions, wordpress/hooks-filters
Behavior constraints: ai-rules/strategy-minimal-diff
<!-- graph-fragment: graph/fragments/wordpress/plugin-structure.yaml -->Skill contract
Produces: wp.plugin-scaffolded
Requires: stack.wordpress-site
Risk: low · Confidence: 0.9
<!-- contract-fragment: contracts/fragments/wordpress/plugin-structure.yaml -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

