WordPress Hook Documentation Skill
You are documenting custom WordPress hooks for this project. This is the deep pass — thorough documentation with parameters, examples, and context, beyond what the auto-scanner produces.
Workflow
Step 1: Run the Scanner
Run the hook scanner to get a fresh inventory:
SCAN_HOOKS_VERBOSE=1 bash "$CLAUDE_PROJECT_DIR/.claude/hooks/scan-hooks.sh" "$CLAUDE_PROJECT_DIR"
If scan-hooks.sh is not available at that path, check the plugin's scripts directory:
SCAN_HOOKS_VERBOSE=1 bash "${CLAUDE_PLUGIN_ROOT}/scripts/scan-hooks.sh" "$CLAUDE_PROJECT_DIR"
If neither is available, scan manually:
- Search all
.php files (excluding vendor/, node_modules/, wp-admin/, wp-includes/) for do_action( and apply_filters( calls
- Skip WordPress core hooks (prefixed
wp_, admin_, the_, etc.)
Step 2: Read Existing Reference
Read docs/hooks-reference.md if it exists. Note any manually-written descriptions — these must be preserved.
Step 3: Deep Analysis
For each custom hook found, read the surrounding code to determine:
Parameters — names, types, and purpose. Check:
- PHPDoc
@param tags on the enclosing function
- Variable types from usage context
- WordPress conventions (e.g.,
$post_id is always int)
Purpose — what the hook enables. Read:
- The enclosing function's PHPDoc
@since and description
- What happens before/after the hook fires
- Whether it's a lifecycle event, data modification point, or extension point
Example usage — write a working add_action() or add_filter() snippet:
- Use realistic parameter names matching the hook's arguments
- Include proper callback signature with type hints
- Show a practical use case, not just a skeleton
Version — extract @since if available from the enclosing docblock
Step 4: Generate Documentation
Write docs/hooks-reference.md with this structure:
# Custom Hooks Reference
<!-- Auto-generated by wp-hooks skill — manual edits are preserved -->
<!-- Last documented: YYYY-MM-DD HH:MM:SS -->
## Overview
Brief description of the hook architecture in this plugin/theme.
## Actions
### `prefix_hook_name`
**Type:** Action
**Since:** 1.0.0
**File:** `path/to/file.php:42` (function `function_name`)
Description of what this action does and when it fires.
**Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `$arg1` | `string` | Description of arg1 |
| `$arg2` | `int` | Description of arg2 |
**Example:**
\```php
add_action( 'prefix_hook_name', function( string $arg1, int $arg2 ): void {
// Your code here
}, 10, 2 );
\```
---
## Filters
### `prefix_filter_name`
**Type:** Filter
**Since:** 1.0.0
**File:** `path/to/file.php:87` (function `function_name`)
Description of what this filter modifies.
**Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `$value` | `array` | The value being filtered |
| `$context` | `string` | Additional context |
**Default:** Description of the unfiltered default value.
**Example:**
\```php
add_filter( 'prefix_filter_name', function( array $value, string $context ): array {
// Modify and return $value
return $value;
}, 10, 2 );
\```
Rules
- Preserve manual edits — if a description already exists and was written by a human (not
<!-- TODO: describe -->), keep it
- Filters must document the return — always describe what the unfiltered default value is and what the filter is expected to return
- Actions should describe timing — when in the lifecycle does this fire?
- Group logically — if hooks belong to a subsystem (e.g., "checkout", "import"), add subheadings
- Skip core hooks — only document project-specific hooks, not
wp_enqueue_scripts or init
- Flag dynamic hooks — if a hook name is built from variables (e.g.,
"prefix_{$type}_loaded"), document the pattern and possible values
- Include the hook count — end with a summary line: "N custom hooks (X actions, Y filters)"
1---2name: wp-hooks3description: This skill should be used when the user asks to "document hooks", "generate a hooks reference", "list hooks", "show custom hooks", "generate hook docs", or mentions "hook documentation", "what hooks exist", "do_action", "apply_filters". Scans PHP source for do_action() and apply_filters() calls and produces detailed documentation with parameters, examples, and usage context.4license: MIT5---67# WordPress Hook Documentation Skill89You are documenting custom WordPress hooks for this project. This is the **deep pass** — thorough documentation with parameters, examples, and context, beyond what the auto-scanner produces.1011## Workflow1213### Step 1: Run the Scanner1415Run the hook scanner to get a fresh inventory:1617```bash18SCAN_HOOKS_VERBOSE=1 bash "$CLAUDE_PROJECT_DIR/.claude/hooks/scan-hooks.sh" "$CLAUDE_PROJECT_DIR"19```2021If `scan-hooks.sh` is not available at that path, check the plugin's scripts directory:22```bash23SCAN_HOOKS_VERBOSE=1 bash "${CLAUDE_PLUGIN_ROOT}/scripts/scan-hooks.sh" "$CLAUDE_PROJECT_DIR"24```2526If neither is available, scan manually:27- Search all `.php` files (excluding `vendor/`, `node_modules/`, `wp-admin/`, `wp-includes/`) for `do_action(` and `apply_filters(` calls28- Skip WordPress core hooks (prefixed `wp_`, `admin_`, `the_`, etc.)2930### Step 2: Read Existing Reference3132Read `docs/hooks-reference.md` if it exists. Note any manually-written descriptions — these must be preserved.3334### Step 3: Deep Analysis3536For **each** custom hook found, read the surrounding code to determine:37381. **Parameters** — names, types, and purpose. Check:39 - PHPDoc `@param` tags on the enclosing function40 - Variable types from usage context41 - WordPress conventions (e.g., `$post_id` is always `int`)42432. **Purpose** — what the hook enables. Read:44 - The enclosing function's PHPDoc `@since` and description45 - What happens before/after the hook fires46 - Whether it's a lifecycle event, data modification point, or extension point47483. **Example usage** — write a working `add_action()` or `add_filter()` snippet:49 - Use realistic parameter names matching the hook's arguments50 - Include proper callback signature with type hints51 - Show a practical use case, not just a skeleton52534. **Version** — extract `@since` if available from the enclosing docblock5455### Step 4: Generate Documentation5657Write `docs/hooks-reference.md` with this structure:5859```markdown60# Custom Hooks Reference6162<!-- Auto-generated by wp-hooks skill — manual edits are preserved -->63<!-- Last documented: YYYY-MM-DD HH:MM:SS -->6465## Overview6667Brief description of the hook architecture in this plugin/theme.6869## Actions7071### `prefix_hook_name`7273**Type:** Action74**Since:** 1.0.075**File:** `path/to/file.php:42` (function `function_name`)7677Description of what this action does and when it fires.7879**Parameters:**8081| Parameter | Type | Description |82|-----------|------|-------------|83| `$arg1` | `string` | Description of arg1 |84| `$arg2` | `int` | Description of arg2 |8586**Example:**8788\```php89add_action( 'prefix_hook_name', function( string $arg1, int $arg2 ): void {90 // Your code here91}, 10, 2 );92\```9394---9596## Filters9798### `prefix_filter_name`99100**Type:** Filter101**Since:** 1.0.0102**File:** `path/to/file.php:87` (function `function_name`)103104Description of what this filter modifies.105106**Parameters:**107108| Parameter | Type | Description |109|-----------|------|-------------|110| `$value` | `array` | The value being filtered |111| `$context` | `string` | Additional context |112113**Default:** Description of the unfiltered default value.114115**Example:**116117\```php118add_filter( 'prefix_filter_name', function( array $value, string $context ): array {119 // Modify and return $value120 return $value;121}, 10, 2 );122\```123```124125## Rules126127- **Preserve manual edits** — if a description already exists and was written by a human (not `<!-- TODO: describe -->`), keep it128- **Filters must document the return** — always describe what the unfiltered default value is and what the filter is expected to return129- **Actions should describe timing** — when in the lifecycle does this fire?130- **Group logically** — if hooks belong to a subsystem (e.g., "checkout", "import"), add subheadings131- **Skip core hooks** — only document project-specific hooks, not `wp_enqueue_scripts` or `init`132- **Flag dynamic hooks** — if a hook name is built from variables (e.g., `"prefix_{$type}_loaded"`), document the pattern and possible values133- **Include the hook count** — end with a summary line: "*N custom hooks (X actions, Y filters)*"