npx skills add ...
npx skills add anthropics/claude-plugins-public --skill plugin-settings
npx skills add anthropics/claude-plugins-public --skill plugin-settings
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.
The same skill content is published under more than one repo. The install counts are split across them; any of these commands works.
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:
.claude/plugin-name.local.md in project root.gitignore).claude/my-plugin.local.md:
Pattern: Check existence and parse frontmatter
See examples/read-settings-hook.sh for complete working example.
Commands can read settings files to customize behavior:
Agents can reference settings in their instructions:
String fields:
Boolean fields:
Numeric fields:
Extract content after second ---:
Use settings file to control hook activation:
Use case: Enable/disable hooks without editing hooks.json (requires restart).
Store agent-specific state and configuration:
.claude/multi-agent-swarm.local.md:
Read from hooks to coordinate agents:
.claude/my-plugin.local.md:
Use in hooks or commands:
Commands can create settings files:
Provide template in plugin README:
✅ DO:
.claude/plugin-name.local.md format.local.md suffix for user-local files❌ DON'T:
.claude/).md without .local (might be committed)Always add to .gitignore:
Document this in plugin README.
Provide sensible defaults when settings file doesn't exist:
Validate settings values:
Important: Settings changes require Claude Code restart.
Document in your README:
Hooks cannot be hot-swapped within a session.
When writing settings files from user input:
If settings contain file paths:
Settings files should be:
chmod 600).claude/multi-agent-swarm.local.md:
Hook usage (agent-stop-notification.sh):
enabled: true/false.claude/ralph-loop.local.md:
Hook usage (stop-hook.sh):
For detailed implementation patterns:
references/parsing-techniques.md - Complete guide to parsing YAML frontmatter and markdown bodiesreferences/real-world-examples.md - Deep dive into multi-agent-swarm and ralph-loop implementationsWorking examples in examples/:
read-settings-hook.sh - Hook that reads and uses settingscreate-settings-command.md - Command that creates settings fileexample-settings.md - Template settings fileDevelopment tools in scripts/:
validate-settings.sh - Validate settings file structureparse-frontmatter.sh - Extract frontmatter fieldsTo add settings to a plugin:
.claude/*.local.mdFocus on keeping settings simple and providing good defaults when settings file doesn't exist.
---
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.#!/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---
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---
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# Extract everything between --- markers
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")VALUE=$(echo "$FRONTMATTER" | grep '^field_name:' | sed 's/field_name: *//' | sed 's/^"\(.*\)"$/\1/')ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
# Compare: if [[ "$ENABLED" == "true" ]]; thenMAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//')
# Use: if [[ $MAX -gt 100 ]]; then# Get everything after closing ---
BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")#!/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
# ...---
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 greenAGENT_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---
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.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# 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## 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..claude/*.local.md
.claude/*.local.jsonif [[ ! -f "$STATE_FILE" ]]; then
# Use defaults
ENABLED=true
MODE=standard
else
# Read from file
# ...
fiMAX=$(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## 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# Escape quotes in user input
SAFE_VALUE=$(echo "$USER_INPUT" | sed 's/"/\\"/g')
# Write to file
cat > "$STATE_FILE" <<EOF
---
user_setting: "$SAFE_VALUE"
---
EOFFILE_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---
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.---
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.project-root/
└── .claude/
└── plugin-name.local.md# Extract frontmatter
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
# Read field
VALUE=$(echo "$FRONTMATTER" | grep '^field:' | sed 's/field: *//' | sed 's/^"\(.*\)"$/\1/')# Extract body (after second ---)
BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")if [[ ! -f ".claude/my-plugin.local.md" ]]; then
exit 0 # Not configured
fi