Section 7: Configurable Skills¶
EXPERIMENTAL
This section describes an advanced pattern for creating skills that adapt to different projects. The pattern is conceptually sound but the concrete implementations (example skills) will be delivered in Epic 3.
Current Status: Pattern documented, examples pending.
The Problem: Hardcoded Conventions Kill Reusability¶
Skills are meant to be portable—write once, use everywhere. But in practice, many skills become project-specific because they hardcode local conventions.
Example: A Non-Portable Skill¶
# Hexagonal Architecture Skill
When implementing Hexagonal Architecture:
1. Put domain logic in `src/domain/`
2. Put ports (interfaces) in `src/domain/ports/`
3. Put adapters in `src/infrastructure/adapters/`
4. Put use cases in `src/application/`
The Problem: These paths work for this project, but the next project might use:
core/instead ofsrc/domain/interfaces/instead ofports/- A completely different directory structure
If you share this skill, it won't work. You've mixed Category 4 (Universal Pattern) with Category 5 (Project-Specific Conventions).
The Solution: Separate "Universal How" from "Local Where"¶
Configurable skills solve this by separating the pattern from the configuration.
The Pattern (Universal)¶
# Hexagonal Architecture Skill
When implementing Hexagonal Architecture:
1. Domain logic goes in the **domain directory**
2. Port interfaces go in the **ports directory**
3. Adapter implementations go in the **adapters directory**
4. Use case orchestration goes in the **application directory**
The Configuration (Project-Specific)¶
# Configuration
domain_dir: src/domain
ports_dir: src/domain/ports
adapters_dir: src/infrastructure/adapters
application_dir: src/application
The Result¶
The skill reads its configuration and applies the pattern using this project's conventions. The same skill works in any project—just change the configuration.
Why Configure? The Precision-Reusability Breakthrough¶
Configuration solves a fundamental dilemma in AI memory:
| Without Configuration | With Configuration |
|---|---|
| Reusable skills are vague | Pattern is reusable AND precise |
| Precise skills are project-bound | Configuration is project-specific |
| You must choose one | You get both |
The Same Skill, Two Projects¶
Project A (E-commerce):
paths:
domain_dir: src/core/domain
application_dir: src/core/use-cases
Project B (Healthcare API):
paths:
domain_dir: lib/domain
application_dir: lib/services
Same Hexagonal Architecture skill, different structures. The skill teaches how to implement the pattern; the configuration says where in this project.
Benefits of Configurable Skills¶
1. True Portability¶
Write the skill once, configure per project. No more copying and editing. Portability is stack-scoped: a well-crafted skill becomes a reusable asset across all projects in the same technology stack (e.g., all React projects, all Python projects).
2. Separation of Concerns¶
- The skill author focuses on the pattern (the "how")
- The skill user provides the configuration (the "where")
3. Team Consistency¶
Everyone uses the same skill with the same configuration. No drift between team members.
4. Easier Maintenance¶
Update the skill in one place, all projects benefit. Configuration stays local.
5. Self-Documenting¶
The configuration block explicitly declares what the skill needs from the project.
Configuration Schema Format¶
Basic Structure¶
A configurable skill has a # Configuration section with a YAML block:
# Skill Name
## Purpose
What this skill does.
## Configuration
```yaml
# Required
domain_dir: src/domain # Where domain logic lives
ports_dir: src/domain/ports # Where port interfaces live
# Optional (with defaults)
adapters_dir: src/infrastructure # Where adapters live (default: src/adapters)
use_barrel_files: true # Whether to use index.ts exports (default: true)
```
Instructions¶
[Instructions that reference config values like "the domain directory"]
### Schema Elements
| Element | Description | Example |
|---------|-------------|---------|
| **Key** | Configuration variable name | `domain_dir` |
| **Value** | Project-specific value | `src/domain` |
| **Comment** | Description/purpose | `# Where domain logic lives` |
| **Default** | Fallback if not specified | `(default: src/adapters)` |
### Required vs. Optional
```yaml
# Required - skill cannot function without these
domain_dir: ??? # REQUIRED: Where domain logic lives
ports_dir: ??? # REQUIRED: Where port interfaces live
# Optional - skill has sensible defaults
file_extension: .ts # Optional (default: .ts)
use_barrel_files: true # Optional (default: true)
```
Skills should:
- Fail clearly if required config is missing
- Use sensible defaults for optional config
- Document what each config key controls
Type Hints¶
While not enforced, document expected types in comments:
# Paths
domain_dir: src/domain # string: directory path
ports_dir: src/domain/ports # string: directory path
# Booleans
use_barrel_files: true # boolean: true/false
strict_mode: false # boolean: true/false
# Lists
allowed_extensions: # list: file extensions
- .ts
- .tsx
# Numbers
max_file_lines: 500 # number: maximum lines per file
Self-Initialization Patterns¶
Configurable skills can get their configuration in three ways:
Pattern 1: Scan Mode¶
The skill examines the codebase to infer configuration values.
How it works:
- Skill is invoked without configuration
- Skill scans project structure (package.json, directory layout, etc.)
- Skill infers configuration values
- Skill proceeds with inferred values
Best for:
- Projects with standard structures (Next.js, Rails, etc.)
- Configuration that can be reliably detected
- Reducing friction for first-time use
Example Scan Logic:
## Self-Initialization
If configuration is not provided, this skill will attempt to detect values:
1. Check for `src/domain/` → set `domain_dir: src/domain`
2. Check for `core/` → set `domain_dir: core`
3. Check for `app/domain/` → set `domain_dir: app/domain`
4. If none found → prompt user
Pattern 2: Prompt Mode¶
The skill asks the user for configuration on first use.
How it works:
- Skill is invoked without configuration
- Skill prompts user for each required value
- Skill can write configuration to the skill file for future use
- Skill proceeds with provided values
Best for:
- Non-standard project structures
- Configuration that can't be reliably detected
- Ensuring explicit user intent
Example Prompt:
## Self-Initialization
This skill requires configuration. Please provide:
1. **Domain directory**: Where should domain logic go?
Example: `src/domain`, `core`, `lib/domain`
2. **Ports directory**: Where should port interfaces go?
Example: `src/domain/ports`, `core/interfaces`
3. **Adapters directory**: Where should adapters go?
Example: `src/infrastructure`, `lib/adapters`
Pattern 3: Hybrid (Scan + Confirm)¶
The skill scans, then confirms with the user.
How it works:
- Skill scans project structure
- Skill presents inferred values to user
- User confirms or corrects
- Skill proceeds with confirmed values
Best for:
- Balancing automation with user control
- Catching misdetections
- Building user confidence
Example Hybrid:
## Self-Initialization
I detected the following structure:
- Domain directory: `src/domain` ✓
- Ports directory: `src/domain/ports` ✓
- Adapters directory: `src/infrastructure` ✓
Does this look correct? If not, please provide corrections.
When to Use Each Pattern¶
| Pattern | Use When |
|---|---|
| Scan | Standard frameworks, high confidence detection |
| Prompt | Unusual structures, critical configuration |
| Hybrid | Balance of convenience and control |
Structure Template¶
SKILL.md Template¶
---
name: {skill-name}
description: |
{What this skill does}.
Use when {triggers/scenarios}.
Configurable: requires project-specific paths.
allowed-tools: Read, Grep, Glob
---
# {Skill Name}
> **Configurable Skill**: This skill requires project-specific configuration.
> See Configuration section below.
## Purpose
{Brief description of what this skill accomplishes.}
## Configuration
```yaml
# Required
{key1}: {example_value} # {description}
{key2}: {example_value} # {description}
# Optional
{key3}: {default_value} # {description} (default: {default})
```
## Self-Initialization
{Describe how the skill gets its configuration if not provided.}
Option 1: Scan
- Look for {pattern} → set {key1}
- Look for {pattern} → set {key2}
Option 2: Prompt
- Ask user for {key1}: "{question}"
- Ask user for {key2}: "{question}"
## Instructions
### Step 1: {First Step}
{Instructions referencing config like "the domain directory" or "configured ports path"}
### Step 2: {Second Step}
{More instructions...}
## Examples
### Example 1: {Scenario}
{Show the skill applied with sample configuration}
## Validation
{How to verify the skill was applied correctly}
README.md Companion Template¶
For skills distributed as packages or shared across teams:
# {Skill Name}
{Brief description}
## Installation
Copy the `{skill-name}/` folder to your project's `.claude/skills/` directory.
## Configuration
Before first use, configure the skill by editing `SKILL.md`:
```yaml
# Configuration
{ key1 }: { your_value } # {what this controls}
{ key2 }: { your_value } # {what this controls}
```
## Usage
{How to invoke the skill}
## Configuration Reference
| Key | Required | Default | Description |
| -------- | -------- | ----------- | ------------- |
| `{key1}` | Yes | - | {description} |
| `{key2}` | Yes | - | {description} |
| `{key3}` | No | `{default}` | {description} |
## Examples
{Show the skill in action with different configurations}
Example: Hexagonal Architecture Skill¶
Here's what a complete configurable skill looks like:
---
name: hexagonal-architecture
description: |
Implements Hexagonal Architecture (Ports and Adapters) pattern.
Use when creating domain logic, defining ports, or implementing adapters.
Configurable: requires project-specific directory paths.
allowed-tools: Read, Write, Grep, Glob
---
# Hexagonal Architecture
> **Configurable Skill**: Edit the Configuration section for your project structure.
## Purpose
Guides implementation of Hexagonal Architecture, ensuring proper separation between
domain logic (inside) and infrastructure (outside).
## Configuration
```yaml
# Required - specify your project's directory structure
paths:
domain_dir: src/domain # Where domain entities and logic live
ports_dir: src/domain/ports # Where port interfaces are defined
adapters_dir: src/infrastructure # Where adapter implementations live
application_dir: src/application # Where use cases/services live
# Optional
naming:
file_case: kebab-case # kebab-case, PascalCase, or camelCase
use_barrel_files: true # Create index.ts exports (default: true)
# Architectural decisions (embedded markdown for complex guidance)
decisions:
repository_placement: |
## Where to Place Repositories
**Decision:** Repositories can be use-case-specific or shared.
| Condition | Location | Rationale |
|-----------|----------|-----------|
| Used by 1 use case | `{application_dir}/{use-case}/repositories/` | Keep cohesion |
| Used by 2+ use cases | `{domain_dir}/repositories/` | Avoid duplication |
**Example:** `OrderRepository` used by CreateOrder and CancelOrder → shared.
```
> **Note on `decisions:`** The `decisions:` key holds embedded markdown using YAML multiline
> strings (`|`). This keeps all configuration in one block while allowing rich decision
> documentation that Claude can render and apply.
## Self-Initialization
If configuration is empty, I will:
1. **Scan** for common patterns:
- `src/domain/` → domain_dir
- `core/domain/` → domain_dir
- `lib/domain/` → domain_dir
2. **Prompt** if not found:
- "Where should domain logic live? (e.g., src/domain)"
## Instructions
### Creating Domain Entities
1. Create entity in the **domain directory** (`domain_dir`)
2. Entity should have no external dependencies
3. Export from barrel file if `use_barrel_files` is enabled
### Defining Ports
1. Create interface in the **ports directory** (`ports_dir`)
2. Ports define what the domain needs from the outside world
3. Name convention: `I{Noun}Repository`, `I{Noun}Service`
### Implementing Adapters
1. Create implementation in the **adapters directory** (`adapters_dir`)
2. Adapter implements a port interface
3. Contains all infrastructure-specific code (database, HTTP, etc.)
### Creating Use Cases
1. Create use case in the **application directory** (`application_dir`)
2. Use case orchestrates domain entities via ports
3. Inject adapters through constructor
Use Cases for Configurable Skills¶
Architecture Patterns¶
- Hexagonal Architecture (ports, adapters, domain)
- Clean Architecture (entities, use cases, interfaces)
- MVC variants (models, views, controllers)
Testing Conventions¶
- Test file locations and naming
- Fixture patterns
- Mock/stub conventions
Coding Standards¶
- File naming patterns
- Export conventions
- Error handling patterns
Workflow Automation¶
- PR templates with project-specific sections
- Deployment scripts with environment paths
- Build configurations
Invocation Reliability¶
The Problem: Silent Invocation Failure¶
When a skill's invocation is set to automatic (the default), Claude decides whether to invoke
it based on the description frontmatter and conversation context. This decision is
probabilistic—a skill that fires reliably in one session may not fire in another. Worse,
failures are silent: Claude simply proceeds without the skill, and you may not notice
the difference until you see lower-quality output.
Techniques to Improve Reliability¶
1. Add Explicit Directives in CLAUDE.md¶
Tell Claude when to use specific skills:
# In CLAUDE.md
## Skill Directives
- Always use `/code-review` when reviewing pull requests
- Use `/error-handling` when implementing try/catch patterns
- Use `/hexagonal-architecture` when creating domain or adapter code
This trades a small amount of context economy for significantly more reliable invocation.
2. Use the Skill Tool Explicitly¶
In prompts to Claude, reference the Skill tool directly:
Use the Skill tool to invoke the `code-review` skill, then review this PR.
This removes ambiguity and forces the invocation.
3. Use Fully Qualified Skill Names¶
When a project or skill pack uses namespaced skills, reference the full qualified name:
Use the `/my-project:error-handling` skill.
4. Write Precise description Frontmatter¶
The description field is how Claude decides whether to auto-invoke a skill. Vague
descriptions lead to unreliable matching. Be specific about triggers:
# Bad — vague, Claude may not match this to relevant situations
description: "Helps with code quality"
# Good — specific triggers Claude can match against
description: |
Reviews code for security vulnerabilities, performance issues, and style violations.
Use when reviewing pull requests, auditing code, or when the user asks about
code quality, best practices, or security concerns.
5. Preload Skills into Custom Sub-agents¶
Custom sub-agents (.claude/agents/) support a skills: frontmatter field that injects
the full skill content into the agent's context at startup:
---
skills:
- error-handling
- code-review
---
This guarantees the sub-agent has access to the skill content—no probabilistic invocation needed. Note that ad-hoc Task tool sub-agents (Explore, Plan, general-purpose) do not support this mechanism; for those, pass skill content directly in the prompt.
Limitations and Future Work¶
Current Limitations¶
- No runtime enforcement: Configuration is documentation, not code
- Manual configuration: Users must edit the YAML block
- No validation: Skills can't verify configuration is correct
Future Improvements (Epic 3)¶
- Example implementations: Concrete skills demonstrating the pattern
- Self-initialization logic: Built-in scan/prompt patterns
- Configuration validation: Check paths exist, types are correct
Summary¶
Configurable skills solve the portability problem by separating:
- The Pattern (universal knowledge) in skill instructions
- The Configuration (project-specific values) in a YAML block
Key Concepts:
- Configuration Schema: YAML block with required/optional keys
- Self-Initialization: Scan, prompt, or hybrid to get values
- Reference by Name: Instructions use "the domain directory" not
src/domain
This pattern enables true skill reusability—write once, configure per project.
Previous: Section 6 - Migration Guide Next: Worked Examples