BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
## Common Patterns
### Pattern 1: Temporarily Active Hooks
Use settings file to control hook activation:
#!/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:**
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:
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:**
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:
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:
Setup Command
Steps:
- Ask user for configuration preferences
- Create
.claude/my-plugin.local.mdwith YAML frontmatter - Set appropriate values based on user input
- Inform user that settings are saved
- Remind user to restart Claude Code for hooks to recognize changes
### Template Generation
Provide template in plugin README:
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`:
.claude/*.local.md .claude/*.local.json
Document this in plugin README.
### Defaults
Provide sensible defaults when settings file doesn't exist:
if [[ ! -f "$STATE_FILE" ]]; then # Use defaults ENABLED=true MODE=standard else # Read from file # ... fi
### Validation
Validate settings values:
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:
Changing Settings
After editing .claude/my-plugin.local.md:
- Save the file
- Exit Claude Code
- Restart:
claudeorcc - 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:
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:
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:**
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:**
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
Extract frontmatter
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
Read field
VALUE=$(echo "$FRONTMATTER" | grep '^field:' | sed 's/field: *//' | sed 's/^"\(.*\)"$/\1/')
### Body Parsing
Extract body (after second ---)
BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
### Quick Exit Pattern
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.