|
Download plugins/plugin-dev/skills/plugin-settings/SKILL.md from SaylorTwift/claude-code: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/SaylorTwift/claude-code/resolve/main/plugins/plugin-dev/skills/plugin-settings/SKILL.md
- Command line
-
hf download hf://SaylorTwift/claude-code/plugins/plugin-dev/skills/plugin-settings/SKILL.md
-
curl -L -o SKILL.md https://huggingface.co/SaylorTwift/claude-code/resolve/main/plugins/plugin-dev/skills/plugin-settings/SKILL.md
12.1 kB
| name: Plugin Settings | |
| description: 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. | |
| version: 0.1.0 | |
| # Plugin Settings Pattern for Claude Code Plugins | |
| ## Overview | |
| 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:** | |
| - File location: `.claude/plugin-name.local.md` in project root | |
| - Structure: YAML frontmatter + markdown body | |
| - Purpose: Per-project plugin configuration and state | |
| - Usage: Read from hooks, commands, and agents | |
| - Lifecycle: User-managed (not in git, should be in `.gitignore`) | |
| ## File Structure | |
| ### Basic Template | |
| ```markdown | |
| --- | |
| enabled: true | |
| setting1: value1 | |
| setting2: value2 | |
| numeric_setting: 42 | |
| list_setting: ["item1", "item2"] | |
| --- | |
| # Additional Context | |
| This markdown body can contain: | |
| - Task descriptions | |
| - Additional instructions | |
| - Prompts to feed back to Claude | |
| - Documentation or notes | |
| ``` | |
| ### Example: Plugin State File | |
| **.claude/my-plugin.local.md:** | |
| ```markdown | |
| --- | |
| 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. | |
| ``` | |
| ## Reading Settings Files | |
| ### From Hooks (Bash Scripts) | |
| **Pattern: Check existence and parse frontmatter** | |
| ```bash | |
| #!/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 | |
| ``` | |
| See `examples/read-settings-hook.sh` for complete working example. | |
| ### From Commands | |
| Commands can read settings files to customize behavior: | |
| ```markdown | |
| --- | |
| 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 | |
| ``` | |
| ### From Agents | |
| Agents can reference settings in their instructions: | |
| ```markdown | |
| --- | |
| 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 | |
| ``` | |
| ## Parsing Techniques | |
| ### Extract Frontmatter | |
| ```bash | |
| # Extract everything between --- markers | |
| FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE") | |
| ``` | |
| ### Read Individual Fields | |
| **String fields:** | |
| ```bash | |
| VALUE=$(echo "$FRONTMATTER" | grep '^field_name:' | sed 's/field_name: *//' | sed 's/^"\(.*\)"$/\1/') | |
| ``` | |
| **Boolean fields:** | |
| ```bash | |
| ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//') | |
| # Compare: if [[ "$ENABLED" == "true" ]]; then | |
| ``` | |
| **Numeric fields:** | |
| ```bash | |
| MAX=$(echo "$FRONTMATTER" | grep '^max_value:' | sed 's/max_value: *//') | |
| # Use: if [[ $MAX -gt 100 ]]; then | |
| ``` | |
| ### Read Markdown Body | |
| Extract content after second `---`: | |
| ```bash | |
| # Get everything after closing --- | |
| BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE") | |
| ``` | |
| ## Common Patterns | |
| ### Pattern 1: Temporarily Active Hooks | |
| Use settings file to control hook activation: | |
| ```bash | |
| #!/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:** | |
| ```markdown | |
| --- | |
| 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: | |
| ```bash | |
| 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:** | |
| ```markdown | |
| --- | |
| 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: | |
| ```bash | |
| 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: | |
| ```markdown | |
| # 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 | |
| ``` | |
| ### Template Generation | |
| Provide template in plugin README: | |
| ```markdown | |
| ## 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`: | |
| ```gitignore | |
| .claude/*.local.md | |
| .claude/*.local.json | |
| ``` | |
| Document this in plugin README. | |
| ### Defaults | |
| Provide sensible defaults when settings file doesn't exist: | |
| ```bash | |
| if [[ ! -f "$STATE_FILE" ]]; then | |
| # Use defaults | |
| ENABLED=true | |
| MODE=standard | |
| else | |
| # Read from file | |
| # ... | |
| fi | |
| ``` | |
| ### Validation | |
| Validate settings values: | |
| ```bash | |
| 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: | |
| ```markdown | |
| ## 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 | |
| ``` | |
| Hooks cannot be hot-swapped within a session. | |
| ## Security Considerations | |
| ### Sanitize User Input | |
| When writing settings files from user input: | |
| ```bash | |
| # 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: | |
| ```bash | |
| 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:** | |
| ```markdown | |
| --- | |
| 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:** | |
| ```markdown | |
| --- | |
| 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 | |
| ```bash | |
| # Extract frontmatter | |
| FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$FILE") | |
| # Read field | |
| VALUE=$(echo "$FRONTMATTER" | grep '^field:' | sed 's/field: *//' | sed 's/^"\(.*\)"$/\1/') | |
| ``` | |
| ### Body Parsing | |
| ```bash | |
| # Extract body (after second ---) | |
| BODY=$(awk '/^---$/{i++; next} i>=2' "$FILE") | |
| ``` | |
| ### Quick Exit Pattern | |
| ```bash | |
| 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. | |