中文译文
技能创建器
此技能为创建高效技能提供指导。
关于技能
技能是模块化、自包含的包,通过提供专门知识、工作流和工具来扩展 Claude 的能力。可以将它们视为针对特定领域或任务的「入门指南」——它们将 Claude 从通用智能体转变为具备任何模型都无法完全拥有的程序性知识的专门智能体。
技能提供什么
- 专门工作流 - 针对特定领域的多步骤流程
- 工具集成 - 用于处理特定文件格式或 API 的说明
- 领域专业知识 - 公司特定的知识、模式、业务逻辑
- 捆绑资源 - 用于复杂和重复性任务的脚本、参考资料和资产
核心原则
简洁是关键
上下文窗口是一种公共资源。技能与 Claude 所需的其他一切共享上下文窗口:系统提示词、对话历史、其他技能的元数据以及实际用户请求。
默认假设:Claude 已经非常聪明。 只添加 Claude 尚不具备的上下文。对每一条信息提出质疑:「Claude 真的需要这个解释吗?」以及「这一段是否值得其 token 成本?」
优先使用简洁的示例,而非冗长的解释。
设置适当的自由度
将具体程度与任务的脆弱性和可变性相匹配:
高自由度(基于文本的指令):当多种方法都可行、决策取决于上下文,或启发式方法指导做法时使用。
中等自由度(伪代码或带参数的脚本):当存在首选模式、某些变化可接受,或配置会影响行为时使用。
低自由度(特定脚本、少量参数):当操作脆弱且容易出错、一致性至关重要,或必须遵循特定顺序时使用。
将 Claude 想象成在探索一条路径:一座旁边是悬崖的窄桥需要特定的护栏(低自由度),而一片开阔的田野则允许许多路线(高自由度)。
技能的解剖结构
每个技能都由一个必需的 SKILL.md 文件和可选的捆绑资源组成:
skill-name/
├── SKILL.md (required)
│ ├── YAML frontmatter metadata (required)
│ │ ├── name: (required)
│ │ └── description: (required)
│ └── Markdown instructions (required)
└── Bundled Resources (optional)
├── scripts/ - Executable code (Python/Bash/etc.)
├── references/ - Documentation intended to be loaded into context as needed
└── assets/ - Files used in output (templates, icons, fonts, etc.)
SKILL.md(必需)
每个 SKILL.md 由以下部分组成:
- Frontmatter(YAML):包含
name和description字段。这是 Claude 用来判断该技能何时被使用的唯一字段,因此在描述该技能是什么以及何时应被使用时,务必清晰且全面,这一点非常重要。 - Body(Markdown):使用该技能的说明和指导。仅在技能触发之后才加载(如果会加载的话)。
捆绑资源(可选)
脚本(scripts/)
用于需要确定性可靠性或会被反复重写的任务的可执行代码(Python/Bash 等)。
- 何时包含:当同一段代码被反复重写,或需要确定性可靠性时
- 示例:用于 PDF 旋转任务的
scripts/rotate_pdf.py - 优点:节省 token、具有确定性、可无需加载到上下文中即可执行
- 注意:Claude 仍可能需要读取脚本,以便进行修补或针对特定环境进行调整
参考资料(references/)
旨在按需加载到上下文中,以辅助 Claude 的处理过程和思考的文档与参考材料。
- 何时包含:当 Claude 在工作时应参考某些文档时
- 示例:用于财务模式的
references/finance.md、用于公司 NDA 模板的references/mnda.md、用于公司政策的references/policies.md、用于 API 规范的references/api_docs.md - 使用场景:数据库模式、API 文档、领域知识、公司政策、详细工作流指南
- 优点:让 SKILL.md 保持精简,仅在 Claude 判断需要时才加载
- 最佳实践:如果文件很大(超过 1 万词),在 SKILL.md 中包含 grep 搜索模式
- 避免重复:信息应只存在于 SKILL.md 或参考资料文件中,而不是两者都有。
资产(assets/)
不打算加载到上下文中,而是在 Claude 生成的输出中使用的文件。
- 何时包含:当技能需要将在最终输出中使用的文件时
- 示例:
assets/logo.png用于品牌资产,assets/slides.pptx用于 PowerPoint 模板 - 使用场景:模板、图像、图标、样板代码、字体、示例文档
渐进式披露设计原则
技能使用三级加载系统来高效管理上下文:
- 元数据(名称 + 描述) - 始终在上下文中(约 100 词)
- SKILL.md 正文 - 当技能触发时(<5k 词)
- 捆绑资源 - 根据 Claude 的需要
将 SKILL.md 正文保持在 essentials 范围内并少于 500 行,以最小化上下文膨胀。
技能创建流程
技能创建涉及以下步骤:
- 通过具体示例理解技能
- 规划可复用的技能内容(脚本、参考、资产)
- 初始化技能(运行 init_skill.py)
- 编辑技能(实现资源并编写 SKILL.md)
- 打包技能(运行 package_skill.py)
- 根据实际使用进行迭代
步骤 3:初始化技能
从头创建新技能时,始终运行 init_skill.py 脚本:
scripts/init_skill.py <skill-name> --path <output-directory>
第 4 步:编辑技能
根据你的技能需求,参考以下实用指南:
- 多步骤流程:参见 references/workflows.md,了解顺序工作流和条件逻辑
- 特定输出格式或质量标准:参见 references/output-patterns.md,了解模板和示例模式
第 5 步:打包技能
scripts/package_skill.py <path/to/skill-folder>
打包脚本会校验并创建一个用于分发的 .skill 文件。 FILE:references/workflows.md
工作流模式
顺序工作流
对于复杂任务,将操作拆分为清晰的、顺序的步骤。在 SKILL.md 开头部分向 Claude 提供流程概览通常会很有帮助:
Filling a PDF form involves these steps:
1. Analyze the form (run analyze_form.py)
2. Create field mapping (edit fields.json)
3. Validate mapping (run validate_fields.py)
4. Fill the form (run fill_form.py)
5. Verify output (run verify_output.py)
条件工作流
对于带有分支逻辑的任务,引导 Claude 走完各个决策点:
1. Determine the modification type:
**Creating new content?** → Follow "Creation workflow" below
**Editing existing content?** → Follow "Editing workflow" below
2. Creation workflow: [steps]
3. Editing workflow: [steps]
输出模式
当技能需要产生一致、高质量的输出时,使用这些模式。
模板模式
为输出格式提供模板。根据你的需求匹配严格程度。
对于严格要求(如 API 响应或数据格式):
## Report structure
ALWAYS use this exact template structure:
# [Analysis Title]
## Executive summary
[One-paragraph overview of key findings]
## Key findings
- Finding 1 with supporting data
- Finding 2 with supporting data
- Finding 3 with supporting data
## Recommendations
1. Specific actionable recommendation
2. Specific actionable recommendation
用于灵活引导(当适配有用时):
## Report structure
Here is a sensible default format, but use your best judgment:
# [Analysis Title]
## Executive summary
[Overview]
## Key findings
[Adapt sections based on what you discover]
## Recommendations
[Tailor to the specific context]
Adjust sections as needed for the specific analysis type.
示例模式
对于输出质量取决于查看示例的技能,提供输入/输出对:
## Commit message format
Generate commit messages following these examples:
**Example 1:**
Input: Added user authentication with JWT tokens
Output:
feat(auth): 实现基于 JWT 的认证
添加登录端点与令牌校验中间件
**Example 2:**
Input: Fixed bug where dates displayed incorrectly in reports
Output:
fix(reports):修正时区转换中的日期格式
在报告生成过程中统一使用 UTC 时间戳
Follow this style: type(scope): brief description, then detailed explanation.
示例能帮助 Claude 比仅靠描述更清楚地理解期望的风格和详细程度。 文件:scripts/quick_validate.py #!/usr/bin/env python3 """ 技能的快速验证脚本 - 最小版本 """
import sys import os import re import yaml from pathlib import Path
def validate_skill(skill_path): """对技能进行基本验证""" skill_path = Path(skill_path)
# 检查 SKILL.md 是否存在
skill_md = skill_path / 'SKILL.md'
if not skill_md.exists():
return False, "未找到 SKILL.md"
# 读取并验证 frontmatter
content = skill_md.read_text()
if not content.startswith('---'):
return False, "未找到 YAML frontmatter"
# 提取 frontmatter
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not match:
return False, "frontmatter 格式无效"
frontmatter_text = match.group(1)
# 解析 YAML frontmatter
try:
frontmatter = yaml.safe_load(frontmatter_text)
if not isinstance(frontmatter, dict):
return False, "frontmatter 必须是 YAML 字典"
except yaml.YAMLError as e:
return False, f"frontmatter 中的 YAML 无效:{e}"
# 定义允许的属性
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
# 检查意外属性(排除 metadata 下的嵌套键)
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
if unexpected_keys:
return False, (
f"SKILL.md frontmatter 中出现意外键:{', '.join(sorted(unexpected_keys))}。"
f"允许的属性为:{', '.join(sorted(ALLOWED_PROPERTIES))}"
)
# 检查必填字段
if 'name' not in frontmatter:
return False, "frontmatter 中缺少 'name'"
if 'description' not in frontmatter:
return False, "frontmatter 中缺少 'description'"
提取名称以进行校验
name = frontmatter.get('name', '')
if not isinstance(name, str):
return False, f"Name must be a string, got {type(name).__name__}"
name = name.strip()
if name:
# 检查命名规范(连字符格式:小写字母加连字符)
if not re.match(r'^[a-z0-9-]+$', name):
return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
if name.startswith('-') or name.endswith('-') or '--' in name:
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
# 检查名称长度(按规范最多 64 个字符)
if len(name) > 64:
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
# 提取并校验描述
description = frontmatter.get('description', '')
if not isinstance(description, str):
return False, f"Description must be a string, got {type(description).__name__}"
description = description.strip()
if description:
# 检查尖括号
if '<' in description or '>' in description:
return False, "Description cannot contain angle brackets (< or >)"
# 检查描述长度(按规范最多 1024 个字符)
if len(description) > 1024:
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
return True, "Skill is valid!"
if name == "main": if len(sys.argv) != 2: print("Usage: python quick_validate.py ") sys.exit(1)
valid, message = validate_skill(sys.argv[1])
print(message)
sys.exit(0 if valid else 1)
FILE:scripts/init_skill.py #!/usr/bin/env python3 """ 技能初始化器 - 从模板创建一个新技能 用法: init_skill.py --path
示例: init_skill.py my-new-skill --path skills/public init_skill.py my-api-helper --path skills/private init_skill.py custom-skill --path /custom/location """
import sys from pathlib import Path
SKILL_TEMPLATE = """--- name: {skill_name} description: [TODO: 完整且信息丰富的说明,解释该技能的作用以及何时使用它。包括何时使用该技能——触发它的具体场景、文件类型或任务。]
{skill_title}
概述
[TODO: 用 1-2 句话说明该技能能实现什么]
资源
该技能包含示例资源目录,用于演示如何组织不同类型的捆绑资源:
scripts/
可直接运行以执行特定操作的可执行代码(Python/Bash 等)。
references/
旨在加载到上下文中、为 Claude 的处理和思考提供信息的文档和参考资料。
assets/
不打算加载到上下文中,而是在 Claude 生成的输出中使用的文件。
任何不需要的目录都可以删除。 并非每个技能都需要全部三种类型的资源。 """
EXAMPLE_SCRIPT = '''#!/usr/bin/env python3 """ {skill_name} 的示例辅助脚本
这是一个可直接执行的占位脚本。 请替换为实际实现,如不需要则删除。 """
def main(): print("这是 {skill_name} 的示例脚本") # TODO: 在此处添加实际的脚本逻辑
if name == "main": main() '''
EXAMPLE_REFERENCE = """# {skill_title} 的参考文档
这是详细参考文档的占位内容。 请替换为实际的参考内容,如不需要则删除。 """
EXAMPLE_ASSET = """# 示例资产文件
该占位内容表示资产文件的存放位置。 请替换为实际的资产文件(模板、图片、字体等),如不需要则删除。 """ def title_case_skill_name(skill_name): """将连字符风格的技能名称转换为标题大小写以便显示。""" return ' '.join(word.capitalize() for word in skill_name.split('-'))
def init_skill(skill_name, path): """使用模板 SKILL.md 初始化一个新的技能目录。""" skill_dir = Path(path).resolve() / skill_name
if skill_dir.exists():
print(f"❌ Error: Skill directory already exists: {skill_dir}")
return None
try:
skill_dir.mkdir(parents=True, exist_ok=False)
print(f"✅ Created skill directory: {skill_dir}")
except Exception as e:
print(f"❌ Error creating directory: {e}")
return None
skill_title = title_case_skill_name(skill_name)
skill_content = SKILL_TEMPLATE.format(skill_name=skill_name, skill_title=skill_title)
skill_md_path = skill_dir / 'SKILL.md'
try:
skill_md_path.write_text(skill_content)
print("✅ Created SKILL.md")
except Exception as e:
print(f"❌ Error creating SKILL.md: {e}")
return None
try:
scripts_dir = skill_dir / 'scripts'
scripts_dir.mkdir(exist_ok=True)
example_script = scripts_dir / 'example.py'
example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
example_script.chmod(0o755)
print("✅ Created scripts/example.py")
references_dir = skill_dir / 'references'
references_dir.mkdir(exist_ok=True)
example_reference = references_dir / 'api_reference.md'
example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
print("✅ Created references/api_reference.md")
assets_dir = skill_dir / 'assets'
assets_dir.mkdir(exist_ok=True)
example_asset = assets_dir / 'example_asset.txt'
example_asset.write_text(EXAMPLE_ASSET)
print("✅ Created assets/example_asset.txt")
except Exception as e:
print(f"❌ Error creating resource directories: {e}")
return None
print(f"\n✅ 技能 '{skill_name}' 已成功初始化于 {skill_dir}") return skill_dir
def main(): if len(sys.argv) < 4 or sys.argv[2] != '--path': print("用法:init_skill.py --path ") sys.exit(1)
skill_name = sys.argv[1]
path = sys.argv[3]
print(f"🚀 正在初始化技能:{skill_name}")
print(f" 位置:{path}")
print()
result = init_skill(skill_name, path)
sys.exit(0 if result else 1)
if name == "main": main() FILE:scripts/package_skill.py #!/usr/bin/env python3 """ 技能打包器 - 为技能文件夹创建可分发的 .skill 文件
用法: python utils/package_skill.py <path/to/skill-folder> [output-directory]
示例: python utils/package_skill.py skills/public/my-skill python utils/package_skill.py skills/public/my-skill ./dist """
import sys import zipfile from pathlib import Path from quick_validate import validate_skill
def package_skill(skill_path, output_dir=None): """将技能文件夹打包为 .skill 文件。""" skill_path = Path(skill_path).resolve()
if not skill_path.exists():
print(f"❌ 错误:未找到技能文件夹:{skill_path}")
return None
if not skill_path.is_dir():
print(f"❌ 错误:路径不是目录:{skill_path}")
return None
skill_md = skill_path / "SKILL.md"
if not skill_md.exists():
print(f"❌ 错误:在 {skill_path} 中未找到 SKILL.md")
return None
print("🔍 正在验证技能...")
valid, message = validate_skill(skill_path)
if not valid:
print(f"❌ 验证失败:{message}")
print(" 请在打包前修复验证错误。")
return None
print(f"✅ {message}\n")
skill_name = skill_path.name
if output_dir:
output_path = Path(output_dir).resolve()
output_path.mkdir(parents=True, exist_ok=True)
else:
output_path = Path.cwd()
skill_filename = output_path / f"{skill_name}.skill"
try:
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_path in skill_path.rglob('*'):
if file_path.is_file():
arcname = file_path.relative_to(skill_path.parent)
zipf.write(file_path, arcname)
print(f" Added: {arcname}")
print(f"\n✅ Successfully packaged skill to: {skill_filename}")
return skill_filename
except Exception as e:
print(f"❌ Error creating .skill file: {e}")
return None
def main(): if len(sys.argv) < 2: print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]") sys.exit(1)
skill_path = sys.argv[1]
output_dir = sys.argv[2] if len(sys.argv) > 2 else None
print(f"📦 Packaging skill: {skill_path}")
if output_dir:
print(f" Output directory: {output_dir}")
print()
result = package_skill(skill_path, output_dir)
sys.exit(0 if result else 1)
if name == "main": main()
English original
Skill Creator
This skill provides guidance for creating effective skills.
About Skills
Skills are modular, self-contained packages that extend Claude's capabilities by providing specialized knowledge, workflows, and tools. Think of them as "onboarding guides" for specific domains or tasks—they transform Claude from a general-purpose agent into a specialized agent equipped with procedural knowledge that no model can fully possess.
What Skills Provide
- Specialized workflows - Multi-step procedures for specific domains
- Tool integrations - Instructions for working with specific file formats or APIs
- Domain expertise - Company-specific knowledge, schemas, business logic
- Bundled resources - Scripts, references, and assets for complex and repetitive tasks
Core Principles
Concise is Key
The 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.
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?"
Prefer concise examples over verbose explanations.
Set Appropriate Degrees of Freedom
Match the level of specificity to the task's fragility and variability:
High freedom (text-based instructions): Use when multiple approaches are valid, decisions depend on context, or heuristics guide the approach.
Medium freedom (pseudocode or scripts with parameters): Use when a preferred pattern exists, some variation is acceptable, or configuration affects behavior.
Low freedom (specific scripts, few parameters): Use when operations are fragile and error-prone, consistency is critical, or a specific sequence must be followed.
Think 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).
Anatomy of a Skill
Every skill consists of a required SKILL.md file and optional bundled resources:
skill-name/
├── SKILL.md (required)
│ ├── YAML frontmatter metadata (required)
│ │ ├── name: (required)
│ │ └── description: (required)
│ └── Markdown instructions (required)
└── Bundled Resources (optional)
├── scripts/ - Executable code (Python/Bash/etc.)
├── references/ - Documentation intended to be loaded into context as needed
└── assets/ - Files used in output (templates, icons, fonts, etc.)
SKILL.md (required)
Every SKILL.md consists of:
- Frontmatter (YAML): Contains
nameanddescriptionfields. 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. - Body (Markdown): Instructions and guidance for using the skill. Only loaded AFTER the skill triggers (if at all).
Bundled Resources (optional)
Scripts (scripts/)
Executable code (Python/Bash/etc.) for tasks that require deterministic reliability or are repeatedly rewritten.
- When to include: When the same code is being rewritten repeatedly or deterministic reliability is needed
- Example:
scripts/rotate_pdf.pyfor PDF rotation tasks - Benefits: Token efficient, deterministic, may be executed without loading into context
- Note: Scripts may still need to be read by Claude for patching or environment-specific adjustments
References (references/)
Documentation and reference material intended to be loaded as needed into context to inform Claude's process and thinking.
- When to include: For documentation that Claude should reference while working
- Examples:
references/finance.mdfor financial schemas,references/mnda.mdfor company NDA template,references/policies.mdfor company policies,references/api_docs.mdfor API specifications - Use cases: Database schemas, API documentation, domain knowledge, company policies, detailed workflow guides
- Benefits: Keeps SKILL.md lean, loaded only when Claude determines it's needed
- Best practice: If files are large (>10k words), include grep search patterns in SKILL.md
- Avoid duplication: Information should live in either SKILL.md or references files, not both.
Assets (assets/)
Files not intended to be loaded into context, but rather used within the output Claude produces.
- When to include: When the skill needs files that will be used in the final output
- Examples:
assets/logo.pngfor brand assets,assets/slides.pptxfor PowerPoint templates - Use cases: Templates, images, icons, boilerplate code, fonts, sample documents
Progressive Disclosure Design Principle
Skills use a three-level loading system to manage context efficiently:
- Metadata (name + description) - Always in context (~100 words)
- SKILL.md body - When skill triggers (<5k words)
- Bundled resources - As needed by Claude
Keep SKILL.md body to the essentials and under 500 lines to minimize context bloat.
Skill Creation Process
Skill creation involves these steps:
- Understand the skill with concrete examples
- Plan reusable skill contents (scripts, references, assets)
- Initialize the skill (run init_skill.py)
- Edit the skill (implement resources and write SKILL.md)
- Package the skill (run package_skill.py)
- Iterate based on real usage
Step 3: Initializing the Skill
When creating a new skill from scratch, always run the init_skill.py script:
scripts/init_skill.py <skill-name> --path <output-directory>
Step 4: Edit the Skill
Consult these helpful guides based on your skill's needs:
- Multi-step processes: See references/workflows.md for sequential workflows and conditional logic
- Specific output formats or quality standards: See references/output-patterns.md for template and example patterns
Step 5: Packaging a Skill
scripts/package_skill.py <path/to/skill-folder>
The packaging script validates and creates a .skill file for distribution. FILE:references/workflows.md
Workflow Patterns
Sequential Workflows
For complex tasks, break operations into clear, sequential steps. It is often helpful to give Claude an overview of the process towards the beginning of SKILL.md:
Filling a PDF form involves these steps:
1. Analyze the form (run analyze_form.py)
2. Create field mapping (edit fields.json)
3. Validate mapping (run validate_fields.py)
4. Fill the form (run fill_form.py)
5. Verify output (run verify_output.py)
Conditional Workflows
For tasks with branching logic, guide Claude through decision points:
1. Determine the modification type:
**Creating new content?** → Follow "Creation workflow" below
**Editing existing content?** → Follow "Editing workflow" below
2. Creation workflow: [steps]
3. Editing workflow: [steps]
FILE:references/output-patterns.md
Output Patterns
Use these patterns when skills need to produce consistent, high-quality output.
Template Pattern
Provide templates for output format. Match the level of strictness to your needs.
For strict requirements (like API responses or data formats):
## Report structure
ALWAYS use this exact template structure:
# [Analysis Title]
## Executive summary
[One-paragraph overview of key findings]
## Key findings
- Finding 1 with supporting data
- Finding 2 with supporting data
- Finding 3 with supporting data
## Recommendations
1. Specific actionable recommendation
2. Specific actionable recommendation
For flexible guidance (when adaptation is useful):
## Report structure
Here is a sensible default format, but use your best judgment:
# [Analysis Title]
## Executive summary
[Overview]
## Key findings
[Adapt sections based on what you discover]
## Recommendations
[Tailor to the specific context]
Adjust sections as needed for the specific analysis type.
Examples Pattern
For skills where output quality depends on seeing examples, provide input/output pairs:
## Commit message format
Generate commit messages following these examples:
**Example 1:**
Input: Added user authentication with JWT tokens
Output:
feat(auth): implement JWT-based authentication
Add login endpoint and token validation middleware
**Example 2:**
Input: Fixed bug where dates displayed incorrectly in reports
Output:
fix(reports): correct date formatting in timezone conversion
Use UTC timestamps consistently across report generation
Follow this style: type(scope): brief description, then detailed explanation.
Examples help Claude understand the desired style and level of detail more clearly than descriptions alone. FILE:scripts/quick_validate.py #!/usr/bin/env python3 """ Quick validation script for skills - minimal version """
import sys import os import re import yaml from pathlib import Path
def validate_skill(skill_path): """Basic validation of a skill""" skill_path = Path(skill_path)
# Check SKILL.md exists
skill_md = skill_path / 'SKILL.md'
if not skill_md.exists():
return False, "SKILL.md not found"
# Read and validate frontmatter
content = skill_md.read_text()
if not content.startswith('---'):
return False, "No YAML frontmatter found"
# Extract frontmatter
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not match:
return False, "Invalid frontmatter format"
frontmatter_text = match.group(1)
# Parse YAML frontmatter
try:
frontmatter = yaml.safe_load(frontmatter_text)
if not isinstance(frontmatter, dict):
return False, "Frontmatter must be a YAML dictionary"
except yaml.YAMLError as e:
return False, f"Invalid YAML in frontmatter: {e}"
# Define allowed properties
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
# Check for unexpected properties (excluding nested keys under metadata)
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
if unexpected_keys:
return False, (
f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
)
# Check required fields
if 'name' not in frontmatter:
return False, "Missing 'name' in frontmatter"
if 'description' not in frontmatter:
return False, "Missing 'description' in frontmatter"
# Extract name for validation
name = frontmatter.get('name', '')
if not isinstance(name, str):
return False, f"Name must be a string, got {type(name).__name__}"
name = name.strip()
if name:
# Check naming convention (hyphen-case: lowercase with hyphens)
if not re.match(r'^[a-z0-9-]+$', name):
return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
if name.startswith('-') or name.endswith('-') or '--' in name:
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
# Check name length (max 64 characters per spec)
if len(name) > 64:
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
# Extract and validate description
description = frontmatter.get('description', '')
if not isinstance(description, str):
return False, f"Description must be a string, got {type(description).__name__}"
description = description.strip()
if description:
# Check for angle brackets
if '<' in description or '>' in description:
return False, "Description cannot contain angle brackets (< or >)"
# Check description length (max 1024 characters per spec)
if len(description) > 1024:
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
return True, "Skill is valid!"
if name == "main": if len(sys.argv) != 2: print("Usage: python quick_validate.py ") sys.exit(1)
valid, message = validate_skill(sys.argv[1])
print(message)
sys.exit(0 if valid else 1)
FILE:scripts/init_skill.py #!/usr/bin/env python3 """ Skill Initializer - Creates a new skill from template
Usage: init_skill.py --path
Examples: init_skill.py my-new-skill --path skills/public init_skill.py my-api-helper --path skills/private init_skill.py custom-skill --path /custom/location """
import sys from pathlib import Path
SKILL_TEMPLATE = """--- name: {skill_name} description: [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.]
{skill_title}
Overview
[TODO: 1-2 sentences explaining what this skill enables]
Resources
This skill includes example resource directories that demonstrate how to organize different types of bundled resources:
scripts/
Executable code (Python/Bash/etc.) that can be run directly to perform specific operations.
references/
Documentation and reference material intended to be loaded into context to inform Claude's process and thinking.
assets/
Files not intended to be loaded into context, but rather used within the output Claude produces.
Any unneeded directories can be deleted. Not every skill requires all three types of resources. """
EXAMPLE_SCRIPT = '''#!/usr/bin/env python3 """ Example helper script for {skill_name}
This is a placeholder script that can be executed directly. Replace with actual implementation or delete if not needed. """
def main(): print("This is an example script for {skill_name}") # TODO: Add actual script logic here
if name == "main": main() '''
EXAMPLE_REFERENCE = """# Reference Documentation for {skill_title}
This is a placeholder for detailed reference documentation. Replace with actual reference content or delete if not needed. """
EXAMPLE_ASSET = """# Example Asset File
This placeholder represents where asset files would be stored. Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed. """
def title_case_skill_name(skill_name): """Convert hyphenated skill name to Title Case for display.""" return ' '.join(word.capitalize() for word in skill_name.split('-'))
def init_skill(skill_name, path): """Initialize a new skill directory with template SKILL.md.""" skill_dir = Path(path).resolve() / skill_name
if skill_dir.exists():
print(f"❌ Error: Skill directory already exists: {skill_dir}")
return None
try:
skill_dir.mkdir(parents=True, exist_ok=False)
print(f"✅ Created skill directory: {skill_dir}")
except Exception as e:
print(f"❌ Error creating directory: {e}")
return None
skill_title = title_case_skill_name(skill_name)
skill_content = SKILL_TEMPLATE.format(skill_name=skill_name, skill_title=skill_title)
skill_md_path = skill_dir / 'SKILL.md'
try:
skill_md_path.write_text(skill_content)
print("✅ Created SKILL.md")
except Exception as e:
print(f"❌ Error creating SKILL.md: {e}")
return None
try:
scripts_dir = skill_dir / 'scripts'
scripts_dir.mkdir(exist_ok=True)
example_script = scripts_dir / 'example.py'
example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
example_script.chmod(0o755)
print("✅ Created scripts/example.py")
references_dir = skill_dir / 'references'
references_dir.mkdir(exist_ok=True)
example_reference = references_dir / 'api_reference.md'
example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
print("✅ Created references/api_reference.md")
assets_dir = skill_dir / 'assets'
assets_dir.mkdir(exist_ok=True)
example_asset = assets_dir / 'example_asset.txt'
example_asset.write_text(EXAMPLE_ASSET)
print("✅ Created assets/example_asset.txt")
except Exception as e:
print(f"❌ Error creating resource directories: {e}")
return None
print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}")
return skill_dir
def main(): if len(sys.argv) < 4 or sys.argv[2] != '--path': print("Usage: init_skill.py --path ") sys.exit(1)
skill_name = sys.argv[1]
path = sys.argv[3]
print(f"🚀 Initializing skill: {skill_name}")
print(f" Location: {path}")
print()
result = init_skill(skill_name, path)
sys.exit(0 if result else 1)
if name == "main": main() FILE:scripts/package_skill.py #!/usr/bin/env python3 """ Skill Packager - Creates a distributable .skill file of a skill folder
Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]
Example: python utils/package_skill.py skills/public/my-skill python utils/package_skill.py skills/public/my-skill ./dist """
import sys import zipfile from pathlib import Path from quick_validate import validate_skill
def package_skill(skill_path, output_dir=None): """Package a skill folder into a .skill file.""" skill_path = Path(skill_path).resolve()
if not skill_path.exists():
print(f"❌ Error: Skill folder not found: {skill_path}")
return None
if not skill_path.is_dir():
print(f"❌ Error: Path is not a directory: {skill_path}")
return None
skill_md = skill_path / "SKILL.md"
if not skill_md.exists():
print(f"❌ Error: SKILL.md not found in {skill_path}")
return None
print("🔍 Validating skill...")
valid, message = validate_skill(skill_path)
if not valid:
print(f"❌ Validation failed: {message}")
print(" Please fix the validation errors before packaging.")
return None
print(f"✅ {message}\n")
skill_name = skill_path.name
if output_dir:
output_path = Path(output_dir).resolve()
output_path.mkdir(parents=True, exist_ok=True)
else:
output_path = Path.cwd()
skill_filename = output_path / f"{skill_name}.skill"
try:
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_path in skill_path.rglob('*'):
if file_path.is_file():
arcname = file_path.relative_to(skill_path.parent)
zipf.write(file_path, arcname)
print(f" Added: {arcname}")
print(f"\n✅ Successfully packaged skill to: {skill_filename}")
return skill_filename
except Exception as e:
print(f"❌ Error creating .skill file: {e}")
return None
def main(): if len(sys.argv) < 2: print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]") sys.exit(1)
skill_path = sys.argv[1]
output_dir = sys.argv[2] if len(sys.argv) > 2 else None
print(f"📦 Packaging skill: {skill_path}")
if output_dir:
print(f" Output directory: {output_dir}")
print()
result = package_skill(skill_path, output_dir)
sys.exit(0 if result else 1)
if name == "main": main()