Skip to main content

Compositions

Skills reach full power when combined with other Claude Code extension points. Each composition addresses a specific architectural need that neither mechanism handles alone.

Skills + Hooks

Skills are advisory — Claude follows them voluntarily. Hooks are deterministic — they execute shell commands regardless of what Claude decides. The combination gives you guidance with enforcement.

The pattern: A skill teaches Claude the standard. A hook validates the result.

.claude/skills/commit-messages/SKILL.md teaches Claude the commit format:

# Commit Message Standards
## Format
<type>(<scope>): <subject>
 
## Rules
- type: feat|fix|docs|style|refactor|perf|test|build|ci|chore
- scope: component or module name
- subject: imperative mood, no period, max 72 chars

.claude/settings.json hooks enforce it:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "command": "python scripts/validate-commit-msg.py",
        "description": "Validates commit message format after git commit"
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "python scripts/block-force-push.py",
        "description": "Blocks git push --force on main/master"
      }
    ]
  }
}

Why both? The skill reduces hook trigger frequency. When Claude follows the skill's instructions correctly, the PostToolUse hook passes silently. The hook only catches the cases where Claude deviates — typos in the type field, missing scope, subject over 72 chars.

PreToolUse hooks can BLOCK actions. This is the only mechanism in Claude Code that can prevent a tool call from executing. PostToolUse hooks validate after execution but cannot undo it.

When to Use Each

RequirementMechanism
Claude should follow a workflowSkill
A constraint must never be violatedHook
Format output before it reaches the userHook (PostToolUse)
Prevent a dangerous command from runningHook (PreToolUse)
Guide Claude through a multi-step processSkill
Auto-format files after editsHook (PostToolUse)

Skills + Subagents (context: fork)

The context: fork frontmatter field runs a skill in an isolated subagent. The subagent gets its own context window, does not see conversation history, and returns a concise summary.

---
name: analyzing-dependencies
description: |
  Dependency analysis expert. ALWAYS invoke when asked about
  dependencies, imports, or module relationships.
context: fork
allowed-tools: Read,Grep,Glob,Bash(find:*)
---

When to Fork

ScenarioFork?Reason
Exploration that reads 20+ files✓ YesKeeps main context clean
Validation producing verbose output✓ YesSummary is more useful than raw output
Task needing a fresh perspective✓ YesNo conversation bias
Task needing conversation context✗ NoSubagent cannot see prior decisions
Interactive workflow with user feedback✗ NoSubagent cannot interact with user
Quick task (< 3 tool calls)✗ NoFork overhead exceeds benefit

The fork overhead is real: spinning up a subagent, injecting the skill, summarizing results. For tasks under 3 tool calls, the overhead costs more than the context savings.

Skills + CLAUDE.md

CLAUDE.md loads every turn. Skills load on demand. The composition creates a two-layer system: CLAUDE.md provides always-present directives, skills provide detailed procedures when needed.

CLAUDE.md references skills by name:

## Deployment
Before deploying, always run `/deploy-checklist`. Do not push to
production without completing the checklist.
 
## Code Review
Use `/review` before creating any PR. See .claude/skills/review/
for the full checklist.

This pattern keeps CLAUDE.md under its recommended 200-line / 2,000-token budget. The directive is short (two lines), but the actual procedure can be 200+ lines in the skill.

The precedence rule: When CLAUDE.md and a skill give contradictory instructions, the skill tends to win for the specific task. The skill's content is more recent in the conversation and more contextually relevant. Keep them consistent to avoid ambiguity.

Token Budget Breakdown

A well-composed setup:

ComponentTokensFrequency
CLAUDE.md~1,500Every turn
15 skill descriptions~1,500Every turn
1-2 invoked skill bodies~3,000-6,000Current task only
Baseline overhead~3,000Always

Compare this to cramming everything into CLAUDE.md: 15 detailed workflows at ~400 tokens each = 6,000 tokens on every turn, most of it irrelevant to the current task.

Skills + MCP

MCP provides tools. Skills provide the procedure for using those tools effectively. MCP gives Claude the ability to query a database. A skill tells Claude the migration workflow, safety checks, and rollback procedure.

---
name: database-migration
description: |
  Database migration workflow. ALWAYS invoke when creating, modifying,
  or rolling back database migrations. Requires PostgreSQL MCP server.
allowed-tools: Read,Write,Edit,Bash(npm:*),mcp__postgres__query
---
# Database Migration Workflow
 
## Prerequisites
- PostgreSQL MCP server must be connected
- Run `mcp__postgres__query` to verify connection
 
