# Skill Config Pattern (schema 3.6.0)

> **Status:** AUTHORITATIVE — defines the self-declared config surface introduced in schema 3.6.0.
> **Schema log:** `000-docs/SCHEMA_CHANGELOG.md` § [3.6.0]
> **Master spec:** `000-docs/6767-b-SPEC-DR-STND-claude-skills-standard.md`

A skill in this marketplace can self-declare two kinds of configuration so that the installer / runtime helper can prompt the user on first run instead of letting them hit a runtime error:

1. **Required environment variables** — secrets and credentials the skill consumes from the process environment.
2. **Per-skill config keys** — non-secret behavior knobs that the user can override on a per-skill basis.

Both are optional. A skill that hardcodes its env-var reads or has no user-tunable config does not need either block.

---

## 1. `required_environment_variables`

Top-level frontmatter field. List of objects. Each entry describes one env var.

### Schema

| Key | Required | Type | Purpose |
|---|---|---|---|
| `name` | yes | string (UPPER_SNAKE_CASE) | Env var name as read at runtime |
| `prompt` | yes | string | First-run installer prompt shown to user |
| `help` | no | string | Extra context (URLs, scopes, format examples) |
| `required_for` | no | string | What the var unlocks (used by partial-mode skills) |

### Example

```yaml
---
name: pr-review
description: Run a multi-AI PR review against a GitHub repo
allowed-tools: Bash(gh:*), Read
required_environment_variables:
  - name: GITHUB_TOKEN
    prompt: "Personal access token (repo + write:packages scopes)"
    help: "Create at https://github.com/settings/tokens"
    required_for: "PR comment + release operations"
  - name: ANTHROPIC_API_KEY
    prompt: "Anthropic API key"
    help: "From console.anthropic.com → API keys"
---
```

### Validation rules

- The field itself must be a YAML list. Other shapes (string, mapping, scalar) are ERRORs.
- Every entry must be a mapping with at least `name` + `prompt`. Missing either is an ERROR.
- The validator does NOT grep the skill body to check whether declared vars are actually read — declaration is the contract, body usage is the implementation.

### Cross-field consistency with `requires_env` (schema 3.5.0)

If a skill declares `requires_env: [GITHUB_TOKEN]` for visibility gating (schema 3.5.0) but does NOT have a matching `required_environment_variables` entry with `name: GITHUB_TOKEN`, the validator emits a WARNING. Reason: a user installing the skill needs to know *what* `GITHUB_TOKEN` should contain, not just that it must be set. Adding the prompt/help description closes that gap.

The warning is non-blocking — `requires_env` alone is still useful for gating, and not every skill author needs to ship installer copy.

---

## 2. `metadata.intent-solutions.config`

Nested under the existing `metadata` top-level. List of objects. Each entry describes one non-secret config key.

### Schema

| Key | Required | Type | Purpose |
|---|---|---|---|
| `key` | yes | string | Config key the skill reads at runtime |
| `description` | yes | string | What the key controls |
| `default` | yes | any | Default value if user accepts the prompt as-is |
| `prompt` | no | string | First-run installer prompt (defaults to "Set `<key>`?") |

### Example

```yaml
---
name: branch-prs
description: Open PRs against a configured target branch
allowed-tools: Bash(gh:*)
metadata:
  intent-solutions:
    config:
      - key: default_branch
        description: "Branch to target for new PRs"
        default: main
        prompt: "What branch should PRs target?"
      - key: auto_label
        description: "Add 'ai-authored' label to every PR"
        default: true
---
```

### Where the user's resolved values live

Resolved values from the installer are written to `~/.claude/skill-config/<skill-name>.yaml` (mode 600). Format:

```yaml
# Generated by skill-creator / install helper. Single source of truth for
# this skill's per-user config. Do not hand-edit.
default_branch: main
auto_label: true
```

Skills read this file at runtime through whatever loader they're built with. The marketplace does NOT enforce a specific loader — a Python skill might use `yaml.safe_load`; a bash skill might `yq` it; a Node skill might `js-yaml` it. The contract is the file path and the YAML shape, not the language.

### Validation rules

- The `config` list itself must be a YAML list. Other shapes are ERRORs.
- Every entry must be a mapping with at least `key` + `description` + `default`. Missing any is an ERROR.
- The validator does NOT type-check `default` against the value's runtime type — defaults can be string, number, bool, list, or mapping per skill author choice.

---

## Why this pattern (vs. hardcoded env reads)

| Without self-declaration | With self-declaration |
|---|---|
| Skill reads `os.environ['GITHUB_TOKEN']`. If unset, the user hits a `KeyError` mid-task. | Installer reads the frontmatter, prompts the user, and writes the env to `~/.claude/skill-config/<name>.yaml`. The skill never sees an unset state. |
| New users don't know which secrets the skill needs until they fail. | First-run prompts list every required var with a link to where to generate it. |
| Audit tooling can't tell which skills consume secrets vs. which are pure local. | The marketplace UI can group skills by env-var dependency; security review can scan declarations directly. |

The pattern is the open-standard convention (agentskills.io) for skill installers. Adopting it lets the IS marketplace prompt cleanly without each skill author writing a custom first-run UX.

---

## Migration

None required. Existing skills that hardcode env reads continue to work unchanged. To opt in, add one or both blocks to the skill's frontmatter.

For a skill that already uses `requires_env` (schema 3.5.0), adding the matching `required_environment_variables` entries silences the cross-field warning and unlocks installer prompts.

---

## What this does NOT cover (intentionally)

- **Validator does not grep skill bodies for undeclared env-var reads.** Initial design considered this; ruled out because (a) noise at 2783 skills, (b) false-positive prone (string concatenation, indirect lookups, optional fallbacks), (c) declaration is the contract — body usage is implementation. May revisit when JRig Tier 3 behavioral eval lands.
- **No automatic secret-value validation.** The installer trusts whatever the user pastes. Format / regex checks would be skill-specific and live in the skill body, not the marketplace.
- **No runtime config-file watcher.** Resolved values are read at skill invocation; restart the skill to pick up changes.

---

## Cross-refs

- Bead `claude-la6s`
- GH issue `claude-code-plugins-plus-skills#713`
- Plane CCP-23
- Pairs with schema 3.5.0 (`requires_env` / `requires_tools` visibility gating in #712 / claude-22cg)
- Part of the self-improving-skills series (`claude-nwdy` progressive disclosure + `claude-22cg` conditional visibility + this one)
