Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Claude Code Community Plugins & Examples — Administrator & Developer Guide

Generated May 2026 from anthropics/claude-code at fb063cd

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Architecture Overview

The anthropics/claude-code repository is the official community collection of plugins, examples, and tooling for extending Claude Code. It is not the Claude Code application itself — it is a plugin and example ecosystem that Claude Code discovers and loads at runtime.

System Architecture

Claude Code Runtime
├── Plugin Discovery
│   └── Scans plugin directories for standard structure
│       ├── commands/     → Registers slash commands
│       ├── agents/       → Registers spawnable agents
│       ├── skills/       → Registers knowledge packs (SKILL.md)
│       ├── hooks/        → Registers event hooks (hooks.json)
│       └── scripts/      → Utility scripts (not auto-discovered)
│
├── Hook Event Pipeline
│   ├── SessionStart      → Fires on session init
│   ├── UserPromptSubmit  → Fires on user input
│   ├── PreToolUse        → Fires before tool execution
│   ├── PostToolUse       → Fires after tool execution
│   └── Stop              → Fires when Claude stops
│
├── Settings Layer
│   ├── Managed settings (MDM / settings.json)
│   ├── Permission rules (ask/deny/allow)
│   └── Sandbox configuration
│
└── MCP Server Integration
    ├── stdio  (local process)
    ├── SSE    (hosted cloud)
    └── HTTP   (REST API)

Note

The plugin discovery mechanism uses convention-over-configuration. Plugins need no registration file beyond the standard directory structure — Claude Code auto-discovers components by scanning known subdirectory names.

Component Inventory

Component Path Role
Hookify core plugins/hookify/core/ Rule engine + config loader (Python)
Security guidance plugins/security-guidance/hooks/ Security pattern detection hook (Python)
Code review plugins/code-review/commands/ Code review slash command
PR review toolkit plugins/pr-review-toolkit/ 6 specialized review agents + orchestrator command
Commit commands plugins/commit-commands/commands/ Git commit/push/PR workflow commands
Feature dev plugins/feature-dev/ 3 agents + feature development command
Plugin dev plugins/plugin-dev/ Meta-plugin: 7 skills, 3 agents, 1 command
Agent SDK dev plugins/agent-sdk-dev/ Agent SDK scaffolding command + verifier agents
Ralph Wiggum plugins/ralph-wiggum/ Looping task automation
Explanatory style plugins/explanatory-output-style/ SessionStart hook for explanatory output
Learning style plugins/learning-output-style/ SessionStart hook for teaching output
Claude Opus 4.5 migration plugins/claude-opus-4-5-migration/ Model migration skill pack
Frontend design plugins/frontend-design/ Frontend design skill
Settings examples examples/settings/ 3 settings presets (strict, lax, sandbox)
Hook examples examples/hooks/ Bash command validator example
MDM examples examples/mdm/ Managed device templates (macOS + Windows)
DevContainer script Script/ PowerShell DevContainer automation
Issue scripts scripts/ TypeScript/bash issue management scripts

Technology Stack

Layer Technology
Hook scripts Python 3, Bash
Rule engine Python 3 (dataclasses, regex, glob)
Commands / Agents / Skills Markdown with YAML frontmatter
Hook configuration JSON (hooks.json)
Settings JSON
MCP configuration JSON (stdio/SSE/HTTP)
DevContainer script PowerShell
Issue management scripts TypeScript, Bash
MDM templates Apple plist/mobileconfig, Windows ADMX/ADML, PowerShell

Data Flow: Hook Execution

1. User or Claude triggers a tool call (e.g., Bash "rm -rf /tmp")
2. Claude Code fires PreToolUse event
3. Event pipeline checks hooks.json for matching hooks
   └── matcher: "Bash" matches tool_name "Bash"
4. Hook script receives JSON on stdin:
   {"tool_name": "Bash", "tool_input": {"command": "rm -rf /tmp"}, "session_id": "..."}