## Process
1. Check current migration state: query the migrations table
2. Generate migration file with timestamp naming
3. Write UP and DOWN migrations
4. Test DOWN migration rolls back cleanly
5. Apply migration to development database
6. Verify schema matches expectations

The allowed-tools field is critical here. It restricts the skill to only the MCP tools it needs. Without it, Claude could use any connected MCP tool during the skill execution — including destructive ones from other servers.

Hidden cost warning: Each MCP server loads its full tool schema into context on every request, even when unused. A server with 20 tools can consume 5,000-10,000 tokens just by existing. If you have multiple MCP servers, the schema overhead alone can eat 20-30% of your context budget. Use Tool Search / lazy loading to mitigate.

Skill Chaining

Skills do not call each other directly. Claude is the coordinator. Two approaches work in production.

Approach 1: Orchestrator Skill

A parent skill that instructs Claude to invoke other skills in sequence. The full SKILL.md:

---
name: releasing
description: |
  Release orchestrator. ALWAYS invoke when the user says "release",
  "ship it", "deploy to production", or "cut a release". Do not
  deploy directly — use this skill to coordinate the pipeline.
---
 
# Release Workflow
 
## Steps
1. Invoke `/review` to review all changes
2. If review passes, invoke `/test-suite` to run full tests
3. If tests pass, invoke `/deploy staging` to deploy to staging
4. After staging verification, invoke `/deploy production`
 
## State
After each step, record the result in `.claude/release-state.json`
so the workflow can resume if interrupted.
 
## Failure Handling
- If any step returns FAIL, STOP the pipeline
- Record the failure in the state file with the error message
- Report which step failed and what needs to be fixed
- Do NOT skip failed steps or continue to the next stage

The orchestrator skill stays in context while the child skills are invoked. Each child skill adds its body to the conversation. For long chains, this accumulates context rapidly — consider using context: fork on child skills to keep the main context clean.

Approach 2: Shared State Files

Each skill reads and writes to a shared state file. The orchestrator (or CLAUDE.md directive) determines which skill runs next based on the state:

{
  "workflow": "release",
  "current_step": "review",
  "results": {
    "review": { "status": "pass", "timestamp": "2026-04-16T10:00:00Z" },
    "tests": null,
    "staging": null,
    "production": null
  }
}

This pattern survives session boundaries. If the session ends mid-workflow, the next session can read the state file and resume from the correct step.

Skills + Memory

Skills can interact with Claude's memory system for cross-session learning.

Auto Memory (~/.claude/projects/<project>/memory/): Claude saves notes for itself across sessions. A skill can instruct Claude to persist learnings.

CLAUDE.md updates: A skill can instruct Claude to append discovered conventions to CLAUDE.md, evolving the project's baseline instructions over time.

Custom state files: Skills can read/write JSON files in the project for workflow state persistence.

A complete skill with memory integration:

---
name: onboarding-codebase
description: |
  Codebase onboarding assistant. ALWAYS invoke when a user asks
  "how does X work" or needs to understand a module. Persists
  learnings across sessions.
context: fork
allowed-tools: Read,Grep,Glob,Bash(find:*),Bash(wc:*)
---
 
# Codebase Onboarding
 
## Step 1: Check Memory
Read `~/.claude/projects/<project>/memory/` for prior exploration notes.
Skip any areas already documented.
 
## Step 2: Explore
Investigate $ARGUMENTS — trace entry points, data flow, and dependencies.
 
## Step 3: Synthesize
Return a structured summary: entry points, key files, data flow, gotchas.
 
## Step 4: Persist
After completing this workflow:
1. If you discovered a new project convention, append it to CLAUDE.md
2. If this is a recurring pattern, save a note to memory about it
3. Update .claude/workflow-state.json with the completion status

This creates a feedback loop: skills execute workflows, discover patterns, persist knowledge, and future sessions benefit from that accumulated context. The skill itself does not change — the memory layer accumulates around it.

Composition Decision Matrix

I need...Composition
Guidance + enforcementSkill + Hook
Detailed procedure without context bloatSkill + CLAUDE.md reference
Tool access with safety proceduresSkill + MCP + allowed-tools
Multi-skill workflowsOrchestrator Skill + child skills
Workflows that survive session boundariesSkill + shared state files
Cross-session learningSkill + Memory
Heavy exploration without polluting contextSkill + context: fork
Dangerous operations with guardrailsSkill + Hook (PreToolUse) + disable-model-invocation