Building Custom Skills for Claude

Learn how to create, deploy, and manage custom skills to extend Claude’s capabilities with your organization’s specialized knowledge and workflows.

Table of Contents

  1. Introduction & Setup
  2. Understanding Custom Skills Architecture
  3. Example 1: Financial Ratio Calculator
  4. Example 2: Company Brand Guidelines
  5. Example 3: Financial Modeling Suite
  6. Skill Management & Versioning
  7. Best Practices & Production Tips
  8. Troubleshooting

1. Introduction & Setup

What are Custom Skills?

Custom skills are specialized expertise packages you create to teach Claude your organization’s unique workflows, domain knowledge, and best practices. Unlike Anthropic’s pre-built skills (Excel, PowerPoint, PDF), custom skills allow you to:

  • Codify organizational knowledge - Capture your team’s specific methodologies
  • Ensure consistency - Apply the same standards across all interactions
  • Automate complex workflows - Chain together multi-step processes
  • Maintain intellectual property - Keep proprietary methods secure

Key Benefits

Benefit Description
Expertise at Scale Deploy specialized knowledge to every Claude interaction
Version Control Track changes and roll back if needed
Composability Combine multiple skills for complex tasks
Privacy Your skills remain private to your organization

Prerequisites

Before starting, ensure you have: - Completed Notebook 1: Introduction to Skills - An Anthropic API key with Skills beta access - Python environment with the local SDK installed

Environment Setup

Let’s set up our environment and import necessary libraries:

import os
import sys
from pathlib import Path
from typing import Any

# Add parent directory for imports
sys.path.insert(0, str(Path.cwd().parent))

from anthropic import Anthropic
from anthropic.lib import files_from_dir
from dotenv import load_dotenv

# Import our utilities
from file_utils import (
    download_all_files,
    extract_file_ids,
    print_download_summary,
)

# We'll create skill_utils later in this notebook
# from skill_utils import (
#     create_skill,
#     list_skills,
#     delete_skill,
#     test_skill
# )

# Load environment variables
load_dotenv(Path.cwd().parent / ".env")

API_KEY = os.getenv("ANTHROPIC_API_KEY")
MODEL = os.getenv("ANTHROPIC_MODEL", "claude-sonnet-4-6")

if not API_KEY:
    raise ValueError(
        "ANTHROPIC_API_KEY not found. Copy ../.env.example to ../.env and add your API key."
    )

# Initialize client with Skills beta
client = Anthropic(api_key=API_KEY, default_headers={"anthropic-beta": "skills-2025-10-02"})

# Setup directories
SKILLS_DIR = Path.cwd().parent / "custom_skills"
OUTPUT_DIR = Path.cwd().parent / "outputs"
OUTPUT_DIR.mkdir(exist_ok=True)

print("✓ API key loaded")
print(f"✓ Using model: {MODEL}")
print(f"✓ Custom skills directory: {SKILLS_DIR}")
print(f"✓ Output directory: {OUTPUT_DIR}")
print("\n📝 Skills beta header configured for skill management")