5. Hook evaluates input:
   ├── Exit 0 → Allow (operation proceeds)
   ├── Exit 1 → Error (stderr to user, operation proceeds)
   └── Exit 2 → Block (stderr JSON with systemMessage to Claude)
6. If blocked: Claude sees the systemMessage and adjusts behavior

Data Flow: Hookify Rule Evaluation

1. PreToolUse/PostToolUse/Stop/UserPromptSubmit event fires
2. Hookify hook script runs (e.g., pretooluse.py)
3. config_loader.py scans .claude/hookify.*.local.md files
4. Each file's YAML frontmatter is parsed into a Rule object
5. rule_engine.py evaluates all enabled rules against input_data
   ├── Tool matcher check (e.g., "Bash", "Edit|Write", "*")
   ├── All conditions must match (AND logic)
   │   └── Each condition: extract field → apply operator → match pattern
   └── Results accumulated: blocking rules take priority over warnings
6. Combined response:
   ├── Block → {"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "..."}
   ├── Warn  → {"systemMessage": "..."}
   └── None  → {} (allow)

2. System Requirements

Requirement Version Notes
Claude Code Latest with plugin support Core runtime — this repo extends it
Python 3.8+ Required by hookify core and security-guidance hooks
jq Any Recommended for bash hook scripts that parse JSON
Git Any For cloning and contributing
Docker 20.10+ Only for DevContainer script
Podman 4.0+ Alternative to Docker for DevContainer script
devcontainer CLI Any Required by DevContainer script
Node.js / npm 18+ Only for issue management scripts (TypeScript)
PowerShell 5.1+ / 7+ Only for DevContainer script (Windows)

3. Configuration Reference

Settings JSON Schema

Settings are configured via JSON files. The repository provides three example presets demonstrating the available fields.

Permission Settings

Key Type Default Description Required
permissions.disableBypassPermissionsMode string (unset) Set to "disable" to prevent users from bypassing permission checks No
permissions.ask string[] [] Tool names that require explicit user approval before each use No
permissions.deny string[] [] Tool names that are completely blocked No

Sandbox Settings

Key Type Default Description Required
sandbox.enabled boolean false Enable command sandboxing No
sandbox.autoAllowBashIfSandboxed boolean false Auto-approve Bash commands when sandbox is active No
sandbox.allowUnsandboxedCommands boolean true Allow commands to run outside the sandbox No
sandbox.excludedCommands string[] [] Commands excluded from sandboxing No
sandbox.enableWeakerNestedSandbox boolean false Allow a weaker sandbox for nested operations No

Sandbox Network Settings

Key Type Default Description Required
sandbox.network.allowUnixSockets string[] [] Specific Unix socket paths to allow No
sandbox.network.allowAllUnixSockets boolean false Allow all Unix socket connections No
sandbox.network.allowLocalBinding boolean false Allow binding to local ports No
sandbox.network.allowedDomains string[] [] Domains allowed for outbound connections No
sandbox.network.httpProxyPort integer|null null HTTP proxy port for sandboxed traffic No
sandbox.network.socksProxyPort integer|null null SOCKS proxy port for sandboxed traffic No

Management Settings

Key Type Default Description Required
allowManagedPermissionRulesOnly boolean false Only allow permission rules set by managed configuration (MDM) No
allowManagedHooksOnly boolean false Only allow hooks set by managed configuration No
strictKnownMarketplaces string[] (unset) Restrict plugin sources to listed marketplaces No

Important

When allowManagedPermissionRulesOnly is true, users cannot add their own permission rules — only centrally managed rules apply. This is the primary enterprise control lever for locking down Claude Code.

Environment Variables

Variable Type Default Description Required
ENABLE_SECURITY_REMINDER string "1" Set to "0" to disable the security-guidance hook entirely No
CLAUDE_PLUGIN_ROOT string (set by runtime) Absolute path to the plugin's root directory; use in hooks.json paths No (auto)
CLAUDE_PROJECT_DIR string (set by runtime) Absolute path to the current project directory No (auto)
CLAUDE_ENV_FILE string (set by runtime) Path to environment file for persisting variables across hooks No (auto)

Hook Configuration (hooks.json)

Each plugin's hooks/hooks.json defines event subscriptions:

{
  "description": "Optional description of this hook set",
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<ToolName|ToolName2>",
        "hooks": [
          {
            "type": "command",
            "command": "<executable> ${CLAUDE_PLUGIN_ROOT}/path/to/script"
          }
        ]
      }
    ]
  }
}

