Back to snippets

claude_skill_creation_guide_with_init_validate_package_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_validate_package_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## Core Principles
28
29### Concise is Key
30
31The context window is a public good. Skills share the context window with everything else Claude needs: system prompt, conversation history, other Skills' metadata, and the actual user request.
32
33**Default assumption: Claude is already very smart.** Only add context Claude doesn't already have. Challenge each piece of information: "Does Claude really need this explanation?" and "Does this paragraph justify its token cost?"
34
35Prefer concise examples over verbose explanations.
36
37### Set Appropriate Degrees of Freedom
38
39Match the level of specificity to the task's fragility and variability:
40
41**High freedom (text-based instructions)**: Use when multiple approaches are valid, decisions depend on context, or heuristics guide the approach.
42
43**Medium freedom (pseudocode or scripts with parameters)**: Use when a preferred pattern exists, some variation is acceptable, or configuration affects behavior.
44
45**Low freedom (specific scripts, few parameters)**: Use when operations are fragile and error-prone, consistency is critical, or a specific sequence must be followed.
46
47Think of Claude as exploring a path: a narrow bridge with cliffs needs specific guardrails (low freedom), while an open field allows many routes (high freedom).
48
49### Anatomy of a Skill
50
51Every skill consists of a required SKILL.md file and optional bundled resources:
52
53```
54skill-name/
55├── SKILL.md (required)
56│   ├── YAML frontmatter metadata (required)
57│   │   ├── name: (required)
58│   │   └── description: (required)
59│   └── Markdown instructions (required)
60└── Bundled Resources (optional)
61    ├── scripts/          - Executable code (Python/Bash/etc.)
62    ├── references/       - Documentation intended to be loaded into context as needed
63    └── assets/           - Files used in output (templates, icons, fonts, etc.)
64```
65
66#### SKILL.md (required)
67
68Every SKILL.md consists of:
69
70- **Frontmatter** (YAML): Contains `name` and `description` fields. These are the only fields that Claude reads to determine when the skill gets used, thus it is very important to be clear and comprehensive in describing what the skill is, and when it should be used.
71- **Body** (Markdown): Instructions and guidance for using the skill. Only loaded AFTER the skill triggers (if at all).
72
73#### Bundled Resources (optional)
74
75##### Scripts (`scripts/`)
76
77Executable code (Python/Bash/etc.) for tasks that require deterministic reliability or are repeatedly rewritten.
78
79- **When to include**: When the same code is being rewritten repeatedly or deterministic reliability is needed
80- **Example**: `scripts/rotate_pdf.py` for PDF rotation tasks
81- **Benefits**: Token efficient, deterministic, may be executed without loading into context
82- **Note**: Scripts may still need to be read by Claude for patching or environment-specific adjustments
83
84##### References (`references/`)
85
86Documentation and reference material intended to be loaded as needed into context to inform Claude's process and thinking.
87
88- **When to include**: For documentation that Claude should reference while working
89- **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
90- **Use cases**: Database schemas, API documentation, domain knowledge, company policies, detailed workflow guides
91- **Benefits**: Keeps SKILL.md lean, loaded only when Claude determines it's needed
92- **Best practice**: If files are large (>10k words), include grep search patterns in SKILL.md
93- **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.
94
95##### Assets (`assets/`)
96
97Files not intended to be loaded into context, but rather used within the output Claude produces.
98
99- **When to include**: When the skill needs files that will be used in the final output
100- **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
101- **Use cases**: Templates, images, icons, boilerplate code, fonts, sample documents that get copied or modified
102- **Benefits**: Separates output resources from documentation, enables Claude to use files without loading them into context
103
104#### What to Not Include in a Skill
105
106A skill should only contain essential files that directly support its functionality. Do NOT create extraneous documentation or auxiliary files, including:
107
108- README.md
109- INSTALLATION_GUIDE.md
110- QUICK_REFERENCE.md
111- CHANGELOG.md
112- etc.
113
114The skill should only contain the information needed for an AI agent to do the job at hand. It should not contain auxilary context about the process that went into creating it, setup and testing procedures, user-facing documentation, etc. Creating additional documentation files just adds clutter and confusion.
115
116### Progressive Disclosure Design Principle
117
118Skills use a three-level loading system to manage context efficiently:
119
1201. **Metadata (name + description)** - Always in context (~100 words)
1212. **SKILL.md body** - When skill triggers (<5k words)
1223. **Bundled resources** - As needed by Claude (Unlimited because scripts can be executed without reading into context window)
123
124#### Progressive Disclosure Patterns
125
126Keep SKILL.md body to the essentials and under 500 lines to minimize context bloat. Split content into separate files when approaching this limit. When splitting out content into other files, it is very important to reference them from SKILL.md and describe clearly when to read them, to ensure the reader of the skill knows they exist and when to use them.
127
128**Key principle:** When a skill supports multiple variations, frameworks, or options, keep only the core workflow and selection guidance in SKILL.md. Move variant-specific details (patterns, examples, configuration) into separate reference files.
129
130**Pattern 1: High-level guide with references**
131
132```markdown
133# PDF Processing
134
135## Quick start
136
137Extract text with pdfplumber:
138[code example]
139
140## Advanced features
141
142- **Form filling**: See [FORMS.md](FORMS.md) for complete guide
143- **API reference**: See [REFERENCE.md](REFERENCE.md) for all methods
144- **Examples**: See [EXAMPLES.md](EXAMPLES.md) for common patterns
145```
146
147Claude loads FORMS.md, REFERENCE.md, or EXAMPLES.md only when needed.
148
149**Pattern 2: Domain-specific organization**
150
151For Skills with multiple domains, organize content by domain to avoid loading irrelevant context:
152
153```
154bigquery-skill/
155├── SKILL.md (overview and navigation)
156└── reference/
157    ├── finance.md (revenue, billing metrics)
158    ├── sales.md (opportunities, pipeline)
159    ├── product.md (API usage, features)
160    └── marketing.md (campaigns, attribution)
161```
162
163When a user asks about sales metrics, Claude only reads sales.md.
164
165Similarly, for skills supporting multiple frameworks or variants, organize by variant:
166
167```
168cloud-deploy/
169├── SKILL.md (workflow + provider selection)
170└── references/
171    ├── aws.md (AWS deployment patterns)
172    ├── gcp.md (GCP deployment patterns)
173    └── azure.md (Azure deployment patterns)
174```
175
176When the user chooses AWS, Claude only reads aws.md.
177
178**Pattern 3: Conditional details**
179
180Show basic content, link to advanced content:
181
182```markdown
183# DOCX Processing
184
185## Creating documents
186
187Use docx-js for new documents. See [DOCX-JS.md](DOCX-JS.md).
188
189## Editing documents
190
191For simple edits, modify the XML directly.
192
193**For tracked changes**: See [REDLINING.md](REDLINING.md)
194**For OOXML details**: See [OOXML.md](OOXML.md)
195```
196
197Claude reads REDLINING.md or OOXML.md only when the user needs those features.
198
199**Important guidelines:**
200
201- **Avoid deeply nested references** - Keep references one level deep from SKILL.md. All reference files should link directly from SKILL.md.
202- **Structure longer reference files** - For files longer than 100 lines, include a table of contents at the top so Claude can see the full scope when previewing.
203
204## Skill Creation Process
205
206Skill creation involves these steps:
207
2081. Understand the skill with concrete examples
2092. Plan reusable skill contents (scripts, references, assets)
2103. Initialize the skill (run init_skill.py)
2114. Edit the skill (implement resources and write SKILL.md)
2125. Package the skill (run package_skill.py)
2136. Iterate based on real usage
214
215Follow these steps in order, skipping only if there is a clear reason why they are not applicable.
216
217### Step 1: Understanding the Skill with Concrete Examples
218
219Skip this step only when the skill's usage patterns are already clearly understood. It remains valuable even when working with an existing skill.
220
221To 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.
222
223For example, when building an image-editor skill, relevant questions include:
224
225- "What functionality should the image-editor skill support? Editing, rotating, anything else?"
226- "Can you give some examples of how this skill would be used?"
227- "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?"
228- "What would a user say that should trigger this skill?"
229
230To 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.
231
232Conclude this step when there is a clear sense of the functionality the skill should support.
233
234### Step 2: Planning the Reusable Skill Contents
235
236To turn concrete examples into an effective skill, analyze each example by:
237
2381. Considering how to execute on the example from scratch
2392. Identifying what scripts, references, and assets would be helpful when executing these workflows repeatedly
240
241Example: When building a `pdf-editor` skill to handle queries like "Help me rotate this PDF," the analysis shows:
242
2431. Rotating a PDF requires re-writing the same code each time
2442. A `scripts/rotate_pdf.py` script would be helpful to store in the skill
245
246Example: 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:
247
2481. Writing a frontend webapp requires the same boilerplate HTML/React each time
2492. An `assets/hello-world/` template containing the boilerplate HTML/React project files would be helpful to store in the skill
250
251Example: When building a `big-query` skill to handle queries like "How many users have logged in today?" the analysis shows:
252
2531. Querying BigQuery requires re-discovering the table schemas and relationships each time
2542. A `references/schema.md` file documenting the table schemas would be helpful to store in the skill
255
256To establish the skill's contents, analyze each concrete example to create a list of the reusable resources to include: scripts, references, and assets.
257
258### Step 3: Initializing the Skill
259
260At this point, it is time to actually create the skill.
261
262Skip this step only if the skill being developed already exists, and iteration or packaging is needed. In this case, continue to the next step.
263
264When 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.
265
266Usage:
267
268```bash
269scripts/init_skill.py <skill-name> --path <output-directory>
270```
271
272The script:
273
274- Creates the skill directory at the specified path
275- Generates a SKILL.md template with proper frontmatter and TODO placeholders
276- Creates example resource directories: `scripts/`, `references/`, and `assets/`
277- Adds example files in each directory that can be customized or deleted
278
279After initialization, customize or remove the generated SKILL.md and example files as needed.
280
281### Step 4: Edit the Skill
282
283When editing the (newly-generated or existing) skill, remember that the skill is being created for another instance of Claude to use. Include 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.
284
285#### Learn Proven Design Patterns
286
287Consult these helpful guides based on your skill's needs:
288
289- **Multi-step processes**: See references/workflows.md for sequential workflows and conditional logic
290- **Specific output formats or quality standards**: See references/output-patterns.md for template and example patterns
291
292These files contain established best practices for effective skill design.
293
294#### Start with Reusable Skill Contents
295
296To 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/`.
297
298Added scripts must be tested by actually running them to ensure there are no bugs and that the output matches what is expected. If there are many similar scripts, only a representative sample needs to be tested to ensure confidence that they all work while balancing time to completion.
299
300Any example files and directories not needed for the skill should be deleted. The initialization script creates example files in `scripts/`, `references/`, and `assets/` to demonstrate structure, but most skills won't need all of them.
301
302#### Update SKILL.md
303
304**Writing Guidelines:** Always use imperative/infinitive form.
305
306##### Frontmatter
307
308Write the YAML frontmatter with `name` and `description`:
309
310- `name`: The skill name
311- `description`: This is the primary triggering mechanism for your skill, and helps Claude understand when to use the skill.
312  - Include both what the Skill does and specific triggers/contexts for when to use it.
313  - Include all "when to use" information here - Not in the body. The body is only loaded after triggering, so "When to Use This Skill" sections in the body are not helpful to Claude.
314  - Example description for a `docx` skill: "Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. Use when Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks"
315
316Do not include any other fields in YAML frontmatter.
317
318##### Body
319
320Write instructions for using the skill and its bundled resources.
321
322### Step 5: Packaging a Skill
323
324Once development of the skill is complete, it must be packaged into a distributable .skill file that gets shared with the user. The packaging process automatically validates the skill first to ensure it meets all requirements:
325
326```bash
327scripts/package_skill.py <path/to/skill-folder>
328```
329
330Optional output directory specification:
331
332```bash
333scripts/package_skill.py <path/to/skill-folder> ./dist
334```
335
336The packaging script will:
337
3381. **Validate** the skill automatically, checking:
339
340   - YAML frontmatter format and required fields
341   - Skill naming conventions and directory structure
342   - Description completeness and quality
343   - File organization and resource references
344
3452. **Package** the skill if validation passes, creating a .skill file named after the skill (e.g., `my-skill.skill`) that includes all files and maintains the proper directory structure for distribution. The .skill file is a zip file with a .skill extension.
346
347If validation fails, the script will report the errors and exit without creating a package. Fix any validation errors and run the packaging command again.
348
349### Step 6: Iterate
350
351After testing the skill, users may request improvements. Often this happens right after using the skill, with fresh context of how the skill performed.
352
353**Iteration workflow:**
354
3551. Use the skill on real tasks
3562. Notice struggles or inefficiencies
3573. Identify how SKILL.md or bundled resources should be updated
3584. Implement changes and test again
359
360
361
362# init_skill.py
363
364```python
365#!/usr/bin/env python3
366"""
367Skill Initializer - Creates a new skill from template
368
369Usage:
370    init_skill.py <skill-name> --path <path>
371
372Examples:
373    init_skill.py my-new-skill --path skills/public
374    init_skill.py my-api-helper --path skills/private
375    init_skill.py custom-skill --path /custom/location
376"""
377
378import sys
379from pathlib import Path
380
381
382SKILL_TEMPLATE = """---
383name: {skill_name}
384description: [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.]
385---
386
387# {skill_title}
388
389## Overview
390
391[TODO: 1-2 sentences explaining what this skill enables]
392
393## Structuring This Skill
394
395[TODO: Choose the structure that best fits this skill's purpose. Common patterns:
396
397**1. Workflow-Based** (best for sequential processes)
398- Works well when there are clear step-by-step procedures
399- Example: DOCX skill with "Workflow Decision Tree" → "Reading" → "Creating" → "Editing"
400- Structure: ## Overview → ## Workflow Decision Tree → ## Step 1 → ## Step 2...
401
402**2. Task-Based** (best for tool collections)
403- Works well when the skill offers different operations/capabilities
404- Example: PDF skill with "Quick Start" → "Merge PDFs" → "Split PDFs" → "Extract Text"
405- Structure: ## Overview → ## Quick Start → ## Task Category 1 → ## Task Category 2...
406
407**3. Reference/Guidelines** (best for standards or specifications)
408- Works well for brand guidelines, coding standards, or requirements
409- Example: Brand styling with "Brand Guidelines" → "Colors" → "Typography" → "Features"
410- Structure: ## Overview → ## Guidelines → ## Specifications → ## Usage...
411
412**4. Capabilities-Based** (best for integrated systems)
413- Works well when the skill provides multiple interrelated features
414- Example: Product Management with "Core Capabilities" → numbered capability list
415- Structure: ## Overview → ## Core Capabilities → ### 1. Feature → ### 2. Feature...
416
417Patterns can be mixed and matched as needed. Most skills combine patterns (e.g., start with task-based, add workflow for complex operations).
418
419Delete this entire "Structuring This Skill" section when done - it's just guidance.]
420
421## [TODO: Replace with the first main section based on chosen structure]
422
423[TODO: Add content here. See examples in existing skills:
424- Code samples for technical skills
425- Decision trees for complex workflows
426- Concrete examples with realistic user requests
427- References to scripts/templates/references as needed]
428
429## Resources
430
431This skill includes example resource directories that demonstrate how to organize different types of bundled resources:
432
433### scripts/
434Executable code (Python/Bash/etc.) that can be run directly to perform specific operations.
435
436**Examples from other skills:**
437- PDF skill: `fill_fillable_fields.py`, `extract_form_field_info.py` - utilities for PDF manipulation
438- DOCX skill: `document.py`, `utilities.py` - Python modules for document processing
439
440**Appropriate for:** Python scripts, shell scripts, or any executable code that performs automation, data processing, or specific operations.
441
442**Note:** Scripts may be executed without loading into context, but can still be read by Claude for patching or environment adjustments.
443
444### references/
445Documentation and reference material intended to be loaded into context to inform Claude's process and thinking.
446
447**Examples from other skills:**
448- Product management: `communication.md`, `context_building.md` - detailed workflow guides
449- BigQuery: API reference documentation and query examples
450- Finance: Schema documentation, company policies
451
452**Appropriate for:** In-depth documentation, API references, database schemas, comprehensive guides, or any detailed information that Claude should reference while working.
453
454### assets/
455Files not intended to be loaded into context, but rather used within the output Claude produces.
456
457**Examples from other skills:**
458- Brand styling: PowerPoint template files (.pptx), logo files
459- Frontend builder: HTML/React boilerplate project directories
460- Typography: Font files (.ttf, .woff2)
461
462**Appropriate for:** Templates, boilerplate code, document templates, images, icons, fonts, or any files meant to be copied or used in the final output.
463
464---
465
466**Any unneeded directories can be deleted.** Not every skill requires all three types of resources.
467"""
468
469EXAMPLE_SCRIPT = '''#!/usr/bin/env python3
470"""
471Example helper script for {skill_name}
472
473This is a placeholder script that can be executed directly.
474Replace with actual implementation or delete if not needed.
475
476Example real scripts from other skills:
477- pdf/scripts/fill_fillable_fields.py - Fills PDF form fields
478- pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images
479"""
480
481def main():
482    print("This is an example script for {skill_name}")
483    # TODO: Add actual script logic here
484    # This could be data processing, file conversion, API calls, etc.
485
486if __name__ == "__main__":
487    main()
488'''
489
490EXAMPLE_REFERENCE = """# Reference Documentation for {skill_title}
491
492This is a placeholder for detailed reference documentation.
493Replace with actual reference content or delete if not needed.
494
495Example real reference docs from other skills:
496- product-management/references/communication.md - Comprehensive guide for status updates
497- product-management/references/context_building.md - Deep-dive on gathering context
498- bigquery/references/ - API references and query examples
499
500## When Reference Docs Are Useful
501
502Reference docs are ideal for:
503- Comprehensive API documentation
504- Detailed workflow guides
505- Complex multi-step processes
506- Information too lengthy for main SKILL.md
507- Content that's only needed for specific use cases
508
509## Structure Suggestions
510
511### API Reference Example
512- Overview
513- Authentication
514- Endpoints with examples
515- Error codes
516- Rate limits
517
518### Workflow Guide Example
519- Prerequisites
520- Step-by-step instructions
521- Common patterns
522- Troubleshooting
523- Best practices
524"""
525
526EXAMPLE_ASSET = """# Example Asset File
527
528This placeholder represents where asset files would be stored.
529Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
530
531Asset files are NOT intended to be loaded into context, but rather used within
532the output Claude produces.
533
534Example asset files from other skills:
535- Brand guidelines: logo.png, slides_template.pptx
536- Frontend builder: hello-world/ directory with HTML/React boilerplate
537- Typography: custom-font.ttf, font-family.woff2
538- Data: sample_data.csv, test_dataset.json
539
540## Common Asset Types
541
542- Templates: .pptx, .docx, boilerplate directories
543- Images: .png, .jpg, .svg, .gif
544- Fonts: .ttf, .otf, .woff, .woff2
545- Boilerplate code: Project directories, starter files
546- Icons: .ico, .svg
547- Data files: .csv, .json, .xml, .yaml
548
549Note: This is a text placeholder. Actual assets can be any file type.
550"""
551
552
553def title_case_skill_name(skill_name):
554    """Convert hyphenated skill name to Title Case for display."""
555    return ' '.join(word.capitalize() for word in skill_name.split('-'))
556
557
558def init_skill(skill_name, path):
559    """
560    Initialize a new skill directory with template SKILL.md.
561
562    Args:
563        skill_name: Name of the skill
564        path: Path where the skill directory should be created
565
566    Returns:
567        Path to created skill directory, or None if error
568    """
569    # Determine skill directory path
570    skill_dir = Path(path).resolve() / skill_name
571
572    # Check if directory already exists
573    if skill_dir.exists():
574        print(f"❌ Error: Skill directory already exists: {skill_dir}")
575        return None
576
577    # Create skill directory
578    try:
579        skill_dir.mkdir(parents=True, exist_ok=False)
580        print(f"✅ Created skill directory: {skill_dir}")
581    except Exception as e:
582        print(f"❌ Error creating directory: {e}")
583        return None
584
585    # Create SKILL.md from template
586    skill_title = title_case_skill_name(skill_name)
587    skill_content = SKILL_TEMPLATE.format(
588        skill_name=skill_name,
589        skill_title=skill_title
590    )
591
592    skill_md_path = skill_dir / 'SKILL.md'
593    try:
594        skill_md_path.write_text(skill_content)
595        print("✅ Created SKILL.md")
596    except Exception as e:
597        print(f"❌ Error creating SKILL.md: {e}")
598        return None
599
600    # Create resource directories with example files
601    try:
602        # Create scripts/ directory with example script
603        scripts_dir = skill_dir / 'scripts'
604        scripts_dir.mkdir(exist_ok=True)
605        example_script = scripts_dir / 'example.py'
606        example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
607        example_script.chmod(0o755)
608        print("✅ Created scripts/example.py")
609
610        # Create references/ directory with example reference doc
611        references_dir = skill_dir / 'references'
612        references_dir.mkdir(exist_ok=True)
613        example_reference = references_dir / 'api_reference.md'
614        example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
615        print("✅ Created references/api_reference.md")
616
617        # Create assets/ directory with example asset placeholder
618        assets_dir = skill_dir / 'assets'
619        assets_dir.mkdir(exist_ok=True)
620        example_asset = assets_dir / 'example_asset.txt'
621        example_asset.write_text(EXAMPLE_ASSET)
622        print("✅ Created assets/example_asset.txt")
623    except Exception as e:
624        print(f"❌ Error creating resource directories: {e}")
625        return None
626
627    # Print next steps
628    print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}")
629    print("\nNext steps:")
630    print("1. Edit SKILL.md to complete the TODO items and update the description")
631    print("2. Customize or delete the example files in scripts/, references/, and assets/")
632    print("3. Run the validator when ready to check the skill structure")
633
634    return skill_dir
635
636
637def main():
638    if len(sys.argv) < 4 or sys.argv[2] != '--path':
639        print("Usage: init_skill.py <skill-name> --path <path>")
640        print("\nSkill name requirements:")
641        print("  - Hyphen-case identifier (e.g., 'data-analyzer')")
642        print("  - Lowercase letters, digits, and hyphens only")
643        print("  - Max 40 characters")
644        print("  - Must match directory name exactly")
645        print("\nExamples:")
646        print("  init_skill.py my-new-skill --path skills/public")
647        print("  init_skill.py my-api-helper --path skills/private")
648        print("  init_skill.py custom-skill --path /custom/location")
649        sys.exit(1)
650
651    skill_name = sys.argv[1]
652    path = sys.argv[3]
653
654    print(f"🚀 Initializing skill: {skill_name}")
655    print(f"   Location: {path}")
656    print()
657
658    result = init_skill(skill_name, path)
659
660    if result:
661        sys.exit(0)
662    else:
663        sys.exit(1)
664
665
666if __name__ == "__main__":
667    main()
668
669```
670
671
672# package_skill.py
673
674```python
675#!/usr/bin/env python3
676"""
677Skill Packager - Creates a distributable .skill file of a skill folder
678
679Usage:
680    python utils/package_skill.py <path/to/skill-folder> [output-directory]
681
682Example:
683    python utils/package_skill.py skills/public/my-skill
684    python utils/package_skill.py skills/public/my-skill ./dist
685"""
686
687import sys
688import zipfile
689from pathlib import Path
690from quick_validate import validate_skill
691
692
693def package_skill(skill_path, output_dir=None):
694    """
695    Package a skill folder into a .skill file.
696
697    Args:
698        skill_path: Path to the skill folder
699        output_dir: Optional output directory for the .skill file (defaults to current directory)
700
701    Returns:
702        Path to the created .skill file, or None if error
703    """
704    skill_path = Path(skill_path).resolve()
705
706    # Validate skill folder exists
707    if not skill_path.exists():
708        print(f"❌ Error: Skill folder not found: {skill_path}")
709        return None
710
711    if not skill_path.is_dir():
712        print(f"❌ Error: Path is not a directory: {skill_path}")
713        return None
714
715    # Validate SKILL.md exists
716    skill_md = skill_path / "SKILL.md"
717    if not skill_md.exists():
718        print(f"❌ Error: SKILL.md not found in {skill_path}")
719        return None
720
721    # Run validation before packaging
722    print("🔍 Validating skill...")
723    valid, message = validate_skill(skill_path)
724    if not valid:
725        print(f"❌ Validation failed: {message}")
726        print("   Please fix the validation errors before packaging.")
727        return None
728    print(f"✅ {message}\n")
729
730    # Determine output location
731    skill_name = skill_path.name
732    if output_dir:
733        output_path = Path(output_dir).resolve()
734        output_path.mkdir(parents=True, exist_ok=True)
735    else:
736        output_path = Path.cwd()
737
738    skill_filename = output_path / f"{skill_name}.skill"
739
740    # Create the .skill file (zip format)
741    try:
742        with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
743            # Walk through the skill directory
744            for file_path in skill_path.rglob('*'):
745                if file_path.is_file():
746                    # Calculate the relative path within the zip
747                    arcname = file_path.relative_to(skill_path.parent)
748                    zipf.write(file_path, arcname)
749                    print(f"  Added: {arcname}")
750
751        print(f"\n✅ Successfully packaged skill to: {skill_filename}")
752        return skill_filename
753
754    except Exception as e:
755        print(f"❌ Error creating .skill file: {e}")
756        return None
757
758
759def main():
760    if len(sys.argv) < 2:
761        print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
762        print("\nExample:")
763        print("  python utils/package_skill.py skills/public/my-skill")
764        print("  python utils/package_skill.py skills/public/my-skill ./dist")
765        sys.exit(1)
766
767    skill_path = sys.argv[1]
768    output_dir = sys.argv[2] if len(sys.argv) > 2 else None
769
770    print(f"📦 Packaging skill: {skill_path}")
771    if output_dir:
772        print(f"   Output directory: {output_dir}")
773    print()
774
775    result = package_skill(skill_path, output_dir)
776
777    if result:
778        sys.exit(0)
779    else:
780        sys.exit(1)
781
782
783if __name__ == "__main__":
784    main()
785
786```
787
788
789# quick_validate.py
790
791```python
792#!/usr/bin/env python3
793"""
794Quick validation script for skills - minimal version
795"""
796
797import sys
798import os
799import re
800import yaml
801from pathlib import Path
802
803def validate_skill(skill_path):
804    """Basic validation of a skill"""
805    skill_path = Path(skill_path)
806
807    # Check SKILL.md exists
808    skill_md = skill_path / 'SKILL.md'
809    if not skill_md.exists():
810        return False, "SKILL.md not found"
811
812    # Read and validate frontmatter
813    content = skill_md.read_text()
814    if not content.startswith('---'):
815        return False, "No YAML frontmatter found"
816
817    # Extract frontmatter
818    match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
819    if not match:
820        return False, "Invalid frontmatter format"
821
822    frontmatter_text = match.group(1)
823
824    # Parse YAML frontmatter
825    try:
826        frontmatter = yaml.safe_load(frontmatter_text)
827        if not isinstance(frontmatter, dict):
828            return False, "Frontmatter must be a YAML dictionary"
829    except yaml.YAMLError as e:
830        return False, f"Invalid YAML in frontmatter: {e}"
831
832    # Define allowed properties
833    ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
834
835    # Check for unexpected properties (excluding nested keys under metadata)
836    unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
837    if unexpected_keys:
838        return False, (
839            f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
840            f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
841        )
842
843    # Check required fields
844    if 'name' not in frontmatter:
845        return False, "Missing 'name' in frontmatter"
846    if 'description' not in frontmatter:
847        return False, "Missing 'description' in frontmatter"
848
849    # Extract name for validation
850    name = frontmatter.get('name', '')
851    if not isinstance(name, str):
852        return False, f"Name must be a string, got {type(name).__name__}"
853    name = name.strip()
854    if name:
855        # Check naming convention (hyphen-case: lowercase with hyphens)
856        if not re.match(r'^[a-z0-9-]+$', name):
857            return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
858        if name.startswith('-') or name.endswith('-') or '--' in name:
859            return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
860        # Check name length (max 64 characters per spec)
861        if len(name) > 64:
862            return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
863
864    # Extract and validate description
865    description = frontmatter.get('description', '')
866    if not isinstance(description, str):
867        return False, f"Description must be a string, got {type(description).__name__}"
868    description = description.strip()
869    if description:
870        # Check for angle brackets
871        if '<' in description or '>' in description:
872            return False, "Description cannot contain angle brackets (< or >)"
873        # Check description length (max 1024 characters per spec)
874        if len(description) > 1024:
875            return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
876
877    return True, "Skill is valid!"
878
879if __name__ == "__main__":
880    if len(sys.argv) != 2:
881        print("Usage: python quick_validate.py <skill_directory>")
882        sys.exit(1)
883    
884    valid, message = validate_skill(sys.argv[1])
885    print(message)
886    sys.exit(0 if valid else 1)
887```