Configure per-project plugin settings via .claude/plugin-name.local.md files. Use when building plugins with user-configurable behavior, storing agent state, or controlling hooks.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add laurigates/claude-plugins --skill plugin-settings --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Plugin Settings?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/laurigates-plugin-settings)More formats (shields.io, HTML) on the badges page.
---
name: plugin-settings
description: Configure per-project plugin settings via .claude/plugin-name.local.md files. Use when building plugins with user-configurable behavior, storing agent state, or controlling hooks.
user-invocable: false
allowed-tools: Bash, Read, Write, Edit, Grep, Glob, TodoWrite
created: 2026-03-06
modified: 2026-07-28
compatibility: claude-code
reviewed: 2026-03-06
---
# 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.
Reach for a different mechanism when the settings are **global** (`~/.claude/settings.json`) or **purely structured** with no prose/prompt content (a plain `.json` file). The `.local.md` form earns its keep when config must carry prompts or instructions alongside structured fields.
## File Structure
### Location
```
project-root/
└── .claude/
└── plugin-name.local.md # Per-project, user-local settings
```
### Format
```markdown
---
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.md` format
- Match the plugin name exactly from `plugin.json`
- The `.local.md` suffix signals user-local (not committed to git)
### Gitignore
Add to project `.gitignore`:
```gitignore
.claude/*.local.md
```
## Reading Settings
### From Shell Scripts (Hooks)
Use the standard frontmatter extraction pattern from `.claude/rules/shell-scripting.md`:
```bash
#!/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
```bash
# 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:
```markdown
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`:
```bash
#!/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:
```markdown
---
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
```markdown
---
validation_level: strict
max_file_size: 1000000
allowed_extensions: [".js", ".ts", ".tsx"]
---
```
```bash
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:
1. Design settings schema (fields, types, defaults)
2. Create template in plugin README
3. Add `.claude/*.local.md` to `.gitignore`
4. Implement parsing using `extract_field` pattern
5. Use quick-exit pattern (`[[ -f "$STATE_FILE" ]] || exit 0`)
6. Provide sensible defaults when file is missing
7. 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 |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!