Event types and their input data:

Event Input Fields Matcher Applies To
PreToolUse tool_name, tool_input, session_id, hook_event_name tool_name
PostToolUse tool_name, tool_input, tool_output, session_id tool_name
Stop reason, transcript_path, session_id N/A
SessionStart session_id N/A
UserPromptSubmit user_prompt, session_id N/A

Hook output JSON schema (exit code 2):

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny|ask|allow"
  },
  "systemMessage": "Message visible to Claude explaining why the operation was blocked",
  "decision": "block",
  "reason": "For Stop events — reason for blocking"
}

Hookify Rule File Format

Rule files are markdown with YAML frontmatter, stored as .claude/hookify.{name}.local.md:

Frontmatter Key Type Default Description
name string "unnamed" Rule identifier
enabled boolean true Whether the rule is active
event string "all" Event filter: bash, file, stop, all
action string "warn" warn (show message) or block (deny operation)
pattern string (none) Legacy simple pattern (auto-converted to condition)
tool_matcher string (none) Tool name filter: "Bash", "Edit|Write", "*"
conditions list [] List of condition objects (see below)

Condition object:

Key Type Description
field string Field to extract from input (command, file_path, new_text, content, reason, transcript, user_prompt)
operator string Match operator (regex_match, contains, equals, not_contains, starts_with, ends_with)
pattern string Value to match against

MCP Server Configuration

Three transport types are supported in plugin MCP configurations:

stdio — local process:

Key Type Description
command string Executable to run
args string[] Command arguments
env object Environment variables

SSE — hosted cloud service:

Key Type Description
type "sse" Transport type
url string SSE endpoint URL
headers object Optional HTTP headers

HTTP — REST API:

Key Type Description
type "http" Transport type
url string HTTP endpoint URL
headers object HTTP headers (e.g., Authorization)

Command Frontmatter Reference

Slash commands are markdown files with optional YAML frontmatter:

Field Type Default Description
description string (none) Brief description shown in /help
allowed-tools string (all) Comma-separated tool whitelist (e.g., Read, Bash(git:*))
model string (default) Model override: sonnet, opus, haiku
argument-hint string (none) Argument documentation (e.g., [pr-number] [priority])
disable-model-invocation boolean false When true, command is manual-only (not auto-invoked)

Dynamic argument substitution:

Syntax Description
$ARGUMENTS All arguments as a single string
$1, $2, $3 Positional arguments
@path/to/file Include file contents inline
!`command` Execute bash command and include output

4. Deployment & Scaling

Enterprise Deployment via MDM

The examples/mdm/ directory provides templates for managed device management deployment on macOS and Windows.

macOS Deployment

File Format Purpose
com.anthropic.claudecode.mobileconfig Apple Configuration Profile Full MDM profile for deployment via MDM solutions (Jamf, Mosyle, etc.)
com.anthropic.claudecode.plist Property List Preference domain for defaults write or profile manager

Windows Deployment

File Format Purpose
ClaudeCode.admx Group Policy Administrative Template Defines Claude Code policy settings for Group Policy Editor
en-US/ClaudeCode.adml ADML Language File English language strings for the ADMX template
Set-ClaudeCodePolicy.ps1 PowerShell Script Programmatically set Claude Code policies via registry

