# How Claude Plugins Handle User Preferences: File-Based Configuration Guide

> Discover how Claude plugins manage user preferences using file-based configuration in YAML front-matter. Learn to store and access settings for your projects efficiently.

- Repository: [Anthropic/claude-plugins-official](https://github.com/anthropics/claude-plugins-official)
- Tags: how-to-guide
- Published: 2026-03-13

---

**Claude plugins store user preferences in per-project markdown files located at `.claude/<plugin-name>.local.md`, using YAML front-matter for structured data that is parsed by [`config_loader.py`](https://github.com/anthropics/claude-plugins-official/blob/main/config_loader.py) and consumed by hooks and commands at runtime.**

Claude plugins manage user preferences through a declarative, file-based configuration system designed for per-project customization. In the `anthropics/claude-plugins-official` repository, preferences are persisted as markdown files with YAML front-matter, allowing developers to store settings alongside source code without committing them to version control. This approach enables plugins to read user-specific configurations at runtime to adjust behavior, thresholds, and toolchains dynamically.

## The `.claude/` Directory and Local Configuration Files

Claude plugins treat user preferences as **per-project configuration files** that live in a hidden `.claude/` directory at the repository root. The preferred pattern follows the naming convention:

```

.claude/<plugin-name>.local.md

```

These files are **ignored by Git**—developers are encouraged to add `.claude/*.local.md` to `.gitignore`—so each user can maintain personal settings without polluting the shared repository. The format consists of YAML front-matter for structured key-value pairs, followed by an optional markdown body that can hold extra context or prompts.

### File Structure and Format

A typical preferences file contains:

```markdown
---
enabled: true
max_retries: 5
notification_level: "info"
---

# Optional explanatory notes or context

```

The front-matter section between the triple dashes stores the actual configuration values, while the markdown body below provides human-readable documentation or additional prompts for the user.

## Loading and Parsing Preferences with [`config_loader.py`](https://github.com/anthropics/claude-plugins-official/blob/main/config_loader.py)

When a plugin or hook needs to honor a preference, the system loads and parses these markdown files through a centralized configuration loader. In [`plugins/hookify/core/config_loader.py`](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/hookify/core/config_loader.py), the `load_rules()` function scans the `.claude/` directory to discover relevant configuration files.

The parsing workflow follows three steps:

1. **File Discovery** – The loader identifies files matching `hookify.*.local.md` for rule-based hooks or `<plugin>.local.md` for the plugin-settings skill.
2. **Front-Matter Extraction** – The `extract_frontmatter()` function parses the YAML block into a Python dictionary, returning a tuple of `(frontmatter_dict, body)`.
3. **Value Application** – The resulting dictionary is consulted by hook logic, agents, or commands to enable or disable functionality, adjust thresholds, or select toolchains.

## The Plugin-Settings Skill for Interactive Configuration

The **plugin-settings skill** (defined in [`plugins/plugin-dev/skills/plugin-settings/SKILL.md`](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/plugin-dev/skills/plugin-settings/SKILL.md)) provides a guided workflow for creating and managing these configuration files. This skill automates the process of preference management by:

- Prompting the user for configuration values they want to persist
- Generating a starter `.claude/<plugin>.local.md` file with the supplied values
- Documenting the schema so future hooks can read the same keys reliably

Users invoke this skill through Claude Code to interactively generate properly formatted configuration files without manually editing YAML.

## Implementing Preference Checks in Hooks and Commands

Plugins consume user preferences uniformly across the ecosystem, whether in Python-based hooks or shell commands.

### Reading Preferences in Python Hooks

Hooks can load and evaluate preferences using the configuration loader and rule engine:

```python
#!/usr/bin/env python3
import json
import sys
from core.config_loader import load_rules
from core.rule_engine import RuleEngine

def main():
    input_data = json.load(sys.stdin)          # data about the tool use

    rules = load_rules(event='bash')           # loads .claude/*.local.md

    engine = RuleEngine()
    result = engine.evaluate_rules(rules, input_data)

    # The result may contain a decision based on preferences like `enabled`

    print(json.dumps(result), file=sys.stdout)

if __name__ == "__main__":
    main()

```

In this example, `load_rules(event='bash')` pulls the front-matter from [`.claude/hookify.my-plugin.local.md`](https://github.com/anthropics/claude-plugins-official/blob/main/.claude/hookify.my-plugin.local.md) (if present) and constructs `Rule` objects that the `RuleEngine` evaluates against the incoming tool-use payload.

### Reading Preferences in Bash Commands

For shell-based plugins, you can extract preferences using standard Unix tools:

```bash
#!/usr/bin/env bash
SETTINGS=".claude/my-plugin.local.md"

# Exit if no settings file

[[ -f "$SETTINGS" ]] || exit 0

# Extract front-matter

FRONT=$(sed -n '/^---$/,/^---$/{/^---$/d;p;}' "$SETTINGS")

# Get individual preferences

ENABLED=$(echo "$FRONT" | grep '^enabled:' | cut -d' ' -f2)
MAX_RETRIES=$(echo "$FRONT" | grep '^max_retries:' | cut -d' ' -f2)

if [[ "$ENABLED" != "true" ]]; then
    echo "Plugin disabled – skipping"
    exit 0
fi

echo "Running with max retries = $MAX_RETRIES"

# …rest of command logic…

```

This script extracts the YAML front-matter by parsing content between the first two `---` delimiters, then reads specific preference values to control execution flow.

## Summary

- **Storage Location**: User preferences reside in `.claude/<plugin-name>.local.md` files at the project root, ignored by Git to prevent repository pollution.
- **Format**: YAML front-matter provides structured key-value storage, with an optional markdown body for documentation.
- **Parsing Mechanism**: The `extract_frontmatter()` function in [`plugins/hookify/core/config_loader.py`](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/hookify/core/config_loader.py) converts YAML blocks into Python dictionaries for runtime consumption.
- **Discovery**: The `load_rules()` function scans the `.claude/` directory to locate and load relevant configuration files based on event type or plugin name.
- **Workflow**: The plugin-settings skill offers an interactive interface for generating and updating preference files without manual YAML editing.

## Frequently Asked Questions

### What file format do Claude plugins use for user preferences?

Claude plugins use markdown files with YAML front-matter. The front-matter section (delimited by triple dashes) contains structured key-value pairs, while the remainder of the file can contain markdown documentation. This format is human-readable, editable in any text editor, and easily parsed by both Python and shell scripts.

### Are user preferences shared across different projects?

No, preferences are **per-project** by design. The `.claude/<plugin-name>.local.md` file lives within the specific repository's root directory, allowing users to maintain different configurations for different codebases. Since these files are gitignored, each clone of the repository can have its own independent settings.

### How do hooks programmatically access user preferences?

Hooks access preferences through the `load_rules()` function in [`plugins/hookify/core/config_loader.py`](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/hookify/core/config_loader.py), which returns parsed rule objects containing the front-matter data. Alternatively, hooks can import and use `extract_frontmatter()` directly to parse specific `.claude/` files, receiving a tuple of `(frontmatter_dict, body)` for custom processing logic.

### Why are preference files stored as markdown rather than JSON or YAML files?

The markdown format with YAML front-matter provides a balance between machine-parseable structure and human readability. The [`.local.md`](https://github.com/anthropics/claude-plugins-official/blob/main/.local.md) extension clearly indicates these are local configuration files, while the markdown body allows developers to include explanatory notes, context, or prompts alongside the structured data. This approach keeps documentation and configuration co-located for easier maintenance.