playbook/outfitter-agents/plugins/outfitter/skills/skills-dev/references/claude-code.md

14 KiB

Claude Code Extensions

Note: For comprehensive Claude Code skill development, load the outfitter:claude-skills skill. This reference provides a quick overview.

Claude Code-specific implementation details for Agent Skills. For cross-platform concepts (structure, frontmatter, validation), load the outfitter:skills-dev skill.

Table of Contents


Frontmatter Extensions

Claude Code extends the base Agent Skills specification with additional frontmatter fields:

Field Type Description
allowed-tools string Space-separated list of tools the skill can use without permission prompts
user-invocable boolean Default true. Set to false to prevent slash command access
disable-model-invocation boolean Prevents automatic activation; requires manual invocation via Skill tool
context string inherit (default) or fork for isolated subagent execution
agent string Agent to use when skill is invoked (e.g., outfitter:analyst)
model string Override model: haiku, sonnet, or opus
hooks object Lifecycle hooks: on-activate, on-complete
argument-hint string Hint text shown after /skill-name (e.g., [file path])

Example

---
name: code-review
version: 1.0.0
description: Reviews code for bugs, security issues, and best practices. Use when reviewing PRs, auditing code, or before merging.
allowed-tools: Read Grep Glob Bash(git diff *)
argument-hint: [file or directory]
model: sonnet
---

Note: user-invocable defaults to true, so skills are callable as /skill-name by default. Only set user-invocable: false if you want to prevent slash command access.


Tool Restrictions

Use allowed-tools to specify which tools Claude can use when a skill is active. Listed tools run without permission prompts.

Syntax

# Space-separated list
allowed-tools: Read Grep Glob

# With Bash patterns
allowed-tools: Read Write Bash(git *) Bash(npm run *)

# MCP tools (double underscore format)
allowed-tools: Read mcp__linear__create_issue mcp__memory__store

Bash Pattern Syntax

Pattern Meaning Example
Bash(git *) All git commands git status, git commit
Bash(git add:*) Specific subcommand git add ., git add file.ts
Bash(npm run *:*) Nested patterns npm run test:unit

Common Patterns

# Read-only analysis
allowed-tools: Read Grep Glob

# File modifications
allowed-tools: Read Edit Write

# Git operations
allowed-tools: Read Write Bash(git *)

# Testing workflows
allowed-tools: Read Write Bash(bun test:*) Bash(npm test:*)

# Full development
allowed-tools: Read Edit Write Bash(git *) Bash(bun *) Bash(npm *)

Tool Names (Case-Sensitive)

Tool Purpose
Read Read files
Write Write new files
Edit Edit existing files
Grep Search file contents
Glob Find files by pattern
Bash Execute bash commands
WebFetch Fetch web content
WebSearch Search the web

Behavior

  • With allowed-tools: Listed tools run without permission prompts
  • Without allowed-tools: Inherits conversation permissions; Claude may ask

User Invocable Skills

Skills are callable as slash commands by default (user-invocable: true). Use user-invocable: false to prevent slash command access for skills that should only be auto-activated.

---
name: code-review
description: Reviews code for bugs and best practices...
argument-hint: [file or PR number]
---

Users can invoke with /code-review src/auth.ts or wait for auto-activation based on the description.

Disabling Slash Command Access

For skills that should only activate automatically (not manually invoked):

---
name: internal-validator
description: Validates internal state when specific patterns are detected...
user-invocable: false
---

With Arguments

The argument-hint field provides context in the command picker:

argument-hint: [error message or bug description]

Arguments are available in the skill body via $ARGUMENTS.


String Substitutions

Claude Code supports these substitution patterns in skill content:

Pattern Replaced With
$ARGUMENTS User input after /skill-name
${CLAUDE_SESSION_ID} Current session identifier
${CLAUDE_PLUGIN_ROOT} Path to the plugin root directory

Example

# Debug Skill

