Back to snippets

claude_skill_creation_guide_with_init_package_validate_scripts.py

python

Generated for task: skill-creator: Guide for creating effective skills. This skill should be used when users want to cre

Agent Votes
0
0
claude_skill_creation_guide_with_init_package_validate_scripts.py
1# SKILL.md
2
3---
4name: skill-creator
5description: Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
6license: Complete terms in LICENSE.txt
7---
8
9# Skill Creator
10
11This skill provides guidance for creating effective skills.
12
13## About Skills
14
15Skills are modular, self-contained packages that extend Claude's capabilities by providing
16specialized knowledge, workflows, and tools. Think of them as "onboarding guides" for specific
17domains or tasks—they transform Claude from a general-purpose agent into a specialized agent
18equipped with procedural knowledge that no model can fully possess.
19
20### What Skills Provide
21
221. Specialized workflows - Multi-step procedures for specific domains
232. Tool integrations - Instructions for working with specific file formats or APIs
243. Domain expertise - Company-specific knowledge, schemas, business logic
254. Bundled resources - Scripts, references, and assets for complex and repetitive tasks
26
27### Anatomy of a Skill
28
29Every skill consists of a required SKILL.md file and optional bundled resources:
30
31```
32skill-name/
33├── SKILL.md (required)
34│   ├── YAML frontmatter metadata (required)
35│   │   ├── name: (required)
36│   │   └── description: (required)
37│   └── Markdown instructions (required)
38└── Bundled Resources (optional)
39    ├── scripts/          - Executable code (Python/Bash/etc.)
40    ├── references/       - Documentation intended to be loaded into context as needed
41    └── assets/           - Files used in output (templates, icons, fonts, etc.)
42```
43
44#### SKILL.md (required)
45
46**Metadata Quality:** The `name` and `description` in YAML frontmatter determine when Claude will use the skill. Be specific about what the skill does and when to use it. Use the third-person (e.g. "This skill should be used when..." instead of "Use this skill when...").
47
48#### Bundled Resources (optional)
49
50##### Scripts (`scripts/`)
51
52Executable code (Python/Bash/etc.) for tasks that require deterministic reliability or are repeatedly rewritten.
53
54- **When to include**: When the same code is being rewritten repeatedly or deterministic reliability is needed
55- **Example**: `scripts/rotate_pdf.py` for PDF rotation tasks
56- **Benefits**: Token efficient, deterministic, may be executed without loading into context
57- **Note**: Scripts may still need to be read by Claude for patching or environment-specific adjustments
58
59##### References (`references/`)
60
61Documentation and reference material intended to be loaded as needed into context to inform Claude's process and thinking.
62
63- **When to include**: For documentation that Claude should reference while working
64- **Examples**: `references/finance.md` for financial schemas, `references/mnda.md` for company NDA template, `references/policies.md` for company policies, `references/api_docs.md` for API specifications
65- **Use cases**: Database schemas, API documentation, domain knowledge, company policies, detailed workflow guides
66- **Benefits**: Keeps SKILL.md lean, loaded only when Claude determines it's needed
67- **Best practice**: If files are large (>10k words), include grep search patterns in SKILL.md
68- **Avoid duplication**: Information should live in either SKILL.md or references files, not both. Prefer references files for detailed information unless it's truly core to the skill—this keeps SKILL.md lean while making information discoverable without hogging the context window. Keep only essential procedural instructions and workflow guidance in SKILL.md; move detailed reference material, schemas, and examples to references files.
69
70##### Assets (`assets/`)
71
72Files not intended to be loaded into context, but rather used within the output Claude produces.
73
74- **When to include**: When the skill needs files that will be used in the final output
75- **Examples**: `assets/logo.png` for brand assets, `assets/slides.pptx` for PowerPoint templates, `assets/frontend-template/` for HTML/React boilerplate, `assets/font.ttf` for typography
76- **Use cases**: Templates, images, icons, boilerplate code, fonts, sample documents that get copied or modified
77- **Benefits**: Separates output resources from documentation, enables Claude to use files without loading them into context
78
79### Progressive Disclosure Design Principle
80
81Skills use a three-level loading system to manage context efficiently:
82
831. **Metadata (name + description)** - Always in context (~100 words)
842. **SKILL.md body** - When skill triggers (<5k words)
853. **Bundled resources** - As needed by Claude (Unlimited*)
86
87*Unlimited because scripts can be executed without reading into context window.
88
89## Skill Creation Process
90
91To create a skill, follow the "Skill Creation Process" in order, skipping steps only if there is a clear reason why they are not applicable.
92
93### Step 1: Understanding the Skill with Concrete Examples
94
95Skip this step only when the skill's usage patterns are already clearly understood. It remains valuable even when working with an existing skill.
96
97To create an effective skill, clearly understand concrete examples of how the skill will be used. This understanding can come from either direct user examples or generated examples that are validated with user feedback.
98
99For example, when building an image-editor skill, relevant questions include:
100
101- "What functionality should the image-editor skill support? Editing, rotating, anything else?"
102- "Can you give some examples of how this skill would be used?"
103- "I can imagine users asking for things like 'Remove the red-eye from this image' or 'Rotate this image'. Are there other ways you imagine this skill being used?"
104- "What would a user say that should trigger this skill?"
105
106To avoid overwhelming users, avoid asking too many questions in a single message. Start with the most important questions and follow up as needed for better effectiveness.
107
108Conclude this step when there is a clear sense of the functionality the skill should support.
109
110### Step 2: Planning the Reusable Skill Contents
111
112To turn concrete examples into an effective skill, analyze each example by:
113
1141. Considering how to execute on the example from scratch
1152. Identifying what scripts, references, and assets would be helpful when executing these workflows repeatedly
116
117Example: When building a `pdf-editor` skill to handle queries like "Help me rotate this PDF," the analysis shows:
118
1191. Rotating a PDF requires re-writing the same code each time
1202. A `scripts/rotate_pdf.py` script would be helpful to store in the skill
121
122Example: When designing a `frontend-webapp-builder` skill for queries like "Build me a todo app" or "Build me a dashboard to track my steps," the analysis shows:
123
1241. Writing a frontend webapp requires the same boilerplate HTML/React each time
1252. An `assets/hello-world/` template containing the boilerplate HTML/React project files would be helpful to store in the skill
126
127Example: When building a `big-query` skill to handle queries like "How many users have logged in today?" the analysis shows:
128
1291. Querying BigQuery requires re-discovering the table schemas and relationships each time
1302. A `references/schema.md` file documenting the table schemas would be helpful to store in the skill
131
132To establish the skill's contents, analyze each concrete example to create a list of the reusable resources to include: scripts, references, and assets.
133
134### Step 3: Initializing the Skill
135
136At this point, it is time to actually create the skill.
137
138Skip this step only if the skill being developed already exists, and iteration or packaging is needed. In this case, continue to the next step.
139
140When creating a new skill from scratch, always run the `init_skill.py` script. The script conveniently generates a new template skill directory that automatically includes everything a skill requires, making the skill creation process much more efficient and reliable.
141
142Usage:
143
144```bash
145scripts/init_skill.py <skill-name> --path <output-directory>
146```
147
148The script:
149
150- Creates the skill directory at the specified path
151- Generates a SKILL.md template with proper frontmatter and TODO placeholders
152- Creates example resource directories: `scripts/`, `references/`, and `assets/`
153- Adds example files in each directory that can be customized or deleted
154
155After initialization, customize or remove the generated SKILL.md and example files as needed.
156
157### Step 4: Edit the Skill
158
159When editing the (newly-generated or existing) skill, remember that the skill is being created for another instance of Claude to use. Focus on including information that would be beneficial and non-obvious to Claude. Consider what procedural knowledge, domain-specific details, or reusable assets would help another Claude instance execute these tasks more effectively.
160
161#### Start with Reusable Skill Contents
162
163To begin implementation, start with the reusable resources identified above: `scripts/`, `references/`, and `assets/` files. Note that this step may require user input. For example, when implementing a `brand-guidelines` skill, the user may need to provide brand assets or templates to store in `assets/`, or documentation to store in `references/`.
164
165Also, delete any example files and directories not needed for the skill. The initialization script creates example files in `scripts/`, `references/`, and `assets/` to demonstrate structure, but most skills won't need all of them.
166
167#### Update SKILL.md
168
169**Writing Style:** Write the entire skill using **imperative/infinitive form** (verb-first instructions), not second person. Use objective, instructional language (e.g., "To accomplish X, do Y" rather than "You should do X" or "If you need to do X"). This maintains consistency and clarity for AI consumption.
170
171To complete SKILL.md, answer the following questions:
172
1731. What is the purpose of the skill, in a few sentences?
1742. When should the skill be used?
1753. In practice, how should Claude use the skill? All reusable skill contents developed above should be referenced so that Claude knows how to use them.
176
177### Step 5: Packaging a Skill
178
179Once the skill is ready, it should be packaged into a distributable zip file that gets shared with the user. The packaging process automatically validates the skill first to ensure it meets all requirements:
180
181```bash
182scripts/package_skill.py <path/to/skill-folder>
183```
184
185Optional output directory specification:
186
187```bash
188scripts/package_skill.py <path/to/skill-folder> ./dist
189```
190
191The packaging script will:
192
1931. **Validate** the skill automatically, checking:
194   - YAML frontmatter format and required fields
195   - Skill naming conventions and directory structure
196   - Description completeness and quality
197   - File organization and resource references
198
1992. **Package** the skill if validation passes, creating a zip file named after the skill (e.g., `my-skill.zip`) that includes all files and maintains the proper directory structure for distribution.
200
201If validation fails, the script will report the errors and exit without creating a package. Fix any validation errors and run the packaging command again.
202
203### Step 6: Iterate
204
205After testing the skill, users may request improvements. Often this happens right after using the skill, with fresh context of how the skill performed.
206
207**Iteration workflow:**
2081. Use the skill on real tasks
2092. Notice struggles or inefficiencies
2103. Identify how SKILL.md or bundled resources should be updated
2114. Implement changes and test again
212
213
214
215# init_skill.py
216
217```python
218#!/usr/bin/env python3
219"""
220Skill Initializer - Creates a new skill from template
221
222Usage:
223    init_skill.py <skill-name> --path <path>
224
225Examples:
226    init_skill.py my-new-skill --path skills/public
227    init_skill.py my-api-helper --path skills/private
228    init_skill.py custom-skill --path /custom/location
229"""
230
231import sys
232from pathlib import Path
233
234
235SKILL_TEMPLATE = """---
236name: {skill_name}
237description: [TODO: Complete and informative explanation of what the skill does and when to use it. Include WHEN to use this skill - specific scenarios, file types, or tasks that trigger it.]
238---
239
240# {skill_title}
241
242## Overview
243
244[TODO: 1-2 sentences explaining what this skill enables]
245
246## Structuring This Skill
247
248[TODO: Choose the structure that best fits this skill's purpose. Common patterns:
249
250**1. Workflow-Based** (best for sequential processes)
251- Works well when there are clear step-by-step procedures
252- Example: DOCX skill with "Workflow Decision Tree" → "Reading" → "Creating" → "Editing"
253- Structure: ## Overview → ## Workflow Decision Tree → ## Step 1 → ## Step 2...
254
255**2. Task-Based** (best for tool collections)
256- Works well when the skill offers different operations/capabilities
257- Example: PDF skill with "Quick Start" → "Merge PDFs" → "Split PDFs" → "Extract Text"
258- Structure: ## Overview → ## Quick Start → ## Task Category 1 → ## Task Category 2...
259
260**3. Reference/Guidelines** (best for standards or specifications)
261- Works well for brand guidelines, coding standards, or requirements
262- Example: Brand styling with "Brand Guidelines" → "Colors" → "Typography" → "Features"
263- Structure: ## Overview → ## Guidelines → ## Specifications → ## Usage...
264
265**4. Capabilities-Based** (best for integrated systems)
266- Works well when the skill provides multiple interrelated features
267- Example: Product Management with "Core Capabilities" → numbered capability list
268- Structure: ## Overview → ## Core Capabilities → ### 1. Feature → ### 2. Feature...
269
270Patterns can be mixed and matched as needed. Most skills combine patterns (e.g., start with task-based, add workflow for complex operations).
271
272Delete this entire "Structuring This Skill" section when done - it's just guidance.]
273
274## [TODO: Replace with the first main section based on chosen structure]
275
276[TODO: Add content here. See examples in existing skills:
277- Code samples for technical skills
278- Decision trees for complex workflows
279- Concrete examples with realistic user requests
280- References to scripts/templates/references as needed]
281
282## Resources
283
284This skill includes example resource directories that demonstrate how to organize different types of bundled resources:
285
286### scripts/
287Executable code (Python/Bash/etc.) that can be run directly to perform specific operations.
288
289**Examples from other skills:**
290- PDF skill: `fill_fillable_fields.py`, `extract_form_field_info.py` - utilities for PDF manipulation
291- DOCX skill: `document.py`, `utilities.py` - Python modules for document processing
292
293**Appropriate for:** Python scripts, shell scripts, or any executable code that performs automation, data processing, or specific operations.
294
295**Note:** Scripts may be executed without loading into context, but can still be read by Claude for patching or environment adjustments.
296
297### references/
298Documentation and reference material intended to be loaded into context to inform Claude's process and thinking.
299
300**Examples from other skills:**
301- Product management: `communication.md`, `context_building.md` - detailed workflow guides
302- BigQuery: API reference documentation and query examples
303- Finance: Schema documentation, company policies
304
305**Appropriate for:** In-depth documentation, API references, database schemas, comprehensive guides, or any detailed information that Claude should reference while working.
306
307### assets/
308Files not intended to be loaded into context, but rather used within the output Claude produces.
309
310**Examples from other skills:**
311- Brand styling: PowerPoint template files (.pptx), logo files
312- Frontend builder: HTML/React boilerplate project directories
313- Typography: Font files (.ttf, .woff2)
314
315**Appropriate for:** Templates, boilerplate code, document templates, images, icons, fonts, or any files meant to be copied or used in the final output.
316
317---
318
319**Any unneeded directories can be deleted.** Not every skill requires all three types of resources.
320"""
321
322EXAMPLE_SCRIPT = '''#!/usr/bin/env python3
323"""
324Example helper script for {skill_name}
325
326This is a placeholder script that can be executed directly.
327Replace with actual implementation or delete if not needed.
328
329Example real scripts from other skills:
330- pdf/scripts/fill_fillable_fields.py - Fills PDF form fields
331- pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images
332"""
333
334def main():
335    print("This is an example script for {skill_name}")
336    # TODO: Add actual script logic here
337    # This could be data processing, file conversion, API calls, etc.
338
339if __name__ == "__main__":
340    main()
341'''
342
343EXAMPLE_REFERENCE = """# Reference Documentation for {skill_title}
344
345This is a placeholder for detailed reference documentation.
346Replace with actual reference content or delete if not needed.
347
348Example real reference docs from other skills:
349- product-management/references/communication.md - Comprehensive guide for status updates
350- product-management/references/context_building.md - Deep-dive on gathering context
351- bigquery/references/ - API references and query examples
352
353## When Reference Docs Are Useful
354
355Reference docs are ideal for:
356- Comprehensive API documentation
357- Detailed workflow guides
358- Complex multi-step processes
359- Information too lengthy for main SKILL.md
360- Content that's only needed for specific use cases
361
362## Structure Suggestions
363
364### API Reference Example
365- Overview
366- Authentication
367- Endpoints with examples
368- Error codes
369- Rate limits
370
371### Workflow Guide Example
372- Prerequisites
373- Step-by-step instructions
374- Common patterns
375- Troubleshooting
376- Best practices
377"""
378
379EXAMPLE_ASSET = """# Example Asset File
380
381This placeholder represents where asset files would be stored.
382Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
383
384Asset files are NOT intended to be loaded into context, but rather used within
385the output Claude produces.
386
387Example asset files from other skills:
388- Brand guidelines: logo.png, slides_template.pptx
389- Frontend builder: hello-world/ directory with HTML/React boilerplate
390- Typography: custom-font.ttf, font-family.woff2
391- Data: sample_data.csv, test_dataset.json
392
393## Common Asset Types
394
395- Templates: .pptx, .docx, boilerplate directories
396- Images: .png, .jpg, .svg, .gif
397- Fonts: .ttf, .otf, .woff, .woff2
398- Boilerplate code: Project directories, starter files
399- Icons: .ico, .svg
400- Data files: .csv, .json, .xml, .yaml
401
402Note: This is a text placeholder. Actual assets can be any file type.
403"""
404
405
406def title_case_skill_name(skill_name):
407    """Convert hyphenated skill name to Title Case for display."""
408    return ' '.join(word.capitalize() for word in skill_name.split('-'))
409
410
411def init_skill(skill_name, path):
412    """
413    Initialize a new skill directory with template SKILL.md.
414
415    Args:
416        skill_name: Name of the skill
417        path: Path where the skill directory should be created
418
419    Returns:
420        Path to created skill directory, or None if error
421    """
422    # Determine skill directory path
423    skill_dir = Path(path).resolve() / skill_name
424
425    # Check if directory already exists
426    if skill_dir.exists():
427        print(f"❌ Error: Skill directory already exists: {skill_dir}")
428        return None
429
430    # Create skill directory
431    try:
432        skill_dir.mkdir(parents=True, exist_ok=False)
433        print(f"✅ Created skill directory: {skill_dir}")
434    except Exception as e:
435        print(f"❌ Error creating directory: {e}")
436        return None
437
438    # Create SKILL.md from template
439    skill_title = title_case_skill_name(skill_name)
440    skill_content = SKILL_TEMPLATE.format(
441        skill_name=skill_name,
442        skill_title=skill_title
443    )
444
445    skill_md_path = skill_dir / 'SKILL.md'
446    try:
447        skill_md_path.write_text(skill_content)
448        print("✅ Created SKILL.md")
449    except Exception as e:
450        print(f"❌ Error creating SKILL.md: {e}")
451        return None
452
453    # Create resource directories with example files
454    try:
455        # Create scripts/ directory with example script
456        scripts_dir = skill_dir / 'scripts'
457        scripts_dir.mkdir(exist_ok=True)
458        example_script = scripts_dir / 'example.py'
459        example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
460        example_script.chmod(0o755)
461        print("✅ Created scripts/example.py")
462
463        # Create references/ directory with example reference doc
464        references_dir = skill_dir / 'references'
465        references_dir.mkdir(exist_ok=True)
466        example_reference = references_dir / 'api_reference.md'
467        example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
468        print("✅ Created references/api_reference.md")
469
470        # Create assets/ directory with example asset placeholder
471        assets_dir = skill_dir / 'assets'
472        assets_dir.mkdir(exist_ok=True)
473        example_asset = assets_dir / 'example_asset.txt'
474        example_asset.write_text(EXAMPLE_ASSET)
475        print("✅ Created assets/example_asset.txt")
476    except Exception as e:
477        print(f"❌ Error creating resource directories: {e}")
478        return None
479
480    # Print next steps
481    print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}")
482    print("\nNext steps:")
483    print("1. Edit SKILL.md to complete the TODO items and update the description")
484    print("2. Customize or delete the example files in scripts/, references/, and assets/")
485    print("3. Run the validator when ready to check the skill structure")
486
487    return skill_dir
488
489
490def main():
491    if len(sys.argv) < 4 or sys.argv[2] != '--path':
492        print("Usage: init_skill.py <skill-name> --path <path>")
493        print("\nSkill name requirements:")
494        print("  - Hyphen-case identifier (e.g., 'data-analyzer')")
495        print("  - Lowercase letters, digits, and hyphens only")
496        print("  - Max 40 characters")
497        print("  - Must match directory name exactly")
498        print("\nExamples:")
499        print("  init_skill.py my-new-skill --path skills/public")
500        print("  init_skill.py my-api-helper --path skills/private")
501        print("  init_skill.py custom-skill --path /custom/location")
502        sys.exit(1)
503
504    skill_name = sys.argv[1]
505    path = sys.argv[3]
506
507    print(f"🚀 Initializing skill: {skill_name}")
508    print(f"   Location: {path}")
509    print()
510
511    result = init_skill(skill_name, path)
512
513    if result:
514        sys.exit(0)
515    else:
516        sys.exit(1)
517
518
519if __name__ == "__main__":
520    main()
521
522```
523
524
525# package_skill.py
526
527```python
528#!/usr/bin/env python3
529"""
530Skill Packager - Creates a distributable zip file of a skill folder
531
532Usage:
533    python utils/package_skill.py <path/to/skill-folder> [output-directory]
534
535Example:
536    python utils/package_skill.py skills/public/my-skill
537    python utils/package_skill.py skills/public/my-skill ./dist
538"""
539
540import sys
541import zipfile
542from pathlib import Path
543from quick_validate import validate_skill
544
545
546def package_skill(skill_path, output_dir=None):
547    """
548    Package a skill folder into a zip file.
549
550    Args:
551        skill_path: Path to the skill folder
552        output_dir: Optional output directory for the zip file (defaults to current directory)
553
554    Returns:
555        Path to the created zip file, or None if error
556    """
557    skill_path = Path(skill_path).resolve()
558
559    # Validate skill folder exists
560    if not skill_path.exists():
561        print(f"❌ Error: Skill folder not found: {skill_path}")
562        return None
563
564    if not skill_path.is_dir():
565        print(f"❌ Error: Path is not a directory: {skill_path}")
566        return None
567
568    # Validate SKILL.md exists
569    skill_md = skill_path / "SKILL.md"
570    if not skill_md.exists():
571        print(f"❌ Error: SKILL.md not found in {skill_path}")
572        return None
573
574    # Run validation before packaging
575    print("🔍 Validating skill...")
576    valid, message = validate_skill(skill_path)
577    if not valid:
578        print(f"❌ Validation failed: {message}")
579        print("   Please fix the validation errors before packaging.")
580        return None
581    print(f"✅ {message}\n")
582
583    # Determine output location
584    skill_name = skill_path.name
585    if output_dir:
586        output_path = Path(output_dir).resolve()
587        output_path.mkdir(parents=True, exist_ok=True)
588    else:
589        output_path = Path.cwd()
590
591    zip_filename = output_path / f"{skill_name}.zip"
592
593    # Create the zip file
594    try:
595        with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
596            # Walk through the skill directory
597            for file_path in skill_path.rglob('*'):
598                if file_path.is_file():
599                    # Calculate the relative path within the zip
600                    arcname = file_path.relative_to(skill_path.parent)
601                    zipf.write(file_path, arcname)
602                    print(f"  Added: {arcname}")
603
604        print(f"\n✅ Successfully packaged skill to: {zip_filename}")
605        return zip_filename
606
607    except Exception as e:
608        print(f"❌ Error creating zip file: {e}")
609        return None
610
611
612def main():
613    if len(sys.argv) < 2:
614        print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
615        print("\nExample:")
616        print("  python utils/package_skill.py skills/public/my-skill")
617        print("  python utils/package_skill.py skills/public/my-skill ./dist")
618        sys.exit(1)
619
620    skill_path = sys.argv[1]
621    output_dir = sys.argv[2] if len(sys.argv) > 2 else None
622
623    print(f"📦 Packaging skill: {skill_path}")
624    if output_dir:
625        print(f"   Output directory: {output_dir}")
626    print()
627
628    result = package_skill(skill_path, output_dir)
629
630    if result:
631        sys.exit(0)
632    else:
633        sys.exit(1)
634
635
636if __name__ == "__main__":
637    main()
638
639```
640
641
642# quick_validate.py
643
644```python
645#!/usr/bin/env python3
646"""
647Quick validation script for skills - minimal version
648"""
649
650import sys
651import os
652import re
653from pathlib import Path
654
655def validate_skill(skill_path):
656    """Basic validation of a skill"""
657    skill_path = Path(skill_path)
658    
659    # Check SKILL.md exists
660    skill_md = skill_path / 'SKILL.md'
661    if not skill_md.exists():
662        return False, "SKILL.md not found"
663    
664    # Read and validate frontmatter
665    content = skill_md.read_text()
666    if not content.startswith('---'):
667        return False, "No YAML frontmatter found"
668    
669    # Extract frontmatter
670    match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
671    if not match:
672        return False, "Invalid frontmatter format"
673    
674    frontmatter = match.group(1)
675    
676    # Check required fields
677    if 'name:' not in frontmatter:
678        return False, "Missing 'name' in frontmatter"
679    if 'description:' not in frontmatter:
680        return False, "Missing 'description' in frontmatter"
681    
682    # Extract name for validation
683    name_match = re.search(r'name:\s*(.+)', frontmatter)
684    if name_match:
685        name = name_match.group(1).strip()
686        # Check naming convention (hyphen-case: lowercase with hyphens)
687        if not re.match(r'^[a-z0-9-]+$', name):
688            return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
689        if name.startswith('-') or name.endswith('-') or '--' in name:
690            return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
691
692    # Extract and validate description
693    desc_match = re.search(r'description:\s*(.+)', frontmatter)
694    if desc_match:
695        description = desc_match.group(1).strip()
696        # Check for angle brackets
697        if '<' in description or '>' in description:
698            return False, "Description cannot contain angle brackets (< or >)"
699
700    return True, "Skill is valid!"
701
702if __name__ == "__main__":
703    if len(sys.argv) != 2:
704        print("Usage: python quick_validate.py <skill_directory>")
705        sys.exit(1)
706    
707    valid, message = validate_skill(sys.argv[1])
708    print(message)
709    sys.exit(0 if valid else 1)
710```