spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / plugins / plugin-dev / skills / plugin-settings / SKILL.md
544 lines · 11.8 KBPreviewCodeRaw
1---
2name: Plugin Settings
3description: 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.
4version: 0.1.0
5---
6
7# Plugin Settings Pattern for Claude Code Plugins
8
9## Overview
10
11Plugins 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.
12
13**Key characteristics:**
14- File location: `.claude/plugin-name.local.md` in project root
15- Structure: YAML frontmatter + markdown body
16- Purpose: Per-project plugin configuration and state
17- Usage: Read from hooks, commands, and agents
18- Lifecycle: User-managed (not in git, should be in `.gitignore`)
19
20## File Structure
21
22### Basic Template
23
24```markdown
25---
26enabled: true
27setting1: value1
28setting2: value2
29numeric_setting: 42
30list_setting: ["item1", "item2"]
31---
32
33# Additional Context
34
35This markdown body can contain:
36- Task descriptions
37- Additional instructions
38- Prompts to feed back to Claude
39- Documentation or notes
40```
41
42### Example: Plugin State File
43
44**.claude/my-plugin.local.md:**
45```markdown
46---
47enabled: true
48strict_mode: false
49max_retries: 3
50notification_level: info
51coordinator_session: team-leader
52---
53
54# Plugin Configuration
55
56This plugin is configured for standard validation mode.
57Contact @team-lead with questions.
58```
59
60## Reading Settings Files
61
62### From Hooks (Bash Scripts)
63
64**Pattern: Check existence and parse frontmatter**
65
66```bash
67#!/bin/bash
68set -euo pipefail
69
70# Define state file path
71STATE_FILE=".claude/my-plugin.local.md"
72
73# Quick exit if file doesn't exist
74if [[ ! -f "$STATE_FILE" ]]; then
75 exit 0 # Plugin not configured, skip
76fi
77
78# Parse YAML frontmatter (between --- markers)
79FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$STATE_FILE")
80
81# Extract individual fields
82ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//' | sed 's/^"\(.*\)"$/\1/')
83STRICT_MODE=$(echo "$FRONTMATTER" | grep '^strict_mode:' | sed 's/strict_mode: *//' | sed 's/^"\(.*\)"$/\1/')
84
85# Check if enabled
86if [[ "$ENABLED" != "true" ]]; then
87 exit 0 # Disabled
88fi
89
90# Use configuration in hook logic
91if [[ "$STRICT_MODE" == "true" ]]; then
92 # Apply strict validation
93 # ...
94fi
95```
96
97See `examples/read-settings-hook.sh` for complete working example.
98
99### From Commands
100
101Commands can read settings files to customize behavior:
102
103```markdown
104---
105description: Process data with plugin
106allowed-tools: ["Read", "Bash"]
107---
108
109# Process Command
110
111Steps:
1121. Check if settings exist at `.claude/my-plugin.local.md`
1132. Read configuration using Read tool
1143. Parse YAML frontmatter to extract settings
1154. Apply settings to processing logic
1165. Execute with configured behavior
117```
118
119### From Agents
120
121Agents can reference settings in their instructions:
122
123```markdown
124---
125name: configured-agent
126description: Agent that adapts to project settings
127---
128
129Check for plugin settings at `.claude/my-plugin.local.md`.
130If present, parse YAML frontmatter and adapt behavior according to:
131- enabled: Whether plugin is active
132- mode: Processing mode (strict, standard, lenient)
133- Additional configuration fields
134```
135
136## Parsing Techniques
137
138### Extract Frontmatter
139
140```bash
141# Extract everything between --- markers
142FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
143```
144
145### Read Individual Fields
146
147**String fields:**
148```bash
149VALUE=$(echo "$FRONTMATTER" | grep '^field_name:' | sed 's/field_name: *//' | sed 's/^"\(.*\)"$/\1/')
150```
151
152**Boolean fields:**
153```bash
154ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
155# Compare: if [[ "$ENABLED" == "true" ]]; then
156```
157
158**Numeric fields:**
159```bash
160MAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//')
161# Use: if [[ $MAX -gt 100 ]]; then
162```
163
164### Read Markdown Body
165
166Extract content after second `---`:
167
168```bash
169# Get everything after closing ---
170BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
171```
172
173## Common Patterns
174
175### Pattern 1: Temporarily Active Hooks
176
177Use settings file to control hook activation:
178
179```bash
180#!/bin/bash
181STATE_FILE=".claude/security-scan.local.md"
182
183# Quick exit if not configured
184if [[ ! -f "$STATE_FILE" ]]; then
185 exit 0
186fi
187
188# Read enabled flag
189FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$STATE_FILE")
190ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
191
192if [[ "$ENABLED" != "true" ]]; then
193 exit 0 # Disabled
194fi
195
196# Run hook logic
197# ...
198```
199
200**Use case:** Enable/disable hooks without editing hooks.json (requires restart).
201
202### Pattern 2: Agent State Management
203
204Store agent-specific state and configuration:
205
206**.claude/multi-agent-swarm.local.md:**
207```markdown
208---
209agent_name: auth-agent
210task_number: 3.5
211pr_number: 1234
212coordinator_session: team-leader
213enabled: true
214dependencies: ["Task 3.4"]
215---
216
217# Task Assignment
218
219Implement JWT authentication for the API.
220
221**Success Criteria:**
222- Authentication endpoints created
223- Tests passing
224- PR created and CI green
225```
226
227Read from hooks to coordinate agents:
228
229```bash
230AGENT_NAME=$(echo "$FRONTMATTER" | grep '^agent_name:' | sed 's/agent_name: *//')
231COORDINATOR=$(echo "$FRONTMATTER" | grep '^coordinator_session:' | sed 's/coordinator_session: *//')
232
233# Send notification to coordinator
234tmux send-keys -t "$COORDINATOR" "Agent $AGENT_NAME completed task" Enter
235```
236
237### Pattern 3: Configuration-Driven Behavior
238
239**.claude/my-plugin.local.md:**
240```markdown
241---
242validation_level: strict
243max_file_size: 1000000
244allowed_extensions: [".js", ".ts", ".tsx"]
245enable_logging: true
246---
247
248# Validation Configuration
249
250Strict mode enabled for this project.
251All writes validated against security policies.
252```
253
254Use in hooks or commands:
255
256```bash
257LEVEL=$(echo "$FRONTMATTER" | grep '^validation_level:' | sed 's/validation_level: *//')
258
259case "$LEVEL" in
260 strict)
261 # Apply strict validation
262 ;;
263 standard)
264 # Apply standard validation
265 ;;
266 lenient)
267 # Apply lenient validation
268 ;;
269esac
270```
271
272## Creating Settings Files
273
274### From Commands
275
276Commands can create settings files:
277
278```markdown
279# Setup Command
280
281Steps:
2821. Ask user for configuration preferences
2832. Create `.claude/my-plugin.local.md` with YAML frontmatter
2843. Set appropriate values based on user input
2854. Inform user that settings are saved
2865. Remind user to restart Claude Code for hooks to recognize changes
287```
288
289### Template Generation
290
291Provide template in plugin README:
292
293```markdown
294## Configuration
295
296Create `.claude/my-plugin.local.md` in your project:
297
298\`\`\`markdown
299---
300enabled: true
301mode: standard
302max_retries: 3
303---
304
305# Plugin Configuration
306
307Your settings are active.
308\`\`\`
309
310After creating or editing, restart Claude Code for changes to take effect.
311```
312
313## Best Practices
314
315### File Naming
316
317✅ **DO:**
318- Use `.claude/plugin-name.local.md` format
319- Match plugin name exactly
320- Use `.local.md` suffix for user-local files
321
322❌ **DON'T:**
323- Use different directory (not `.claude/`)
324- Use inconsistent naming
325- Use `.md` without `.local` (might be committed)
326
327### Gitignore
328
329Always add to `.gitignore`:
330
331```gitignore
332.claude/*.local.md
333.claude/*.local.json
334```
335
336Document this in plugin README.
337
338### Defaults
339
340Provide sensible defaults when settings file doesn't exist:
341
342```bash
343if [[ ! -f "$STATE_FILE" ]]; then
344 # Use defaults
345 ENABLED=true
346 MODE=standard
347else
348 # Read from file
349 # ...
350fi
351```
352
353### Validation
354
355Validate settings values:
356
357```bash
358MAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//')
359
360# Validate numeric range
361if ! [[ "$MAX" =~ ^[0-9]+$ ]] || [[ $MAX -lt 1 ]] || [[ $MAX -gt 100 ]]; then
362 echo "⚠️ Invalid max_value in settings (must be 1-100)" >&2
363 MAX=10 # Use default
364fi
365```
366
367### Restart Requirement
368
369**Important:** Settings changes require Claude Code restart.
370
371Document in your README:
372
373```markdown
374## Changing Settings
375
376After editing `.claude/my-plugin.local.md`:
3771. Save the file
3782. Exit Claude Code
3793. Restart: `claude` or `cc`
3804. New settings will be loaded
381```
382
383Hooks cannot be hot-swapped within a session.
384
385## Security Considerations
386
387### Sanitize User Input
388
389When writing settings files from user input:
390
391```bash
392# Escape quotes in user input
393SAFE_VALUE=$(echo "$USER_INPUT" | sed 's/"/\\"/g')
394
395# Write to file
396cat > "$STATE_FILE" <<EOF
397---
398user_setting: "$SAFE_VALUE"
399---
400EOF
401```
402
403### Validate File Paths
404
405If settings contain file paths:
406
407```bash
408FILE_PATH=$(echo "$FRONTMATTER" | grep '^data_file:' | sed 's/data_file: *//')
409
410# Check for path traversal
411if [[ "$FILE_PATH" == *".."* ]]; then
412 echo "⚠️ Invalid path in settings (path traversal)" >&2
413 exit 2
414fi
415```
416
417### Permissions
418
419Settings files should be:
420- Readable by user only (`chmod 600`)
421- Not committed to git
422- Not shared between users
423
424## Real-World Examples
425
426### multi-agent-swarm Plugin
427
428**.claude/multi-agent-swarm.local.md:**
429```markdown
430---
431agent_name: auth-implementation
432task_number: 3.5
433pr_number: 1234
434coordinator_session: team-leader
435enabled: true
436dependencies: ["Task 3.4"]
437additional_instructions: Use JWT tokens, not sessions
438---
439
440# Task: Implement Authentication
441
442Build JWT-based authentication for the REST API.
443Coordinate with auth-agent on shared types.
444```
445
446**Hook usage (agent-stop-notification.sh):**
447- Checks if file exists (line 15-18: quick exit if not)
448- Parses frontmatter to get coordinator_session, agent_name, enabled
449- Sends notifications to coordinator if enabled
450- Allows quick activation/deactivation via `enabled: true/false`
451
452### ralph-wiggum Plugin
453
454**.claude/ralph-loop.local.md:**
455```markdown
456---
457iteration: 1
458max_iterations: 10
459completion_promise: "All tests passing and build successful"
460---
461
462Fix all the linting errors in the project.
463Make sure tests pass after each fix.
464```
465
466**Hook usage (stop-hook.sh):**
467- Checks if file exists (line 15-18: quick exit if not active)
468- Reads iteration count and max_iterations
469- Extracts completion_promise for loop termination
470- Reads body as the prompt to feed back
471- Updates iteration count on each loop
472
473## Quick Reference
474
475### File Location
476
477```
478project-root/
479└── .claude/
480 └── plugin-name.local.md
481```
482
483### Frontmatter Parsing
484
485```bash
486# Extract frontmatter
487FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE")
488
489# Read field
490VALUE=$(echo "$FRONTMATTER" | grep '^field:' | sed 's/field: *//' | sed 's/^"\(.*\)"$/\1/')
491```
492
493### Body Parsing
494
495```bash
496# Extract body (after second ---)
497BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE")
498```
499
500### Quick Exit Pattern
501
502```bash
503if [[ ! -f ".claude/my-plugin.local.md" ]]; then
504 exit 0 # Not configured
505fi
506```
507
508## Additional Resources
509
510### Reference Files
511
512For detailed implementation patterns:
513
514- **`references/parsing-techniques.md`** - Complete guide to parsing YAML frontmatter and markdown bodies
515- **`references/real-world-examples.md`** - Deep dive into multi-agent-swarm and ralph-wiggum implementations
516
517### Example Files
518
519Working examples in `examples/`:
520
521- **`read-settings-hook.sh`** - Hook that reads and uses settings
522- **`create-settings-command.md`** - Command that creates settings file
523- **`example-settings.md`** - Template settings file
524
525### Utility Scripts
526
527Development tools in `scripts/`:
528
529- **`validate-settings.sh`** - Validate settings file structure
530- **`parse-frontmatter.sh`** - Extract frontmatter fields
531
532## Implementation Workflow
533
534To add settings to a plugin:
535
5361. Design settings schema (which fields, types, defaults)
5372. Create template file in plugin documentation
5383. Add gitignore entry for `.claude/*.local.md`
5394. Implement settings parsing in hooks/commands
5405. Use quick-exit pattern (check file exists, check enabled field)
5416. Document settings in plugin README with template
5427. Remind users that changes require Claude Code restart
543
544Focus on keeping settings simple and providing good defaults when settings file doesn't exist.