mirror of
https://github.com/anthropics/claude-code.git
synced 2025-11-28 08:40:27 +08:00
Adds the plugin-dev plugin to public marketplace. A comprehensive toolkit for
developing Claude Code plugins with 7 expert skills, 3 AI-assisted agents, and
extensive documentation covering the complete plugin development lifecycle.
Key features:
- 7 skills: hook-development, mcp-integration, plugin-structure, plugin-settings,
command-development, agent-development, skill-development
- 3 agents: agent-creator (AI-assisted generation), plugin-validator (structure
validation), skill-reviewer (quality review)
- 1 command: /plugin-dev:create-plugin (guided 8-phase workflow)
- 10 utility scripts for validation and testing
- 21 reference docs with deep-dive guidance (~11k words)
- 9 working examples demonstrating best practices
Changes for public release:
- Replaced all references to internal repositories with "Claude Code"
- Updated MCP examples: internal.company.com → api.example.com
- Updated token variables: ${INTERNAL_TOKEN} → ${API_TOKEN}
- Reframed agent-creation-system-prompt as "proven in production"
- Preserved all ${CLAUDE_PLUGIN_ROOT} references (186 total)
- Preserved valuable test blocks in core modules
Validation:
- All 3 agents validated successfully with validate-agent.sh
- All JSON files validated with jq
- Zero internal references remaining
- 59 files migrated, 21,971 lines added
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
544 lines
12 KiB
Markdown
544 lines
12 KiB
Markdown
---
|
|
name: Plugin Settings
|
|
description: This skill should be used when the user asks about "plugin settings", "store plugin configuration", "user-configurable plugin", ".local.md files", "plugin state files", "read YAML frontmatter", "per-project plugin settings", or wants to make plugin behavior configurable. Documents the .claude/plugin-name.local.md pattern for storing plugin-specific configuration with YAML frontmatter and markdown content.
|
|
version: 0.1.0
|
|
---
|
|
|
|
# Plugin Settings Pattern for Claude Code Plugins
|
|
|
|
## Overview
|
|
|
|
Plugins can store user-configurable settings and state in `.claude/plugin-name.local.md` files within the project directory. This pattern uses YAML frontmatter for structured configuration and markdown content for prompts or additional context.
|
|
|
|
**Key characteristics:**
|
|
- File location: `.claude/plugin-name.local.md` in project root
|
|
- Structure: YAML frontmatter + markdown body
|
|
- Purpose: Per-project plugin configuration and state
|
|
- Usage: Read from hooks, commands, and agents
|
|
- Lifecycle: User-managed (not in git, should be in `.gitignore`)
|
|
|
|
## File Structure
|
|
|
|
### Basic Template
|
|
|
|
```markdown
|
|
---
|
|
enabled: true
|
|
setting1: value1
|
|
setting2: value2
|
|
numeric_setting: 42
|
|
list_setting: ["item1", "item2"]
|
|
---
|
|
|
|
# Additional Context
|
|
|
|
This markdown body can contain:
|
|
- Task descriptions
|
|
- Additional instructions
|
|
- Prompts to feed back to Claude
|
|
- Documentation or notes
|
|
```
|
|
|
|
### Example: Plugin State File
|
|
|
|
**.claude/my-plugin.local.md:**
|
|
```markdown
|
|
---
|
|
enabled: true
|
|
strict_mode: false
|
|
max_retries: 3
|
|
notification_level: info
|
|
coordinator_session: team-leader
|
|
---
|
|
|
|
# Plugin Configuration
|
|
|
|
This plugin is configured for standard validation mode.
|
|
Contact @team-lead with questions.
|
|
```
|
|
|
|
## Reading Settings Files
|
|
|
|
### From Hooks (Bash Scripts)
|
|
|
|
**Pattern: Check existence and parse frontmatter**
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Define state file path
|
|
STATE_FILE=".claude/my-plugin.local.md"
|
|
|
|
# Quick exit if file doesn't exist
|
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
exit 0 # Plugin not configured, skip
|
|
fi
|
|
|
|
# Parse YAML frontmatter (between --- markers)
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$STATE_FILE")
|
|
|
|
# Extract individual fields
|
|
ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
STRICT_MODE=$(echo "$FRONTMATTER" | grep '^strict_mode:' | sed 's/strict_mode: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
|
|
# Check if enabled
|
|
if [[ "$ENABLED" != "true" ]]; then
|
|
exit 0 # Disabled
|
|
fi
|
|
|
|
# Use configuration in hook logic
|
|
if [[ "$STRICT_MODE" == "true" ]]; then
|
|
# Apply strict validation
|
|
# ...
|
|
fi
|
|
```
|
|
|
|
See `examples/read-settings-hook.sh` for complete working example.
|
|
|
|
### From Commands
|
|
|
|
Commands can read settings files to customize behavior:
|
|
|
|
```markdown
|
|
---
|
|
description: Process data with plugin
|
|
allowed-tools: ["Read", "Bash"]
|
|
---
|
|
|
|
# Process Command
|
|
|
|
Steps:
|
|
1. Check if settings exist at `.claude/my-plugin.local.md`
|
|
2. Read configuration using Read tool
|
|
3. Parse YAML frontmatter to extract settings
|
|
4. Apply settings to processing logic
|
|
5. Execute with configured behavior
|
|
```
|
|
|
|
### From Agents
|
|
|
|
Agents can reference settings in their instructions:
|
|
|
|
```markdown
|
|
---
|
|
name: configured-agent
|
|
description: Agent that adapts to project settings
|
|
---
|
|
|
|
Check for plugin settings at `.claude/my-plugin.local.md`.
|
|
If present, parse YAML frontmatter and adapt behavior according to:
|
|
- enabled: Whether plugin is active
|
|
- mode: Processing mode (strict, standard, lenient)
|
|
- Additional configuration fields
|
|
```
|
|
|
|
## Parsing Techniques
|
|
|
|
### Extract Frontmatter
|
|
|
|
```bash
|
|
# Extract everything between --- markers
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
|
|
```
|
|
|
|
### Read Individual Fields
|
|
|
|
**String fields:**
|
|
```bash
|
|
VALUE=$(echo "$FRONTMATTER" | grep '^field_name:' | sed 's/field_name: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
```
|
|
|
|
**Boolean fields:**
|
|
```bash
|
|
ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
|
|
# Compare: if [[ "$ENABLED" == "true" ]]; then
|
|
```
|
|
|
|
**Numeric fields:**
|
|
```bash
|
|
MAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//')
|
|
# Use: if [[ $MAX -gt 100 ]]; then
|
|
```
|
|
|
|
### Read Markdown Body
|
|
|
|
Extract content after second `---`:
|
|
|
|
```bash
|
|
# Get everything after closing ---
|
|
BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Pattern 1: Temporarily Active Hooks
|
|
|
|
Use settings file to control hook activation:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
STATE_FILE=".claude/security-scan.local.md"
|
|
|
|
# Quick exit if not configured
|
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Read enabled flag
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$STATE_FILE")
|
|
ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
|
|
|
|
if [[ "$ENABLED" != "true" ]]; then
|
|
exit 0 # Disabled
|
|
fi
|
|
|
|
# Run hook logic
|
|
# ...
|
|
```
|
|
|
|
**Use case:** Enable/disable hooks without editing hooks.json (requires restart).
|
|
|
|
### Pattern 2: Agent State Management
|
|
|
|
Store agent-specific state and configuration:
|
|
|
|
**.claude/multi-agent-swarm.local.md:**
|
|
```markdown
|
|
---
|
|
agent_name: auth-agent
|
|
task_number: 3.5
|
|
pr_number: 1234
|
|
coordinator_session: team-leader
|
|
enabled: true
|
|
dependencies: ["Task 3.4"]
|
|
---
|
|
|
|
# Task Assignment
|
|
|
|
Implement JWT authentication for the API.
|
|
|
|
**Success Criteria:**
|
|
- Authentication endpoints created
|
|
- Tests passing
|
|
- PR created and CI green
|
|
```
|
|
|
|
Read from hooks to coordinate agents:
|
|
|
|
```bash
|
|
AGENT_NAME=$(echo "$FRONTMATTER" | grep '^agent_name:' | sed 's/agent_name: *//')
|
|
COORDINATOR=$(echo "$FRONTMATTER" | grep '^coordinator_session:' | sed 's/coordinator_session: *//')
|
|
|
|
# Send notification to coordinator
|
|
tmux send-keys -t "$COORDINATOR" "Agent $AGENT_NAME completed task" Enter
|
|
```
|
|
|
|
### Pattern 3: Configuration-Driven Behavior
|
|
|
|
**.claude/my-plugin.local.md:**
|
|
```markdown
|
|
---
|
|
validation_level: strict
|
|
max_file_size: 1000000
|
|
allowed_extensions: [".js", ".ts", ".tsx"]
|
|
enable_logging: true
|
|
---
|
|
|
|
# Validation Configuration
|
|
|
|
Strict mode enabled for this project.
|
|
All writes validated against security policies.
|
|
```
|
|
|
|
Use in hooks or commands:
|
|
|
|
```bash
|
|
LEVEL=$(echo "$FRONTMATTER" | grep '^validation_level:' | sed 's/validation_level: *//')
|
|
|
|
case "$LEVEL" in
|
|
strict)
|
|
# Apply strict validation
|
|
;;
|
|
standard)
|
|
# Apply standard validation
|
|
;;
|
|
lenient)
|
|
# Apply lenient validation
|
|
;;
|
|
esac
|
|
```
|
|
|
|
## Creating Settings Files
|
|
|
|
### From Commands
|
|
|
|
Commands can create settings files:
|
|
|
|
```markdown
|
|
# Setup Command
|
|
|
|
Steps:
|
|
1. Ask user for configuration preferences
|
|
2. Create `.claude/my-plugin.local.md` with YAML frontmatter
|
|
3. Set appropriate values based on user input
|
|
4. Inform user that settings are saved
|
|
5. Remind user to restart Claude Code for hooks to recognize changes
|
|
```
|
|
|
|
### Template Generation
|
|
|
|
Provide template in plugin README:
|
|
|
|
```markdown
|
|
## Configuration
|
|
|
|
Create `.claude/my-plugin.local.md` in your project:
|
|
|
|
\`\`\`markdown
|
|
---
|
|
enabled: true
|
|
mode: standard
|
|
max_retries: 3
|
|
---
|
|
|
|
# Plugin Configuration
|
|
|
|
Your settings are active.
|
|
\`\`\`
|
|
|
|
After creating or editing, restart Claude Code for changes to take effect.
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### File Naming
|
|
|
|
✅ **DO:**
|
|
- Use `.claude/plugin-name.local.md` format
|
|
- Match plugin name exactly
|
|
- Use `.local.md` suffix for user-local files
|
|
|
|
❌ **DON'T:**
|
|
- Use different directory (not `.claude/`)
|
|
- Use inconsistent naming
|
|
- Use `.md` without `.local` (might be committed)
|
|
|
|
### Gitignore
|
|
|
|
Always add to `.gitignore`:
|
|
|
|
```gitignore
|
|
.claude/*.local.md
|
|
.claude/*.local.json
|
|
```
|
|
|
|
Document this in plugin README.
|
|
|
|
### Defaults
|
|
|
|
Provide sensible defaults when settings file doesn't exist:
|
|
|
|
```bash
|
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
# Use defaults
|
|
ENABLED=true
|
|
MODE=standard
|
|
else
|
|
# Read from file
|
|
# ...
|
|
fi
|
|
```
|
|
|
|
### Validation
|
|
|
|
Validate settings values:
|
|
|
|
```bash
|
|
MAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//')
|
|
|
|
# Validate numeric range
|
|
if ! [[ "$MAX" =~ ^[0-9]+$ ]] || [[ $MAX -lt 1 ]] || [[ $MAX -gt 100 ]]; then
|
|
echo "⚠️ Invalid max_value in settings (must be 1-100)" >&2
|
|
MAX=10 # Use default
|
|
fi
|
|
```
|
|
|
|
### Restart Requirement
|
|
|
|
**Important:** Settings changes require Claude Code restart.
|
|
|
|
Document in your README:
|
|
|
|
```markdown
|
|
## Changing Settings
|
|
|
|
After editing `.claude/my-plugin.local.md`:
|
|
1. Save the file
|
|
2. Exit Claude Code
|
|
3. Restart: `claude` or `cc`
|
|
4. New settings will be loaded
|
|
```
|
|
|
|
Hooks cannot be hot-swapped within a session.
|
|
|
|
## Security Considerations
|
|
|
|
### Sanitize User Input
|
|
|
|
When writing settings files from user input:
|
|
|
|
```bash
|
|
# Escape quotes in user input
|
|
SAFE_VALUE=$(echo "$USER_INPUT" | sed 's/"/\\"/g')
|
|
|
|
# Write to file
|
|
cat > "$STATE_FILE" <<EOF
|
|
---
|
|
user_setting: "$SAFE_VALUE"
|
|
---
|
|
EOF
|
|
```
|
|
|
|
### Validate File Paths
|
|
|
|
If settings contain file paths:
|
|
|
|
```bash
|
|
FILE_PATH=$(echo "$FRONTMATTER" | grep '^data_file:' | sed 's/data_file: *//')
|
|
|
|
# Check for path traversal
|
|
if [[ "$FILE_PATH" == *".."* ]]; then
|
|
echo "⚠️ Invalid path in settings (path traversal)" >&2
|
|
exit 2
|
|
fi
|
|
```
|
|
|
|
### Permissions
|
|
|
|
Settings files should be:
|
|
- Readable by user only (`chmod 600`)
|
|
- Not committed to git
|
|
- Not shared between users
|
|
|
|
## Real-World Examples
|
|
|
|
### multi-agent-swarm Plugin
|
|
|
|
**.claude/multi-agent-swarm.local.md:**
|
|
```markdown
|
|
---
|
|
agent_name: auth-implementation
|
|
task_number: 3.5
|
|
pr_number: 1234
|
|
coordinator_session: team-leader
|
|
enabled: true
|
|
dependencies: ["Task 3.4"]
|
|
additional_instructions: Use JWT tokens, not sessions
|
|
---
|
|
|
|
# Task: Implement Authentication
|
|
|
|
Build JWT-based authentication for the REST API.
|
|
Coordinate with auth-agent on shared types.
|
|
```
|
|
|
|
**Hook usage (agent-stop-notification.sh):**
|
|
- Checks if file exists (line 15-18: quick exit if not)
|
|
- Parses frontmatter to get coordinator_session, agent_name, enabled
|
|
- Sends notifications to coordinator if enabled
|
|
- Allows quick activation/deactivation via `enabled: true/false`
|
|
|
|
### ralph-wiggum Plugin
|
|
|
|
**.claude/ralph-loop.local.md:**
|
|
```markdown
|
|
---
|
|
iteration: 1
|
|
max_iterations: 10
|
|
completion_promise: "All tests passing and build successful"
|
|
---
|
|
|
|
Fix all the linting errors in the project.
|
|
Make sure tests pass after each fix.
|
|
```
|
|
|
|
**Hook usage (stop-hook.sh):**
|
|
- Checks if file exists (line 15-18: quick exit if not active)
|
|
- Reads iteration count and max_iterations
|
|
- Extracts completion_promise for loop termination
|
|
- Reads body as the prompt to feed back
|
|
- Updates iteration count on each loop
|
|
|
|
## Quick Reference
|
|
|
|
### File Location
|
|
|
|
```
|
|
project-root/
|
|
└── .claude/
|
|
└── plugin-name.local.md
|
|
```
|
|
|
|
### Frontmatter Parsing
|
|
|
|
```bash
|
|
# Extract frontmatter
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
|
|
|
|
# Read field
|
|
VALUE=$(echo "$FRONTMATTER" | grep '^field:' | sed 's/field: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
```
|
|
|
|
### Body Parsing
|
|
|
|
```bash
|
|
# Extract body (after second ---)
|
|
BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
|
|
```
|
|
|
|
### Quick Exit Pattern
|
|
|
|
```bash
|
|
if [[ ! -f ".claude/my-plugin.local.md" ]]; then
|
|
exit 0 # Not configured
|
|
fi
|
|
```
|
|
|
|
## Additional Resources
|
|
|
|
### Reference Files
|
|
|
|
For detailed implementation patterns:
|
|
|
|
- **`references/parsing-techniques.md`** - Complete guide to parsing YAML frontmatter and markdown bodies
|
|
- **`references/real-world-examples.md`** - Deep dive into multi-agent-swarm and ralph-wiggum implementations
|
|
|
|
### Example Files
|
|
|
|
Working examples in `examples/`:
|
|
|
|
- **`read-settings-hook.sh`** - Hook that reads and uses settings
|
|
- **`create-settings-command.md`** - Command that creates settings file
|
|
- **`example-settings.md`** - Template settings file
|
|
|
|
### Utility Scripts
|
|
|
|
Development tools in `scripts/`:
|
|
|
|
- **`validate-settings.sh`** - Validate settings file structure
|
|
- **`parse-frontmatter.sh`** - Extract frontmatter fields
|
|
|
|
## Implementation Workflow
|
|
|
|
To add settings to a plugin:
|
|
|
|
1. Design settings schema (which fields, types, defaults)
|
|
2. Create template file in plugin documentation
|
|
3. Add gitignore entry for `.claude/*.local.md`
|
|
4. Implement settings parsing in hooks/commands
|
|
5. Use quick-exit pattern (check file exists, check enabled field)
|
|
6. Document settings in plugin README with template
|
|
7. Remind users that changes require Claude Code restart
|
|
|
|
Focus on keeping settings simple and providing good defaults when settings file doesn't exist.
|