Minimal managed settings (prevents permission bypass):

{
  "permissions": {
    "disableBypassPermissionsMode": "disable"
  }
}

Warning

MDM-deployed settings take precedence over user-local settings. Test thoroughly in a staging environment before pushing to production devices.

DevContainer Deployment

The PowerShell script at Script/run_devcontainer_claude_code.ps1 automates containerized Claude Code environments.

Parameters:

Parameter Required Values Description
-Backend Yes docker, podman Container backend to use

Podman flow:

  1. podman machine init claudeVM — creates the VM
  2. podman machine start claudeVM -q — starts the VM
  3. podman system connection default claudeVM — sets default connection
  4. devcontainer up --workspace-folder . --docker-path podman
  5. Finds container by label devcontainer.local_folder={cwd}
  6. podman exec -it {id} zsh -c 'claude; exec zsh'

Docker flow:

  1. Verifies Docker Desktop is running via docker info
  2. devcontainer up --workspace-folder .
  3. Finds container by label devcontainer.local_folder={cwd}
  4. docker exec -it {id} zsh -c 'claude; exec zsh'

5. Operations

Issue Management Scripts

The scripts/ directory contains automation for GitHub issue triage:

Script Language Purpose
auto-close-duplicates.ts TypeScript Automatically close duplicate issues
backfill-duplicate-comments.ts TypeScript Add duplicate markers to existing issues
comment-on-duplicates.sh Bash Comment on duplicate issues
edit-issue-labels.sh Bash Batch edit issue labels
gh.sh Bash GitHub CLI wrapper
issue-lifecycle.ts TypeScript Manage issue lifecycle transitions
lifecycle-comment.ts TypeScript Add lifecycle comments to issues
sweep.ts TypeScript Sweep stale issues

Tip

These scripts are designed for repository maintainers. They require the gh CLI to be authenticated and use the GitHub API for issue management.

Plugin Maintenance

Adding a new plugin:

  1. Create the plugin directory under plugins/
  2. Add a README.md describing the plugin
  3. Create component subdirectories as needed (commands/, hooks/, skills/, agents/)
  4. For hooks: create hooks/hooks.json with event subscriptions
  5. Test with claude --debug

Updating hook scripts:

  1. Edit the script
  2. Lint with hook-linter.sh
  3. Test with test-hook.sh using sample input
  4. Validate hooks.json with validate-hook-schema.sh

Note

The hook development scripts in plugins/plugin-dev/skills/hook-development/scripts/ are the canonical tools for validating and testing hooks across the entire repository.

Security State File Cleanup

The security-guidance hook creates session-scoped state files at ~/.claude/security_warnings_state_{session_id}.json. These are cleaned up automatically:

  • 10% chance per hook invocation: scans ~/.claude/ for state files older than 30 days and removes them
  • Manual cleanup: rm ~/.claude/security_warnings_state_*.json

6. Performance

Hook Execution Performance

Hook scripts run synchronously in the tool execution pipeline. Performance considerations:

  • Hookify regex caching: The RuleEngine uses functools.lru_cache(maxsize=128) for compiled regex patterns, avoiding re-compilation on repeated evaluations
  • Rule file scanning: config_loader.load_rules() scans .claude/hookify.*.local.md via glob.glob() on every hook invocation — keep the number of rule files reasonable (< 50)
  • Security-guidance state I/O: Each invocation reads/writes a JSON state file; this is fast for typical session sizes but could slow down with thousands of unique file-pattern combinations in a single session

Hook timeout guidelines:

  • Hooks should complete within 60 seconds (Claude Code enforces timeouts)
  • Avoid sleep, network calls, or long-running computations in hooks
  • The hook-linter checks for sleep [0-9]{3,} and while true patterns

Hookify Condition Evaluation

All conditions within a rule use AND logic — every condition must match for the rule to fire. Rules are evaluated sequentially; the first blocking rule short-circuits warning-only rules.

The field extraction path for each tool type:

Tool Fields Available
Bash command
Write file_path, content
Edit file_path, new_string/new_text, old_string/old_text, content
MultiEdit file_path, new_text/content (concatenated from all edits)
Stop event reason, transcript (reads from transcript_path file)
UserPromptSubmit user_prompt

7. Security

Security-Guidance Hook — Pattern Coverage

The security-guidance plugin implements a PreToolUse hook that intercepts Edit, Write, and MultiEdit operations. It checks both file paths and content against 9 built-in patterns:

# Rule Name Detection Method Vulnerability Class
1 github_actions_workflow Path match: .github/workflows/*.yml|yaml Command injection in CI/CD
2 child_process_exec Substring: child_process.exec, exec(, execSync( Shell injection
3 new_function_injection Substring: new Function Code injection
4 eval_injection Substring: eval( Arbitrary code execution
5 react_dangerously_set_html Substring: dangerouslySetInnerHTML XSS
6 document_write_xss Substring: document.write XSS
7 innerHTML_xss Substring: .innerHTML =, .innerHTML= XSS
8 pickle_deserialization Substring: pickle Deserialization RCE
9 os_system_injection Substring: os.system, from os import system Command injection

Caution

The security-guidance patterns use simple substring matching, not AST analysis. They will produce false positives (e.g., a comment mentioning eval() and may miss obfuscated patterns. They are a first-line warning system, not a security guarantee.

Session-scoped deduplication: Each warning fires once per unique {file_path}-{rule_name} combination per session. State is stored at ~/.claude/security_warnings_state_{session_id}.json.

Disabling: Set ENABLE_SECURITY_REMINDER=0 in the environment. The hook checks this variable on every invocation and exits immediately if disabled.

Hook Script Security Best Practices

The hook-linter (plugins/plugin-dev/skills/hook-development/scripts/hook-linter.sh) enforces these security checks:

Check Risk Mitigation
Unquoted variables Command/path injection Always use "$variable"
Missing set -euo pipefail Silent failures, undefined variables Add to every bash hook
Hardcoded absolute paths Portability, path traversal Use $CLAUDE_PLUGIN_ROOT or $CLAUDE_PROJECT_DIR
Missing shebang Unpredictable interpreter Always include #!/bin/bash or #!/usr/bin/env python3
Missing input validation Unexpected null/empty fields Check for empty values before processing
Error output not to stderr Error messages lost Use >&2 for all error output
Long-running operations Hook timeout, UX degradation Avoid sleep, network calls, loops

Sandbox Configuration Security Model

The sandbox settings control bash command execution:

  • sandbox.enabled: true — all Bash tool calls run in a sandboxed environment
  • sandbox.autoAllowBashIfSandboxed: false — even sandboxed commands require approval (defense in depth)
  • sandbox.allowUnsandboxedCommands: false — no escape from the sandbox
  • sandbox.network.* — fine-grained network access controls within the sandbox

Warning

The enableWeakerNestedSandbox setting reduces sandbox protections for nested operations. Only enable this if a specific tool requires it and you understand the security implications.

MDM Security Controls

Managed settings pushed via MDM take precedence over user-local settings:

  • disableBypassPermissionsMode: "disable" — prevents users from switching to a permissive mode
  • allowManagedPermissionRulesOnly: true — users cannot add their own permission rules
  • allowManagedHooksOnly: true — users cannot register their own hooks

These three settings together create a fully centrally-controlled Claude Code environment suitable for enterprise deployment.

8. Developer Internals

Repository Structure

anthropics/claude-code/
├── plugins/                          # Community plugins
│   ├── hookify/                      # Rule engine for markdown-based hooks
│   │   ├── core/                     # Python rule engine
│   │   │   ├── config_loader.py      # Rule file parser (YAML frontmatter + conditions)
│   │   │   └── rule_engine.py        # Condition evaluator (regex, contains, equals, etc.)
│   │   ├── commands/                 # Slash commands (hookify, configure, list, help)
│   │   ├── hooks/                    # Hook entry points (pretooluse.py, posttooluse.py, stop.py, userpromptsubmit.py)
│   │   ├── matchers/                 # Tool matching logic
│   │   ├── agents/                   # Conversation analyzer agent
│   │   ├── skills/                   # Writing rules skill
│   │   ├── utils/                    # Shared utilities
│   │   └── examples/                 # Example rule files
│   ├── security-guidance/            # Security pattern detection
│   │   └── hooks/                    # hooks.json + security_reminder_hook.py
│   ├── code-review/                  # Code review command
│   ├── pr-review-toolkit/            # PR review agents + command
│   ├── commit-commands/              # Git workflow commands
│   ├── feature-dev/                  # Feature development agents + command
│   ├── plugin-dev/                   # Plugin development toolkit
│   │   ├── commands/                 # create-plugin command
│   │   ├── agents/                   # agent-creator, plugin-validator, skill-reviewer
│   │   └── skills/                   # 7 skills covering every plugin component type
│   ├── agent-sdk-dev/                # Agent SDK development
│   ├── ralph-wiggum/                 # Looping task automation
│   ├── explanatory-output-style/     # Explanatory output SessionStart hook
│   ├── learning-output-style/        # Learning output SessionStart hook
│   ├── claude-opus-4-5-migration/    # Model migration skill
│   └── frontend-design/             # Frontend design skill
├── examples/
│   ├── hooks/                        # Example hook scripts
│   ├── settings/                     # Settings presets (strict, lax, sandbox)
│   └── mdm/                         # MDM deployment templates
│       ├── macos/                    # plist + mobileconfig
│       └── windows/                  # ADMX + ADML + PowerShell
├── Script/                           # DevContainer automation (PowerShell)
├── scripts/                          # Issue management automation (TypeScript/Bash)
├── README.md
├── CHANGELOG.md
├── LICENSE.md
└── SECURITY.md

Module Reference

plugins/hookify/core/config_loader.py

The configuration loader responsible for parsing hookify rule files.

Classes:

Class Description
Condition Dataclass representing a single match condition (field, operator, pattern)
Rule Dataclass representing a complete hookify rule (name, enabled, event, conditions, action, message)

Key functions:

Function Signature Description
extract_frontmatter (content: str) → tuple[Dict, str] Parses YAML frontmatter from markdown content. Handles simple key-value pairs, list items, and multi-line dictionary items within lists. Returns (frontmatter_dict, message_body).
load_rules (event: Optional[str]) → List[Rule] Scans .claude/hookify.*.local.md files via glob.glob(). Filters by event type and enabled status. Returns list of Rule objects.
load_rule_file (file_path: str) → Optional[Rule] Loads and parses a single rule file. Returns None on parse errors (with stderr warning).

Frontmatter parsing details:

The extract_frontmatter function implements a custom YAML parser (not a full YAML library) that handles:

  • Simple key: value pairs (with boolean coercion for true/false)
  • List items (- item)
  • Inline dict list items (- field: command, operator: regex_match)
  • Multi-line dict list items (indented continuation lines)
  • String unquoting (strips surrounding " and ')

Legacy pattern conversion: When a rule uses the legacy pattern field instead of conditions, the loader auto-converts it into a Condition with operator: regex_match. The inferred field depends on the event type: bash → command, file → new_text, other → content.

plugins/hookify/core/rule_engine.py

The evaluation engine that matches rules against hook input data.

Class: RuleEngine

Method Signature Description
evaluate_rules (rules: List[Rule], input_data: Dict) → Dict Evaluates all rules against input. Blocking rules take priority. Returns response dict with systemMessage, hookSpecificOutput, and/or decision. Returns {} if no rules match.
_rule_matches (rule: Rule, input_data: Dict) → bool Checks tool matcher, then evaluates all conditions (AND logic). Rules with no conditions never match.
_matches_tool (matcher: str, tool_name: str) → bool Supports * (match all) and |-separated alternatives.
_check_condition (condition, tool_name, tool_input, input_data) → bool Extracts field value and applies operator.
_extract_field (field, tool_name, tool_input, input_data) → Optional[str] Field extraction with tool-specific logic (see Performance section).
_regex_match (pattern: str, text: str) → bool Cached regex evaluation via compile_regex().

Global function:

Function Description
compile_regex(pattern: str) → re.Pattern @lru_cache(maxsize=128) — compiles and caches regex patterns with re.IGNORECASE.

Blocking response format by event type:

Event Response Structure
Stop {"decision": "block", "reason": "...", "systemMessage": "..."}
PreToolUse / PostToolUse {"hookSpecificOutput": {"hookEventName": "...", "permissionDecision": "deny"}, "systemMessage": "..."}
Other events {"systemMessage": "..."}

plugins/security-guidance/hooks/security_reminder_hook.py

Standalone Python hook script (no imports from hookify — self-contained).

Functions:

Function Description
debug_log(message) Appends timestamped debug messages to /tmp/security-warnings-log.txt
get_state_file(session_id) Returns ~/.claude/security_warnings_state_{session_id}.json
cleanup_old_state_files() Removes state files older than 30 days from ~/.claude/
load_state(session_id) Loads shown warning keys from session state file
save_state(session_id, shown_warnings) Persists shown warning keys to session state file
check_patterns(file_path, content) Iterates SECURITY_PATTERNS list — checks path-based then content-based patterns. Returns (rule_name, reminder) or (None, None).
extract_content_from_input(tool_name, tool_input) Extracts checkable content: Write → content, Edit → new_string, MultiEdit → concatenated new_string values
main() Entry point: reads JSON from stdin, checks patterns, manages session state, exits 0 (allow) or 2 (block with warning)

Pattern matching order: Patterns are evaluated in definition order. The first match wins — subsequent patterns for the same file are not checked in that invocation.

Code Patterns and Conventions

Plugin structure convention:

Every plugin follows this directory layout:

plugin-name/
├── README.md              # Plugin documentation (required)
├── commands/              # Slash commands as .md files
├── agents/                # Agent definitions as .md files
├── skills/                # Skill packs
│   └── skill-name/
│       ├── SKILL.md       # Core skill content
│       ├── references/    # Deep-dive documentation
│       └── examples/      # Working examples
├── hooks/
│   ├── hooks.json         # Event subscriptions
│   └── *.py / *.sh        # Hook scripts
└── scripts/               # Utility scripts (not auto-discovered)

Path portability: All hook configurations use ${CLAUDE_PLUGIN_ROOT} for plugin-relative paths rather than hardcoded absolute paths. This makes plugins portable across machines and users.

Hook script patterns:

  • All bash hooks start with set -euo pipefail
  • Input is read from stdin (input=$(cat) for bash, sys.stdin.read() for Python)
  • JSON parsing uses jq in bash, json.loads() in Python
  • Exit code 0 = allow, 1 = error (user-visible), 2 = block (Claude-visible)
  • Error output goes to stderr (>&2 in bash, file=sys.stderr in Python)

Progressive disclosure in skills:

Skills use a three-tier structure to manage context window usage:

  1. SKILL.md (~1,500-2,500 words) — core concepts, loaded automatically
  2. references/ — detailed specifications, loaded on demand
  3. examples/ — working code examples, loaded on demand

Hookify conditions inline format:

conditions:
  - field: command, operator: regex_match, pattern: "rm\\s+-rf"

Or multi-line:

conditions:
  - field: command
    operator: regex_match
    pattern: "rm\\s+-rf"

Both formats are supported by the custom YAML parser in config_loader.py.

Testing

Hook testing tools:

Tool Path Purpose
hook-linter.sh plugins/plugin-dev/skills/hook-development/scripts/ Static analysis of hook scripts
test-hook.sh plugins/plugin-dev/skills/hook-development/scripts/ Runtime testing with sample input
validate-hook-schema.sh plugins/plugin-dev/skills/hook-development/scripts/ Validate hooks.json structure

Testing workflow:

  1. Lint: ./hook-linter.sh my-hook.sh
  2. Generate sample input: ./test-hook.sh --create-sample PreToolUse > test-input.json
  3. Test: ./test-hook.sh -v my-hook.sh test-input.json
  4. Validate config: ./validate-hook-schema.sh hooks/hooks.json
  5. Integration test: claude --debug

Unit testing (hookify core):

Both config_loader.py and rule_engine.py include if __name__ == '__main__': blocks with inline test cases:

  • config_loader.py: Tests frontmatter parsing with a simple rule and outputs parsed frontmatter, message, and Rule object
  • rule_engine.py: Tests rule evaluation against matching and non-matching Bash inputs

Potential Improvements

  • Full YAML parser: The custom YAML parser in config_loader.py handles a subset of YAML. Using PyYAML would add robustness for edge cases (nested structures, multiline strings, anchors)
  • Async hook evaluation: Hooks currently run synchronously. Parallel evaluation would reduce latency when multiple plugins register hooks for the same event
  • Hook testing framework: The shell-based testing scripts could be complemented by a Python test suite with proper assertions and CI integration
  • Plugin manifest (plugin.json): The plugin-dev skill references a plugin.json manifest format, but the existing plugins in this repository don't use it — they rely on convention-based discovery. Formalizing this would enable dependency management and version pinning
  • Security pattern extensibility: The security-guidance hook's patterns are hardcoded. A configuration file (similar to hookify rules) would allow admins to add custom patterns without modifying the Python script

Contributing

Plugin contributions:

  1. Create a new directory under plugins/ following the standard structure
  2. Include a README.md with plugin description, usage, and examples
  3. If adding hooks: include hooks.json and use ${CLAUDE_PLUGIN_ROOT} for paths
  4. Lint hook scripts with hook-linter.sh
  5. Test hooks with test-hook.sh
  6. Submit a pull request

Code style:

  • Python: Standard library only (no external dependencies beyond what Claude Code provides)
  • Bash: Always set -euo pipefail, quote all variables, use jq for JSON
  • Markdown: YAML frontmatter for metadata, content body for prompts/messages
  • JSON: 2-space indentation, no trailing commas

9. Integration Points

MCP Server Integration

Plugins can bundle MCP server configurations for three transport types:

Transport Config Location Use Case
stdio Plugin mcpServers config Local tools (filesystem, database, custom scripts)
SSE Plugin mcpServers config Hosted cloud services (Asana, GitHub)
HTTP Plugin mcpServers config REST APIs with authentication

Environment variable substitution (${VAR_NAME}) is supported in all MCP config fields, enabling secrets to be injected at runtime without hardcoding.

Claude Code Runtime Integration

Integration Point Mechanism Example
Slash commands Markdown files in commands/ /code-review, /commit, /review-pr
Sub-agents Markdown files in agents/ code-architect, code-reviewer, plugin-validator
Knowledge packs SKILL.md in skills/ Plugin structure, hook development, MCP integration
Event hooks hooks.json + scripts in hooks/ Security checks, output style, bash validation
Environment $CLAUDE_ENV_FILE writes in SessionStart hooks Project type detection, CI detection
Settings JSON files applied via MDM or manual copy Permission rules, sandbox config

External Dependencies

This repository has zero runtime package dependencies. All code uses language standard libraries:

  • Python hooks: json, os, sys, re, glob, random, datetime, functools, dataclasses, typing
  • Bash hooks: jq (recommended but not strictly required), cat, echo, grep, sed
  • TypeScript scripts (issue management only): requires Node.js runtime