2. Understanding Custom Skills Architecture {#architecture}### Skill StructureEvery custom skill follows this directory structure:skill_name/├── SKILL.md # REQUIRED: Instructions with YAML frontmatter├── *.md # Optional: Any additional .md files (documentation, guides)├── scripts/ # Optional: Executable code│ ├── process.py│ └── utils.js└── resources/ # Optional: Templates, data files └── template.xlsxImportant: - SKILL.md is the ONLY required file - everything else is optional- Multiple .md files allowed - You can have any number of markdown files in the top-level folder- All .md files are loaded - Not just SKILL.md and REFERENCE.md, but any .md file you include- Organize as needed - Use multiple .md files to structure complex documentation📖 Read our engineering blog post on Equipping agents for the real world with Skills### Skills Are Not Just MarkdownSkills Can Include Scripts and FilesSkills can bundle various file types:- Markdown files: Instructions and documentation (SKILL.md, REFERENCE.md, etc.)- Scripts: Python, JavaScript, or other executable code for complex operations- Templates: Pre-built files that can be customized (Excel templates, document templates)- Resources: Supporting data files, configuration, or assets### SKILL.md RequirementsThe SKILL.md file must include:1. YAML Frontmatter (name: 64 chars, description: 1024 chars) - name: Lowercase alphanumeric with hyphens (required) - description: Brief description of what the skill does (required)2. Instructions (markdown format) - Clear guidance for Claude - Examples of usage - Any constraints or rules - Recommended: Keep under 5,000 tokens### Additional Documentation FilesYou can include multiple markdown files for better organization:skill_name/├── SKILL.md # Main instructions (required)├── REFERENCE.md # API reference (optional)├── EXAMPLES.md # Usage examples (optional)├── TROUBLESHOOTING.md # Common issues (optional)└── CHANGELOG.md # Version history (optional)All .md files in the root directory will be available to Claude when the skill is loaded.### Bundled Files ExampleBundled Files in SkillsThis example shows how Skills can bundle multiple files:- SKILL.md: Contains the main instructions with colors, typography, and sections- slide-decks.md: Additional documentation for specific use cases- Scripts and resources: Can be referenced and used during skill execution### Progressive DisclosureSkills load in three stages to optimize token usage:| Stage | Content | Token Cost | When Loaded ||——-|———|————|————-|| 1. Metadata | Name & description | name: 64 chars, description: 1024 chars | Always visible || 2. Instructions | All .md files | <5,000 tokens recommended | When relevant || 3. Resources | Scripts & files | As needed | During execution |### API Workflowpython# 1. Create skillskill = client.beta.skills.create( display_title="My Skill", files=files_from_dir("path/to/skill"))# 2. Use in messagesresponse = client.beta.messages.create( container={ "skills": [{ "type": "custom", "skill_id": skill.id, "version": "latest" }] }, # ... rest of message parameters)### Best PracticesFor detailed guidance on skill creation and best practices, see:- Claude Skills Best Practices- Skills Documentation

Create Skill Utility Functions

Let’s create helper functions for skill management:

def create_skill(client: Anthropic, skill_path: str, display_title: str) -> dict[str, Any]:
    """
    Create a new custom skill from a directory.

    Args:
        client: Anthropic client instance
        skill_path: Path to skill directory
        display_title: Human-readable skill name

    Returns:
        Dictionary with skill_id, version, and metadata
    """
    try:
        # Create skill using files_from_dir
        skill = client.beta.skills.create(
            display_title=display_title, files=files_from_dir(skill_path)
        )

        return {
            "success": True,
            "skill_id": skill.id,
            "display_title": skill.display_title,
            "latest_version": skill.latest_version,
            "created_at": skill.created_at,
            "source": skill.source,
        }
    except Exception as e:
        return {"success": False, "error": str(e)}


def list_custom_skills(client: Anthropic) -> list[dict[str, Any]]:
    """
    List all custom skills in the workspace.

    Returns:
        List of skill dictionaries
    """
    try:
        skills_response = client.beta.skills.list(source="custom")

        skills = []
        for skill in skills_response.data:
            skills.append(
                {
                    "skill_id": skill.id,
                    "display_title": skill.display_title,
                    "latest_version": skill.latest_version,
                    "created_at": skill.created_at,
                    "updated_at": skill.updated_at,
                }
            )

        return skills
    except Exception as e:
        print(f"Error listing skills: {e}")
        return []


def delete_skill(client: Anthropic, skill_id: str) -> bool:
    """
    Delete a custom skill and all its versions.

    Args:
        client: Anthropic client
        skill_id: ID of skill to delete

    Returns:
        True if successful, False otherwise
    """
    try:
        # First delete all versions
        versions = client.beta.skills.versions.list(skill_id=skill_id)

        for version in versions.data:
            client.beta.skills.versions.delete(skill_id=skill_id, version=version.version)

        # Then delete the skill itself
        client.beta.skills.delete(skill_id)
        return True

    except Exception as e:
        print(f"Error deleting skill: {e}")
        return False


def test_skill(
    client: Anthropic,
    skill_id: str,
    test_prompt: str,
    model: str = "claude-sonnet-4-6",
) -> Any:
    """
    Test a custom skill with a prompt.

    Args:
        client: Anthropic client
        skill_id: ID of skill to test
        test_prompt: Prompt to test the skill
        model: Model to use for testing

    Returns:
        Response from Claude
    """
    response = client.beta.messages.create(
        model=model,
        max_tokens=4096,
        container={"skills": [{"type": "custom", "skill_id": skill_id, "version": "latest"}]},
        tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
        messages=[{"role": "user", "content": test_prompt}],
        betas=[
            "code-execution-2025-08-25",
            "files-api-2025-04-14",
            "skills-2025-10-02",
        ],
    )

    return response


print("✓ Skill utility functions defined")
print("  - create_skill()")
print("  - list_custom_skills()")
print("  - delete_skill()")
print("  - test_skill()")

Check Existing Custom Skills

Let’s see if any custom skills already exist in your workspace:

⚠️ Important: Clean Up Existing Skills Before Starting

If you’re re-running this notebook, you may have skills from a previous session. Skills cannot have duplicate display titles, so you have three options:

  1. Delete existing skills (recommended for testing) - Clean slate approach
  2. Use different display titles - Add timestamps or version numbers to names
  3. Update existing skills with new versions - See Skill Management & Versioning section

Let’s check for and optionally clean up existing skills:

# Check for existing skills that might conflict
existing_skills = list_custom_skills(client)
skill_titles_to_create = [
    "Financial Ratio Analyzer",
    "Corporate Brand Guidelines",
    "Financial Modeling Suite",
]
conflicting_skills = []

if existing_skills:
    print(f"Found {len(existing_skills)} existing custom skill(s):")
    for skill in existing_skills:
        print(f"  - {skill['display_title']} (ID: {skill['skill_id']})")
        if skill["display_title"] in skill_titles_to_create:
            conflicting_skills.append(skill)

    if conflicting_skills:
        print(
            f"\n⚠️ Found {len(conflicting_skills)} skill(s) that will conflict with this notebook:"
        )
        for skill in conflicting_skills:
            print(f"  - {skill['display_title']} (ID: {skill['skill_id']})")

        print("\n" + "=" * 70)
        print("To clean up these skills and start fresh, uncomment and run:")
        print("=" * 70)
        print("\n# UNCOMMENT THE LINES BELOW TO DELETE CONFLICTING SKILLS:")
        print("# for skill in conflicting_skills:")
        print("#     if delete_skill(client, skill['skill_id']):")
        print("#         print(f\"✅ Deleted: {skill['display_title']}\")")
        print("#     else:")
        print("#         print(f\"❌ Failed to delete: {skill['display_title']}\")")

        # for skill in conflicting_skills:
        #     if delete_skill(client, skill['skill_id']):
        #         print(f"✅ Deleted: {skill['display_title']}")
        #     else:
        #         print(f"❌ Failed to delete: {skill['display_title']}")
    else:
        print("\n✅ No conflicting skills found. Ready to proceed!")
else:
    print("✅ No existing custom skills found. Ready to create new ones!")

3. Example 1: Financial Ratio Calculator

Let’s create our first custom skill - a financial ratio calculator that can analyze company financial health.

Skill Overview

The Financial Ratio Calculator skill will: - Calculate key financial ratios (ROE, P/E, Current Ratio, etc.) - Interpret ratios with industry context - Generate formatted reports - Work with various data formats (CSV, JSON, text)

Upload the Financial Analyzer Skill

Now let’s upload our financial analyzer skill to Claude:

# Upload the Financial Analyzer skill
financial_skill_path = SKILLS_DIR / "analyzing-financial-statements"

if financial_skill_path.exists():
    print("Uploading Financial Analyzer skill...")
    result = create_skill(client, str(financial_skill_path), "Financial Ratio Analyzer")

    if result["success"]:
        financial_skill_id = result["skill_id"]
        print("✅ Skill uploaded successfully!")
        print(f"   Skill ID: {financial_skill_id}")
        print(f"   Version: {result['latest_version']}")
        print(f"   Created: {result['created_at']}")
    else:
        print(f"❌ Upload failed: {result['error']}")
        if "cannot reuse an existing display_title" in str(result["error"]):
            print("\n💡 Solution: A skill with this name already exists.")
            print("   Run the 'Clean Up Existing Skills' cell above to delete it first,")
            print("   or change the display_title to something unique.")
else:
    print(f"⚠️ Skill directory not found: {financial_skill_path}")
    print(
        "Please ensure the custom_skills directory contains the analyzing-financial-statements folder."
    )

Test the Financial Analyzer Skill

Let’s test the skill with sample financial data:

# Test the Financial Analyzer skill
if "financial_skill_id" in locals():
    test_prompt = """
    Calculate financial ratios for this company:

    Income Statement:
    - Revenue: $1,000M
    - EBITDA: $200M
    - Net Income: $120M

    Balance Sheet:
    - Total Assets: $2,000M
    - Current Assets: $500M
    - Current Liabilities: $300M
    - Total Debt: $400M
    - Shareholders Equity: $1,200M

    Market Data:
    - Share Price: $50
    - Shares Outstanding: 100M

    Please calculate key ratios and provide analysis.
    """

    print("Testing Financial Analyzer skill...")
    response = test_skill(client, financial_skill_id, test_prompt)

    # Print response
    for content in response.content:
        if content.type == "text":
            print(content.text)
else:
    print("⚠️ Please upload the Financial Analyzer skill first (run the previous cell)")

4. Example 2: Company Brand Guidelines

Now let’s create a skill that ensures all documents follow corporate brand standards.

Skill Overview

The Brand Guidelines skill will: - Apply consistent colors, fonts, and layouts - Ensure logo placement and usage - Maintain professional tone and messaging - Work across all document types (Excel, PowerPoint, PDF)

# Upload the Brand Guidelines skill
brand_skill_path = SKILLS_DIR / "applying-brand-guidelines"

if brand_skill_path.exists():
    print("Uploading Brand Guidelines skill...")
    result = create_skill(client, str(brand_skill_path), "Corporate Brand Guidelines")

    if result["success"]:
        brand_skill_id = result["skill_id"]
        print("✅ Skill uploaded successfully!")
        print(f"   Skill ID: {brand_skill_id}")
        print(f"   Version: {result['latest_version']}")
    else:
        print(f"❌ Upload failed: {result['error']}")
        if "cannot reuse an existing display_title" in str(result["error"]):
            print("\n💡 Solution: A skill with this name already exists.")
            print("   Run the 'Clean Up Existing Skills' cell above to delete it first,")
            print("   or change the display_title to something unique.")
else:
    print(f"⚠️ Skill directory not found: {brand_skill_path}")

Test Brand Guidelines with Document Creation

Let’s test the brand skill by creating a branded PowerPoint presentation:

# Test Brand Guidelines skill with PowerPoint creation
if "brand_skill_id" in locals():
    # Combine brand skill with Anthropic's pptx skill
    response = client.beta.messages.create(
        model=MODEL,
        max_tokens=4096,
        container={
            "skills": [
                {"type": "custom", "skill_id": brand_skill_id, "version": "latest"},
                {"type": "anthropic", "skill_id": "pptx", "version": "latest"},
            ]
        },
        tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
        messages=[
            {
                "role": "user",
                "content": """Create a 3-slide PowerPoint presentation following Acme Corporation brand guidelines:

            Slide 1: Title slide for "Q4 2025 Results"
            Slide 2: Revenue Overview with a chart showing Q1-Q4 growth
            Slide 3: Key Achievements (3 bullet points)

            Apply all brand colors, fonts, and formatting standards.
            """,
            }
        ],
        betas=[
            "code-execution-2025-08-25",
            "files-api-2025-04-14",
            "skills-2025-10-02",
        ],
    )

    print("Response from Claude:")
    for content in response.content:
        if content.type == "text":
            print(content.text[:500] + "..." if len(content.text) > 500 else content.text)

    # Download generated file
    file_ids = extract_file_ids(response)
    if file_ids:
        results = download_all_files(
            client, response, output_dir=str(OUTPUT_DIR), prefix="branded_"
        )
        print_download_summary(results)
else:
    print("⚠️ Please upload the Brand Guidelines skill first")

5. Example 3: Financial Modeling Suite

Let’s create our most advanced skill - a comprehensive financial modeling suite for valuation and risk analysis.

Skill Overview

The Financial Modeling Suite skill provides: - DCF Valuation: Complete discounted cash flow models - Sensitivity Analysis: Test impact of variables on valuation - Monte Carlo Simulation: Risk modeling with probability distributions - Scenario Planning: Best/base/worst case analysis

This demonstrates a multi-file skill with complex calculations and professional-grade financial modeling.

Upload the Financial Modeling Suite

First, upload the financial modeling skill:

# Upload the Financial Modeling Suite skill
modeling_skill_path = SKILLS_DIR / "creating-financial-models"

if modeling_skill_path.exists():
    print("Uploading Financial Modeling Suite skill...")
    result = create_skill(client, str(modeling_skill_path), "Financial Modeling Suite")

    if result["success"]:
        modeling_skill_id = result["skill_id"]
        print("✅ Skill uploaded successfully!")
        print(f"   Skill ID: {modeling_skill_id}")
        print(f"   Version: {result['latest_version']}")
        print("\nThis skill includes:")
        print("   - DCF valuation model (dcf_model.py)")
        print("   - Sensitivity analysis framework (sensitivity_analysis.py)")
        print("   - Monte Carlo simulation capabilities")
        print("   - Scenario planning tools")
    else:
        print(f"❌ Upload failed: {result['error']}")
else:
    print(f"⚠️ Skill directory not found: {modeling_skill_path}")
    print(
        "Please ensure the custom_skills directory contains the creating-financial-models folder."
    )

Test the Financial Modeling Suite

Let’s test the advanced modeling capabilities with a DCF valuation request:

# Test the Financial Modeling Suite with a DCF valuation
if "modeling_skill_id" in locals():
    dcf_test_prompt = """
    Perform a DCF valuation for TechCorp with the following data:

    Historical Financials (Last 3 Years):
    - Revenue: $500M, $600M, $750M
    - EBITDA Margin: 25%, 27%, 30%
    - CapEx: $50M, $55M, $60M
    - Working Capital: 15% of revenue

    Projections:
    - Revenue growth: 20% for years 1-3, then declining to 5% by year 5
    - EBITDA margin expanding to 35% by year 5
    - Terminal growth rate: 3%

    Market Assumptions:
    - WACC: 10%
    - Tax rate: 25%
    - Current net debt: $200M
    - Shares outstanding: 100M

    Please create a complete DCF model with sensitivity analysis on WACC and terminal growth.
    Generate an Excel file with the full model including:
    1. Revenue projections
    2. Free cash flow calculations
    3. Terminal value
    4. Enterprise value to equity value bridge
    5. Sensitivity table
    """

    print("Testing Financial Modeling Suite with DCF valuation...")
    print("=" * 70)
    print("\n⏱️ Note: Complex financial model generation may take 1-2 minutes.\n")

    response = client.beta.messages.create(
        model=MODEL,
        max_tokens=4096,
        container={
            "skills": [
                {"type": "custom", "skill_id": modeling_skill_id, "version": "latest"},
                {"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
            ]
        },
        tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
        messages=[{"role": "user", "content": dcf_test_prompt}],
        betas=[
            "code-execution-2025-08-25",
            "files-api-2025-04-14",
            "skills-2025-10-02",
        ],
    )

    # Print Claude's response
    for content in response.content:
        if content.type == "text":
            # Print first 800 characters to keep output manageable
            text = content.text
            if len(text) > 800:
                print(text[:800] + "\n\n[... Output truncated for brevity ...]")
            else:
                print(text)

    # Download the DCF model if generated
    file_ids = extract_file_ids(response)
    if file_ids:
        print("\n" + "=" * 70)
        print("Downloading generated DCF model...")
        results = download_all_files(
            client, response, output_dir=str(OUTPUT_DIR), prefix="dcf_model_"
        )
        print_download_summary(results)
        print("\n💡 Open the Excel file to explore the complete DCF valuation model!")
else:
    print("⚠️ Please upload the Financial Modeling Suite skill first (run the previous cell)")

6. Skill Management & Versioning

Managing skills over time requires understanding versioning, updates, and lifecycle management.

Listing Your Skills

Get an overview of all custom skills in your workspace:

# List all your custom skills
my_skills = list_custom_skills(client)

if my_skills:
    print(f"You have {len(my_skills)} custom skill(s):\n")
    print("=" * 70)
    for i, skill in enumerate(my_skills, 1):
        print(f"\n{i}. {skill['display_title']}")
        print(f"   Skill ID: {skill['skill_id']}")
        print(f"   Current Version: {skill['latest_version']}")
        print(f"   Created: {skill['created_at']}")
        if skill.get("updated_at"):
            print(f"   Last Updated: {skill['updated_at']}")
    print("\n" + "=" * 70)
else:
    print("No custom skills found in your workspace.")

Creating New Versions

Skills support versioning to maintain history and enable rollback. Let’s make an enhancement to our Financial Analyzer skill and create a new version.

Step 1: Enhance the Financial Analyzer

We’ll add healthcare industry benchmarks to make our skill more versatile. This is a real-world scenario where you’d expand a skill’s capabilities based on user needs.

# Add healthcare industry benchmarks to the Financial Analyzer
# This demonstrates a realistic skill enhancement scenario

if "financial_skill_id" in locals():
    # Read the current interpret_ratios.py file
    interpret_file_path = SKILLS_DIR / "analyzing-financial-statements" / "interpret_ratios.py"

    with open(interpret_file_path) as f:
        content = f.read()

    # Add healthcare benchmarks after the 'manufacturing' section
    healthcare_benchmarks = """        },
        'healthcare': {
            'current_ratio': {'excellent': 2.3, 'good': 1.8, 'acceptable': 1.4, 'poor': 1.0},
            'debt_to_equity': {'excellent': 0.3, 'good': 0.6, 'acceptable': 1.0, 'poor': 1.8},
            'roe': {'excellent': 0.22, 'good': 0.16, 'acceptable': 0.11, 'poor': 0.07},
            'gross_margin': {'excellent': 0.65, 'good': 0.45, 'acceptable': 0.30, 'poor': 0.20},
            'pe_ratio': {'undervalued': 18, 'fair': 28, 'growth': 40, 'expensive': 55}
        """

    # Find the position after manufacturing section and before the closing brace
    insert_pos = content.find("        }\n    }")  # Find the end of the BENCHMARKS dict

    if insert_pos != -1:
        # Insert the healthcare benchmarks
        new_content = content[:insert_pos] + healthcare_benchmarks + content[insert_pos:]

        # Save the enhanced file
        with open(interpret_file_path, "w") as f:
            f.write(new_content)

        print("✅ Enhanced Financial Analyzer with healthcare industry benchmarks")
        print("\nChanges made:")
        print("  - Added healthcare industry to BENCHMARKS")
        print("  - Includes specific thresholds for:")
        print("    • Current ratio (liquidity)")
        print("    • Debt-to-equity (leverage)")
        print("    • ROE (profitability)")
        print("    • Gross margin")
        print("    • P/E ratio (valuation)")
        print("\n📝 Now we can create a new version of the skill with this enhancement!")
    else:
        print("⚠️ Could not find the correct position to insert healthcare benchmarks")
        print("The file structure may have changed.")
else:
    print("⚠️ Please upload the Financial Analyzer skill first (run cells in Section 3)")

Step 2: Create a New Version

Now that we’ve enhanced our skill, let’s create a new version to track this change:

# Create a new version of the enhanced Financial Analyzer skill
def create_skill_version(client: Anthropic, skill_id: str, skill_path: str):
    """Create a new version of an existing skill."""
    try:
        version = client.beta.skills.versions.create(
            skill_id=skill_id, files=files_from_dir(skill_path)
        )
        return {
            "success": True,
            "version": version.version,
            "created_at": version.created_at,
        }
    except Exception as e:
        return {"success": False, "error": str(e)}


# Create the new version with our healthcare enhancement
if "financial_skill_id" in locals():
    print("Creating new version of Financial Analyzer with healthcare benchmarks...")

    result = create_skill_version(
        client, financial_skill_id, str(SKILLS_DIR / "analyzing-financial-statements")
    )

    if result["success"]:
        print("✅ New version created successfully!")
        print(f"   Version: {result['version']}")
        print(f"   Created: {result['created_at']}")
        print("\n📊 Version History:")
        print("   v1: Original skill with tech, retail, financial, manufacturing")
        print(f"   v{result['version']}: Enhanced with healthcare industry benchmarks")
    else:
        print(f"❌ Version creation failed: {result['error']}")
else:
    print("⚠️ Please run the previous cells to upload the skill and make enhancements first")

Step 3: Test the New Version

Let’s verify our enhancement works by analyzing a healthcare company:

# Test the enhanced skill with healthcare industry data
if "financial_skill_id" in locals():
    healthcare_test_prompt = """
    Analyze this healthcare company using the healthcare industry benchmarks:

    Company: MedTech Solutions (Healthcare Industry)

    Income Statement:
    - Revenue: $800M
    - EBITDA: $320M
    - Net Income: $160M

    Balance Sheet:
    - Total Assets: $1,200M
    - Current Assets: $400M
    - Current Liabilities: $200M
    - Total Debt: $300M
    - Shareholders Equity: $700M

    Market Data:
    - Share Price: $75
    - Shares Outstanding: 50M

    Please calculate key ratios and provide healthcare-specific analysis.
    """

    print("Testing enhanced Financial Analyzer with healthcare company...")
    print("=" * 70)

    response = test_skill(client, financial_skill_id, healthcare_test_prompt, MODEL)

    # Print Claude's analysis
    for content in response.content:
        if content.type == "text":
            # Print first 1000 characters to keep output manageable
            text = content.text
            if len(text) > 1000:
                print(text[:1000] + "\n\n[... Output truncated for brevity ...]")
            else:
                print(text)

    print(
        "\n✅ The skill now recognizes 'healthcare' as an industry and applies specific benchmarks!"
    )
else:
    print("⚠️ Please run the previous cells to create the enhanced version first")

Cleanup: Managing Your Skills

When you’re done testing or need to clean up your workspace, you can selectively remove skills. Let’s review what we’ve created and provide options for cleanup:

# Comprehensive skill cleanup with detailed reporting
def review_and_cleanup_skills(client, dry_run=True):
    """
    Review all skills and optionally clean up the ones created in this notebook.

    Args:
        client: Anthropic client
        dry_run: If True, only show what would be deleted without actually deleting
    """
    # Get all current skills
    all_skills = list_custom_skills(client)

    # Skills we created in this notebook
    notebook_skill_names = [
        "Financial Ratio Analyzer",
        "Corporate Brand Guidelines",
        "Financial Modeling Suite",
    ]

    # Track skills created by this notebook
    notebook_skills = []
    other_skills = []

    for skill in all_skills:
        if skill["display_title"] in notebook_skill_names:
            notebook_skills.append(skill)
        else:
            other_skills.append(skill)

    print("=" * 70)
    print("SKILL INVENTORY REPORT")
    print("=" * 70)

    print(f"\nTotal custom skills in workspace: {len(all_skills)}")

    if notebook_skills:
        print(f"\n📚 Skills created by this notebook ({len(notebook_skills)}):")
        for skill in notebook_skills:
            print(f"   • {skill['display_title']}")
            print(f"     ID: {skill['skill_id']}")
            print(f"     Version: {skill['latest_version']}")
            print(f"     Created: {skill['created_at']}")
    else:
        print("\n✅ No skills from this notebook found")

    if other_skills:
        print(f"\n🔧 Other skills in workspace ({len(other_skills)}):")
        for skill in other_skills:
            print(f"   • {skill['display_title']} (v{skill['latest_version']})")

    # Cleanup options
    if notebook_skills:
        print("\n" + "=" * 70)
        print("CLEANUP OPTIONS")
        print("=" * 70)

        if dry_run:
            print("\n🔍 DRY RUN MODE - No skills will be deleted")
            print("\nTo delete the notebook skills, uncomment and run:")
            print("-" * 40)
            print("# review_and_cleanup_skills(client, dry_run=False)")
            print("-" * 40)

            print("\nThis would delete:")
            for skill in notebook_skills:
                print(f"   • {skill['display_title']}")
        else:
            print("\n⚠️ DELETION MODE - Skills will be permanently removed")
            print("\nDeleting notebook skills...")

            success_count = 0
            for skill in notebook_skills:
                if delete_skill(client, skill["skill_id"]):
                    print(f"   ✅ Deleted: {skill['display_title']}")
                    success_count += 1
                else:
                    print(f"   ❌ Failed to delete: {skill['display_title']}")

            print(f"\n📊 Cleanup complete: {success_count}/{len(notebook_skills)} skills deleted")

    return {
        "total_skills": len(all_skills),
        "notebook_skills": len(notebook_skills),
        "other_skills": len(other_skills),
        "notebook_skill_ids": [s["skill_id"] for s in notebook_skills],
    }


# Run the review (in dry-run mode by default)
print("Reviewing your custom skills workspace...")
cleanup_summary = review_and_cleanup_skills(client, dry_run=True)

# Store skill IDs for potential cleanup
if cleanup_summary["notebook_skill_ids"]:
    skills_to_cleanup = cleanup_summary["notebook_skill_ids"]
    print(f"\n💡 Tip: {len(skills_to_cleanup)} skill(s) can be cleaned up when you're done testing")

# UNCOMMENT THE LINE BELOW TO ACTUALLY DELETE THE NOTEBOOK SKILLS:
# review_and_cleanup_skills(client, dry_run=False)

7. Best Practices & Production Tips {#best-practices}### Skill Design Principles1. Single Responsibility: Each skill should focus on one area of expertise2. Clear Documentation: SKILL.md should be comprehensive yet concise3. Error Handling: Scripts should handle edge cases gracefully4. Version Control: Use Git to track skill changes5. Testing: Always test skills before production deployment### Directory Structure Best Practicescustom_skills/├── financial_analyzer/ # Single purpose, clear naming│ ├── SKILL.md # Under 5,000 tokens│ ├── scripts/ # Modular Python/JS files│ └── tests/ # Unit tests for scripts├── brand_guidelines/ # Organizational standards│ ├── SKILL.md│ ├── REFERENCE.md # Additional documentation│ └── assets/ # Logos, templates### Performance Optimization| Strategy | Impact | Implementation ||———-|——–|—————-|| Minimal Frontmatter | Faster skill discovery | name: 64 chars, description: 1024 chars || Lazy Loading | Reduced token usage | Reference files only when needed || Skill Composition | Avoid duplication | Combine skills vs. mega-skill || Caching | Faster responses | Reuse skill containers |### Security Considerations- API Keys: Never hardcode credentials in skills- Data Privacy: Don’t include sensitive data in skill files- Access Control: Skills are workspace-specific- Validation: Sanitize inputs in scripts- Audit Trail: Log skill usage for compliance

Next Steps🎉 Congratulations! You’ve learned how to create, deploy, and manage custom skills for Claude.### What You’ve Learned- ✅ Custom skill architecture and requirements- ✅ Creating skills with SKILL.md and Python scripts- ✅ Uploading skills via the API- ✅ Combining custom and Anthropic skills- ✅ Best practices for production deployment- ✅ Troubleshooting common issues### Continue Your Journey1. Experiment: Modify the example skills for your use cases2. Build: Create skills for your organization’s workflows3. Optimize: Monitor token usage and performance4. Share: Document your skills for team collaboration### Resources- Claude API Documentation- Skills Documentation- Best Practices- Files API Documentation- Example Skills Repository (coming soon)### Skill Ideas to Try- 📊 Data Pipeline: ETL workflows with validation- 📝 Document Templates: Contracts, proposals, reports- 🔍 Code Review: Style guides and best practices- 📈 Analytics Dashboard: KPI tracking and visualization- 🤖 Automation Suite: Repetitive task workflowsHappy skill building! 🚀