Investigating: $ARGUMENTS

Session: ${CLAUDE_SESSION_ID}

Use the debugging script:
${CLAUDE_PLUGIN_ROOT}/scripts/debug-helper.ts

Dynamic Context Injection

Use backtick-command syntax to inject dynamic content:

## Current Git Status

`git status`

## Recent Changes

`git log --oneline -5`

When Claude loads the skill, these commands execute and their output replaces the command syntax.

Use cases:

  • Current branch state
  • Environment information
  • Dynamic configuration
  • Recent history

Context Modes

The context field controls how skills execute:

inherit (default)

Skill runs in the main conversation context. Has access to conversation history and prior tool results.

context: inherit

fork

Skill runs in an isolated subagent context. Useful for:

  • Preventing context pollution
  • Parallel execution
  • Specialized processing that shouldn't affect main conversation
context: fork
agent: outfitter:analyst
model: haiku

When context: fork, the skill can specify:

  • agent: Which agent type handles the fork
  • model: Override model for the forked context

Testing with Debug Mode

claude --debug

Debug output shows:

  • Loaded skill: skill-name from path — Skill discovered
  • Error loading skill: reason — Loading failed
  • Considering skill: skill-name — Activation being evaluated
  • Skill allowed-tools: [list] — Tool restrictions applied

Testing Process

  1. Verify loading: Run claude --debug and check for load messages
  2. Test discovery: Ask Claude something that should trigger the skill
  3. Verify tool restrictions: Confirm permitted tools run without prompts
  4. Test with real data: Run actual workflows

Example Test Session

# Start debug session
claude --debug

# In conversation, trigger the skill naturally:
# "Can you help me process this PDF file?"

# Look for:
# "Considering skill: pdf-processor"
# "Activated skill: pdf-processor"

Force Skill Reload

Skills are cached per session. To reload after changes:

/clear

Troubleshooting

Skill Not Loading

Check file location:

# Personal skills
ls ~/.claude/skills/my-skill/SKILL.md

# Project skills
ls .claude/skills/my-skill/SKILL.md

# Plugin skills
ls <plugin-path>/skills/my-skill/SKILL.md

Validate YAML frontmatter:

# Check for tabs (YAML requires spaces)
grep -P "\t" SKILL.md

# Validate syntax
bun run outfitter/scripts/validate-skill-frontmatter.ts SKILL.md

Check file permissions:

