plugin-settings
SKILL.md
Plugin Settings Pattern
Per-project plugin configuration using .claude/plugin-name.local.md files with YAML frontmatter for structured settings and markdown body for additional context.
When to Use This Skill
| Use plugin settings when... | Use alternatives when... |
|---|---|
| Plugin needs per-project configuration | Settings are global (use ~/.claude/settings.json) |
| Hooks need runtime enable/disable control | Hook behavior is always-on |
| Agent state persists between sessions | State is ephemeral within a session |
| Users customize plugin behavior per-project | Plugin has no configurable behavior |
| Configuration includes prose/prompts alongside structured data | All config is purely structured (use .json) |
File Structure
Location
project-root/
└── .claude/
└── plugin-name.local.md # Per-project, user-local settings
Format
---
enabled: true
mode: standard
max_retries: 3
allowed_extensions: [".js", ".ts", ".tsx"]
---
# Additional Context
Markdown body for prompts, instructions, or documentation
that hooks and agents can read and use.
Naming Convention
- Use
.claude/plugin-name.local.mdformat - Match the plugin name exactly from
plugin.json - The
.local.mdsuffix signals user-local (not committed to git)
Gitignore
Add to project .gitignore:
.claude/*.local.md
Reading Settings
From Shell Scripts (Hooks)
Use the standard frontmatter extraction pattern from .claude/rules/shell-scripting.md:
#!/bin/bash
set -euo pipefail
STATE_FILE=".claude/my-plugin.local.md"
# Quick exit if not configured
[[ -f "$STATE_FILE" ]] || exit 0
# Extract field using standard pattern
extract_field() {
local file="$1" field="$2"
head -50 "$file" | grep -m1 "^${field}:" | sed 's/^[^:]*:[[:space:]]*//' | tr -d '\r'
}
plugin_enabled=$(extract_field "$STATE_FILE" "enabled")
[[ "$plugin_enabled" == "true" ]] || exit 0
plugin_mode=$(extract_field "$STATE_FILE" "mode")
Extract Markdown Body
# Get content after the closing --- frontmatter delimiter
BODY=$(awk '/^---$/{i++; next} i>=2' "$STATE_FILE")
From Skills and Agents
Skills and agents read settings with the Read tool:
1. Check if `.claude/my-plugin.local.md` exists
2. Read the file and parse YAML frontmatter
3. Apply settings to current behavior
4. Use markdown body as additional context/prompt
Common Patterns
Pattern 1: Toggle-Based Hook Activation
Control hook activation without editing hooks.json:
#!/bin/bash
set -euo pipefail
STATE_FILE=".claude/security-scan.local.md"
[[ -f "$STATE_FILE" ]] || exit 0
extract_field() {
local file="$1" field="$2"
head -50 "$file" | grep -m1 "^${field}:" | sed 's/^[^:]*:[[:space:]]*//' | tr -d '\r'
}
scan_enabled=$(extract_field "$STATE_FILE" "enabled")
[[ "$scan_enabled" == "true" ]] || exit 0
# Hook logic runs only when enabled
Pattern 2: Agent State Between Sessions
Store agent task state for multi-session work:
---
agent_name: auth-implementation
task_number: 3.5
pr_number: 1234
enabled: true
---
# Current Task
Implement JWT authentication for the REST API.
Coordinate with auth-agent on shared types.
Pattern 3: Configuration-Driven Validation
---
validation_level: strict
max_file_size: 1000000
allowed_extensions: [".js", ".ts", ".tsx"]
---
validation_level=$(extract_field "$STATE_FILE" "validation_level")
case "$validation_level" in
strict) run_strict_checks ;;
standard) run_standard_checks ;;
*) run_standard_checks ;; # Default
esac
Implementation Checklist
When adding settings to a plugin:
- Design settings schema (fields, types, defaults)
- Create template in plugin README
- Add
.claude/*.local.mdto.gitignore - Implement parsing using
extract_fieldpattern - Use quick-exit pattern (
[[ -f "$STATE_FILE" ]] || exit 0) - Provide sensible defaults when file is missing
- Document that changes require Claude Code restart (hooks only)
Best Practices
| Practice | Details |
|---|---|
| Quick exit | Check file existence first, exit 0 if absent |
| Sensible defaults | Provide fallback values when settings file is missing |
Use extract_field |
Standard frontmatter extraction from shell-scripting.md |
| Validate values | Check numeric ranges, enum membership |
| File permissions | Settings files should be user-readable only (chmod 600) |
| Restart notice | Document that hook-related changes need a Claude Code restart |
Agentic Optimizations
| Context | Command |
|---|---|
| Check settings exist | [[ -f ".claude/plugin.local.md" ]] |
| Extract single field | head -50 file | grep -m1 "^field:" | sed 's/^[^:]*:[[:space:]]*//' |
| Extract body | awk '/^---$/{i++; next} i>=2' file |
| Quick enable check | [[ "$(extract_field file enabled)" == "true" ]] |
Weekly Installs
3
Repository
laurigates/clau…-pluginsGitHub Stars
13
First Seen
6 days ago
Security Audits
Installed on
openclaw3
gemini-cli3
github-copilot3
codex3
kimi-cli3
cursor3