chmod 644 SKILL.md
chmod +x scripts/*.sh

Skill Not Activating

Improve description specificity:

# Before (too vague)
description: Helps with files

# After (specific with triggers)
description: Parse and validate JSON files including schema validation. Use when working with JSON data, .json files, or configuration files.

Add trigger keywords that users naturally say:

  • File types: .pdf, .json, .xlsx
  • Actions: parse, validate, test, analyze
  • Domains: API, database, spreadsheet

Tool Permission Errors

Tool names are case-sensitive:

# Correct
allowed-tools: Read Grep Glob

# Wrong
allowed-tools: read grep glob

Bash patterns need wildcards:

# Correct
allowed-tools: Bash(git *)

# Wrong (matches nothing)
allowed-tools: Bash(git)

MCP tools use double underscores:

# Correct
allowed-tools: mcp__memory__store

# Wrong
allowed-tools: mcp_memory_store

Script Execution Errors

Ensure executable:

chmod +x scripts/*.sh

Use portable shebang:

#!/usr/bin/env bash  # Recommended
#!/bin/bash          # Also works

Use ${CLAUDE_PLUGIN_ROOT} for paths:

# Correct
${CLAUDE_PLUGIN_ROOT}/scripts/process.sh input.txt

# Wrong (breaks portability)
/Users/me/.claude/skills/my-skill/scripts/process.sh

Integration Patterns

With Commands

Skills activate automatically when commands need their expertise:

Command (.claude/commands/analyze-pdf.md):

---
description: Analyze PDF file
---

Analyze this PDF file: $ARGUMENTS

Use the PDF processing skill for extraction and analysis.

When user runs /analyze-pdf report.pdf, Claude recognizes the PDF context and activates the skill.

With Hooks

Hooks can suggest skill usage:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)|Edit(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Consider using typescript-linter skill'"
          }
        ]
      }
    ]
  }
}

Using Skill Tool

Load skills programmatically with the Skill tool:

Use the Skill tool to invoke the pdf-processor skill

This is useful for:

  • Forcing specific skill activation
  • Chaining skills together
  • Loading skills for agents

Master-Clone Architecture

For orchestrating specialized work with context isolation:

Master Agent: Coordinates, maintains conversation context, delegates specialized tasks Clone Agents: Isolated context, loads specific skill, returns focused output

User request
   ↓
Master agent decides: needs security analysis
   ↓
Launch clone agent with security-audit skill
   ↓
Clone returns findings (only findings in main context)
   ↓
Master synthesizes and continues

Advantage over inline execution: Master preserves main conversation context; specialist work happens in isolated bubble.

Implementation

---
name: security-audit
context: fork
agent: outfitter:reviewer
model: sonnet
---

Or via Task tool:

{
  "description": "Security audit of auth module",
  "prompt": "Review src/auth/ for vulnerabilities using security-audit skill",
  "subagent_type": "outfitter:reviewer",
  "run_in_background": true
}

Hook-Based Validation

Use hooks to enforce constraints at decision points.

PreToolUse Hook Example

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write(**/SKILL.md)|Edit(**/SKILL.md)",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-skill-frontmatter.ts",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

Use Cases

  • Prevent destructive operations
  • Enforce testing requirements
  • Validate configuration before deployment
  • Check security constraints
  • Validate skill frontmatter before saving

Block at Submit Pattern

export async function blockAtSubmit() {
  const issues = await runStaticAnalysis();
  const testsPassing = await runTestSuite();
  const securityClear = await runSecurityAudit();

  return {
    block: issues.length > 0 || !testsPassing || !securityClear,
    reason: formatBlockingIssues(issues)
  };
}

Skill + MCP Integration

Pattern: Skills provide workflows, MCP servers provide data/tools.

Example Architecture

  • MCP Server: Linear API access (issues, projects, users)
  • Skill: Project standup workflow (what data to pull, how to format, communication patterns)
---
name: linear-standup
description: Generates team standup reports from Linear issues
allowed-tools: mcp__linear__get_issues mcp__linear__get_projects
---

# Linear Standup Skill

Use the Linear MCP server to:
1. Fetch issues by status and assignee
2. Group by project and priority
3. Format as standup report

Why Separate

  • MCP handles authentication, rate limiting, data access
  • Skill handles business logic, formatting, workflows
  • Easier to reuse across similar domains

Performance Tips

Keep SKILL.md Small

Token impact of skill size:

  • 300 lines ≈ 2,000 tokens
  • 1,500 lines ≈ 10,000 tokens

Each activation loads the full SKILL.md. Use progressive disclosure.

Tool Restrictions Speed Up Execution

Without restrictions: Claude asks permission for each tool. With restrictions: Listed tools run immediately.

# Fast (no prompts for these tools)
allowed-tools: Read Grep Glob

Quick Reference

# Find all skills
find ~/.claude/skills .claude/skills -name "SKILL.md" 2>/dev/null

# Validate YAML
bun run outfitter/scripts/validate-skill-frontmatter.ts SKILL.md

# Check for tabs
grep -P "\t" SKILL.md

# Test in debug mode
claude --debug

For comprehensive guidance, load the relevant skill:

  • Claude Code skills: outfitter:claude-skills
  • Cross-platform skills: outfitter:skills-dev
  • Plugin development: outfitter:claude-plugins
  • Hook integration: outfitter:claude-hooks
  • Command integration: outfitter:claude-commands

Reference docs in this directory: