feat: Add OurDigital custom skills package (10 skills)

Complete implementation of OurDigital skills with dual-platform support
(Claude Desktop + Claude Code) following standardized structure.

Skills created:
- 01-ourdigital-brand-guide: Brand reference & style guidelines
- 02-ourdigital-blog: Korean blog drafts (blog.ourdigital.org)
- 03-ourdigital-journal: English essays (journal.ourdigital.org)
- 04-ourdigital-research: Research prompts & workflows
- 05-ourdigital-document: Notion-to-presentation pipeline
- 06-ourdigital-designer: Visual/image prompt generation
- 07-ourdigital-ad-manager: Ad copywriting & keyword research
- 08-ourdigital-trainer: Training materials & workshop planning
- 09-ourdigital-backoffice: Quotes, proposals, cost analysis
- 10-ourdigital-skill-creator: Meta skill for creating new skills

Features:
- YAML frontmatter with "ourdigital" or "our" prefix triggers
- Standardized directory structure (code/, desktop/, shared/, docs/)
- Shared environment setup (_ourdigital-shared/)
- Comprehensive reference documentation
- Cross-skill integration support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 16:50:17 +07:00
parent 7d20abe811
commit 0bc24d00b9
169 changed files with 9970 additions and 741 deletions

View File

@@ -0,0 +1,75 @@
# OurDigital Skill Creator
Meta skill for creating, validating, and managing OurDigital Claude Skills.
## Purpose
This skill helps create new OurDigital skills with:
- Proper directory structure
- YAML frontmatter conventions
- OurDigital trigger patterns
- Notion history tracking
## Activation
Only activates with "ourdigital" keyword:
- "ourdigital 스킬 만들기"
- "ourdigital skill creator"
- "create ourdigital skill"
## Structure
```
10-ourdigital-skill-creator/
├── code/
│ └── SKILL.md # Claude Code version
├── desktop/
│ └── SKILL.md # Claude Desktop version
├── shared/
│ ├── references/
│ │ ├── suitability-criteria.md
│ │ └── skill-patterns.md
│ ├── templates/
│ │ └── SKILL-TEMPLATE.md
│ └── scripts/
│ ├── init_skill.py
│ └── validate_skill.py
├── docs/
│ ├── CHANGELOG.md
│ └── logs/
└── README.md
```
## Usage
### Create a New Skill
```bash
python shared/scripts/init_skill.py {name} --number XX
# Example
python shared/scripts/init_skill.py blog --number 02
```
### Validate a Skill
```bash
python shared/scripts/validate_skill.py {skill-directory}
# Example
python shared/scripts/validate_skill.py 02-ourdigital-blog
```
## Workflow
1. **Suitability Check** - Evaluate if need fits Claude Skill criteria
2. **Requirements Q&A** - Gather purpose, triggers, tools, outputs
3. **Generate Structure** - Create directories and files
4. **Validation** - Verify structure and content
5. **Notion Sync** - Record to Working with AI database
## Version
- Current: 1.0.0
- Author: OurDigital
- Environment: Both (Desktop & Code)

View File

@@ -0,0 +1,170 @@
---
name: ourdigital-skill-creator
description: |
Meta skill for creating OurDigital Claude Skills in Code environment.
Activated with "ourdigital" keyword + skill creation requests.
Triggers:
- "ourdigital 스킬 만들기", "ourdigital skill creator"
- "create ourdigital skill", "new ourdigital skill"
Features:
- Skill suitability evaluation
- Interactive requirements gathering
- Directory/file generation
- Notion history sync
version: "1.0"
author: OurDigital
environment: Code
---
# OurDigital Skill Creator (Code)
Create and manage OurDigital Claude Skills with automated scaffolding.
## Activation
Only when "ourdigital" + skill-related request:
- "ourdigital 스킬 만들어줘"
- "create ourdigital skill for X"
## Quick Start
```bash
# Initialize new skill
python shared/scripts/init_skill.py {skill-name} --number XX
# Validate skill structure
python shared/scripts/validate_skill.py XX-ourdigital-{skill-name}
# Sync to Notion
python shared/scripts/sync_notion.py XX-ourdigital-{skill-name} --action=create
```
## Workflow
### 1. Suitability Check
Before creating, evaluate:
| Criterion | Pass? |
|-----------|-------|
| Clear trigger (includes "ourdigital") | |
| Focused scope (1-3 functions) | |
| Reusable resources needed | |
| Domain-specific knowledge | |
| No overlap with existing skills | |
≥3 passes → proceed with creation.
### 2. Requirements Q&A
Ask in sequence:
1. **Purpose**: Core function of the skill?
2. **Trigger**: When should it activate? (must include "ourdigital")
3. **Tools**: External APIs, MCPs, or scripts needed?
4. **Output**: Expected deliverables?
5. **Environment**: Desktop, Code, or Both?
### 3. Generate Structure
Create directories and files:
```bash
mkdir -p XX-ourdigital-{name}/{code,desktop,shared/{references,templates,scripts},docs/logs}
```
Generate files:
- `desktop/SKILL.md` - MCP-focused version
- `code/SKILL.md` - Action-oriented version
- `shared/references/` - Common documentation
- `docs/CHANGELOG.md` - Initial changelog
- `README.md` - Skill overview
### 4. YAML Frontmatter
Apply standard template:
```yaml
---
name: ourdigital-{skill-name}
description: |
[One-line purpose]
Activated with "ourdigital" keyword.
Triggers:
- "ourdigital {keyword1}"
- "ourdigital {keyword2}"
Features:
- Feature 1
- Feature 2
version: "1.0"
author: OurDigital
environment: Code
---
```
### 5. Validation Checklist
- [ ] Directory structure matches template
- [ ] SKILL.md in both code/ and desktop/
- [ ] "ourdigital" in description triggers
- [ ] Body content 800-1,200 words
- [ ] CHANGELOG.md initialized
- [ ] No conflicts with existing skills
### 6. Notion Sync
Record creation to Working with AI database:
```python
# Properties
{
"Name": "ourdigital-{skill-name} v1.0",
"Status": "Done",
"AI used": "Claude Code",
"AI summary": "Skill description"
}
```
## Scripts
| Script | Purpose |
|--------|---------|
| `init_skill.py` | Scaffold new skill directory |
| `validate_skill.py` | Check skill structure |
| `sync_notion.py` | Sync to Notion database |
## Skill Categories
| Number | Category |
|--------|----------|
| 01-09 | OurDigital Core |
| 10 | Meta (this skill) |
| 11-19 | SEO |
| 20-29 | GTM/Analytics |
| 31-39 | Notion |
| 40-49 | Jamie Clinic |
## Files Reference
```
10-ourdigital-skill-creator/
├── code/SKILL.md # This file
├── desktop/SKILL.md # Desktop version
├── shared/
│ ├── references/
│ │ ├── suitability-criteria.md
│ │ └── skill-patterns.md
│ ├── templates/
│ │ └── skill-template/
│ └── scripts/
│ ├── init_skill.py
│ ├── validate_skill.py
│ └── sync_notion.py
└── docs/
├── CHANGELOG.md
└── logs/
```

View File

@@ -0,0 +1,167 @@
---
name: ourdigital-skill-creator
description: |
Meta skill for creating and managing OurDigital Claude Skills.
Activated when user includes "ourdigital" keyword with skill creation requests.
Triggers (ourdigital or our prefix):
- "ourdigital skill create", "our skill create"
- "ourdigital 스킬 만들기", "our 스킬 만들기"
- "ourdigital skill creator", "our skill creator"
Features:
- Skill suitability evaluation
- Interactive Q&A for requirements gathering
- Optimized skill generation (Desktop/Code)
- Notion history tracking
version: "1.0"
author: OurDigital
environment: Desktop
---
# OurDigital Skill Creator
Meta skill for creating, validating, and managing OurDigital Claude Skills.
## Activation
Activate with "ourdigital" or "our" prefix:
- "ourdigital 스킬 만들어줘" / "our 스킬 만들어줘"
- "ourdigital skill creator" / "our skill creator"
- "our skill create [name]"
Do NOT activate for generic "make a skill" requests (without our/ourdigital prefix).
## Interactive Workflow
### Phase 1: Need Assessment
When user requests a new skill:
1. **Acknowledge** the initial request
2. **Ask clarifying questions** (max 3 per turn):
- What is the core purpose?
- What triggers this skill?
- What outputs do you expect?
### Phase 2: Suitability Check
Evaluate against Claude Skill criteria:
| Criterion | Question to Ask |
|-----------|-----------------|
| Clear trigger | When exactly should this skill activate? |
| Focused scope | Can you describe 1-3 core functions? |
| Reusable resources | What scripts, templates, or references are needed? |
| Domain knowledge | What specialized knowledge does Claude lack? |
| Clear boundaries | How does this differ from existing skills? |
**Decision**: If ≥3 criteria pass → proceed. Otherwise, suggest alternatives.
### Phase 3: Requirements Definition
Guide user through structured Q&A:
```
Q1. 스킬 목적과 핵심 기능은 무엇인가요?
(What is the skill's purpose and core functions?)
Q2. 어떤 상황에서 이 스킬이 트리거되어야 하나요?
(When should this skill be triggered?)
Q3. 필요한 외부 도구나 API가 있나요?
(Any external tools or APIs needed?)
Q4. 기대하는 출력 형식은 무엇인가요?
(What output format do you expect?)
Q5. Desktop, Code, 또는 Both 환경이 필요한가요?
(Which environment: Desktop, Code, or Both?)
```
### Phase 4: Skill Generation
Generate skill structure following OurDigital standards:
```
XX-ourdigital-{skill-name}/
├── desktop/
│ └── SKILL.md # Desktop version
├── code/
│ └── SKILL.md # Code version (CLAUDE.md pattern)
├── shared/
│ ├── references/ # Common documentation
│ ├── templates/ # Shared templates
│ └── scripts/ # Utility scripts
├── docs/
│ ├── CHANGELOG.md # Version history
│ └── logs/ # Update logs
└── README.md # Overview
```
### Phase 5: Validation
Before finalizing, verify:
- [ ] YAML frontmatter includes "ourdigital" trigger keywords
- [ ] Description clearly states activation conditions
- [ ] Body content is 800-1,200 words
- [ ] shared/ resources are properly referenced
- [ ] No overlap with existing ourdigital skills
### Phase 6: Notion Sync
Record to Working with AI database:
- **Database**: f8f19ede-32bd-43ac-9f60-0651f6f40afe
- **Properties**:
- Name: `ourdigital-{skill-name} v{version}`
- Status: In progress → Done
- AI used: Claude Desktop
- AI summary: Brief skill description
## YAML Frontmatter Template
```yaml
---
name: ourdigital-{skill-name}
description: |
[Purpose summary]
Activated when user includes "ourdigital" keyword.
Triggers:
- "ourdigital {keyword1}", "ourdigital {keyword2}"
Features:
- Feature 1
- Feature 2
version: "1.0"
author: OurDigital
environment: Desktop | Code | Both
---
```
## Skill Numbering
| Range | Category |
|-------|----------|
| 01-09 | OurDigital Core (brand, blog, journal, research, etc.) |
| 10 | Meta (skill-creator) |
| 11-19 | SEO Tools |
| 20-29 | GTM/Analytics Tools |
| 31-39 | Notion Tools |
| 40-49 | Jamie Clinic Tools |
## Reference Files
- `shared/references/suitability-criteria.md` - Skill evaluation criteria
- `shared/references/skill-patterns.md` - Common patterns
- `shared/templates/skill-template/` - Blank skill template
## Quick Commands
| Command | Action |
|---------|--------|
| "ourdigital 스킬 적합성" | Run suitability check only |
| "ourdigital 스킬 생성" | Full creation workflow |
| "ourdigital 스킬 검증" | Validate existing skill |

View File

@@ -0,0 +1,26 @@
# Changelog
All notable changes to ourdigital-skill-creator will be documented here.
## [1.0.0] - 2026-01-31
### Added
- Initial skill creation
- Desktop and Code versions with YAML frontmatter
- Interactive Q&A workflow for requirements gathering
- Skill suitability evaluation criteria
- Directory structure scaffolding scripts
- Validation script for skill structure checking
- Skill patterns and templates reference
### Files
- `desktop/SKILL.md` - Claude Desktop version
- `code/SKILL.md` - Claude Code version
- `shared/references/suitability-criteria.md`
- `shared/references/skill-patterns.md`
- `shared/templates/SKILL-TEMPLATE.md`
- `shared/scripts/init_skill.py`
- `shared/scripts/validate_skill.py`
### Notion Ref
- (To be synced)

View File

@@ -0,0 +1,203 @@
# OurDigital Skill Patterns
Common patterns and best practices for OurDigital Claude Skills.
## Directory Structure Pattern
```
XX-ourdigital-{name}/
├── code/
│ └── SKILL.md # Claude Code version
├── desktop/
│ └── SKILL.md # Claude Desktop version
├── shared/
│ ├── references/ # Documentation
│ ├── templates/ # Reusable templates
│ └── scripts/ # Utility scripts
├── docs/
│ ├── CHANGELOG.md # Version history
│ └── logs/ # Update logs
└── README.md # Overview
```
## YAML Frontmatter Pattern
```yaml
---
name: ourdigital-{skill-name}
description: |
[One-line purpose statement]
Activated with "ourdigital" keyword.
Triggers:
- "ourdigital {keyword1}", "ourdigital {keyword2}"
- "ourdigital-{skill-name} {action}"
Features:
- Feature 1 description
- Feature 2 description
version: "1.0"
author: OurDigital
environment: Desktop | Code | Both
dependencies:
python: ">=3.11"
packages: ["package1", "package2"]
---
```
## Workflow Patterns
### Linear Workflow
```
Phase 1 → Phase 2 → Phase 3 → Output
```
Example: ourdigital-blog
```
Topic Input → Research → Draft → SEO Meta → Export
```
### Interactive Q&A Workflow
```
Ask Q1 → Get A1 → Ask Q2 → Get A2 → Process → Output
```
Example: ourdigital-skill-creator
```
Purpose? → Triggers? → Tools? → Output? → Generate
```
### Multi-Output Workflow
```
Input → Process → Output A
└→ Output B
└→ Output C
```
Example: ourdigital-designer
```
Brief → Analyze → DALL-E prompt
└→ Midjourney prompt
└→ Figma spec
```
## Trigger Patterns
### Korean + English Pairs
```yaml
Triggers:
- "ourdigital 블로그", "ourdigital blog"
- "ourdigital 작성", "ourdigital write"
```
### Action-Based
```yaml
Triggers:
- "ourdigital create {type}"
- "ourdigital generate {type}"
- "ourdigital check {type}"
```
### Skill Name Direct
```yaml
Triggers:
- "ourdigital-blog 초안"
- "ourdigital-designer 프롬프트"
```
## Output Patterns
### File Export
```markdown
## Output
Export to:
- iCloud/Ulysses folder: `.md` files
- Google Drive: `.docx`, `.pptx`
- Local: `./output/`
```
### Notion Integration
```markdown
## Notion Save
Database: Working with AI
Properties:
- Name: [Output title]
- Status: Done
- AI used: Claude Code
```
### Artifact Generation
```markdown
## Artifact
Generate HTML artifact with:
- Structured sections
- Styled formatting
- Export options
```
## Reference Patterns
### Style Guide Reference
```markdown
See `shared/references/style-guide.md` for:
- Tone and voice
- Terminology
- Formatting rules
```
### API Config Reference
```markdown
See `shared/references/api-config.md` for:
- Endpoint URLs
- Authentication
- Rate limits
```
### Template Reference
```markdown
Use `shared/templates/{template}.md` as base structure.
```
## Version Numbering
```
Major.Minor.Patch
1.0.0 - Initial release
1.1.0 - New feature added
1.1.1 - Bug fix
2.0.0 - Breaking change
```
## Changelog Pattern
```markdown
## [1.1.0] - 2026-01-31
### Added
- New feature X
### Changed
- Updated behavior Y
### Fixed
- Bug in Z
### Notion Ref
- https://notion.so/page-id
```

View File

@@ -0,0 +1,105 @@
# Skill Suitability Criteria
Evaluation criteria for determining if a need should become an OurDigital Claude Skill.
## Core Criteria
### 1. Clear Trigger (Required)
The skill must have an unambiguous activation condition.
**OurDigital Rule**: Must include "ourdigital" keyword to avoid conflicts with other skills.
| Good Triggers | Bad Triggers |
|---------------|--------------|
| "ourdigital 블로그 작성" | "블로그 써줘" |
| "ourdigital research prompt" | "research this" |
| "ourdigital 스킬 만들기" | "make a skill" |
### 2. Focused Scope
Each skill should do 1-3 things well (Unix philosophy).
**Word Limit**: SKILL.md body should be 800-1,200 words.
| Good Scope | Over-scoped |
|------------|-------------|
| Blog draft generation + SEO meta | Blog + Social + Email + Analytics |
| Visual prompt creation | Design + Development + Deployment |
### 3. Reusable Resources
Skill should bundle valuable resources worth maintaining.
| Resource Type | Examples |
|---------------|----------|
| Scripts | `export_to_ulysses.py`, `sync_notion.py` |
| Templates | `blog-template.md`, `research-plan.md` |
| References | `style-guide.md`, `api-config.md` |
| Assets | `brand-colors.json`, `prompt-library.md` |
### 4. Domain Knowledge
Skill should encode knowledge Claude doesn't have natively.
| Good Domain Knowledge | Not Skill-Worthy |
|-----------------------|------------------|
| OurDigital brand voice rules | Generic writing tips |
| Ghost CMS API specifics | Standard markdown |
| Jamie clinic terminology | Common Korean |
### 5. Clear Boundaries
Skill should not overlap with existing skills.
**Check Against**:
- Other ourdigital-* skills
- Existing custom-skills (SEO, GTM, Jamie, etc.)
- Built-in Claude capabilities
## Scoring Matrix
| Criterion | Weight | Score (0-2) |
|-----------|--------|-------------|
| Clear trigger | 25% | |
| Focused scope | 20% | |
| Reusable resources | 20% | |
| Domain knowledge | 20% | |
| Clear boundaries | 15% | |
**Threshold**: Score ≥ 1.2 (60%) to proceed with skill creation.
## Decision Flow
```
Is there a clear "ourdigital" trigger?
├── No → Suggest using generic Claude or other skill
└── Yes ↓
Is scope focused (1-3 functions)?
├── No → Split into multiple skills
└── Yes ↓
Are there reusable resources?
├── No → Consider if prompt is sufficient
└── Yes ↓
Does it encode domain knowledge?
├── No → May not need a skill
└── Yes ↓
No overlap with existing skills?
├── No → Merge with existing or differentiate
└── Yes → CREATE THE SKILL
```
## Alternatives to Skills
If criteria not met, consider:
| Alternative | When to Use |
|-------------|-------------|
| CLAUDE.md directive | Project-specific instructions |
| Prompt library | Reusable prompts without structure |
| MCP tool | API integration without workflow |
| Existing skill extension | Adding to current skill |

View File

@@ -0,0 +1,215 @@
#!/usr/bin/env python3
"""
Initialize a new OurDigital skill with standard directory structure.
Usage:
python init_skill.py {skill-name} --number XX
python init_skill.py blog --number 02
"""
import argparse
import os
from pathlib import Path
from datetime import datetime
SKILL_TEMPLATE = '''---
name: ourdigital-{name}
description: |
{description}
Activated with "ourdigital" keyword.
Triggers:
- "ourdigital {name}", "ourdigital {trigger}"
Features:
- {feature}
version: "1.0"
author: OurDigital
environment: {environment}
---
# OurDigital {title}
{description}
## Activation
Only activate when user includes "ourdigital" keyword:
- "ourdigital {trigger}"
## Workflow
### Phase 1: Input
Gather requirements from user.
### Phase 2: Process
Execute core functionality.
### Phase 3: Output
Deliver results.
## Quick Commands
| Command | Action |
|---------|--------|
| "ourdigital {name}" | Main action |
'''
CHANGELOG_TEMPLATE = '''# Changelog
All notable changes to this skill will be documented in this file.
## [1.0.0] - {date}
### Added
- Initial skill creation
- Desktop and Code versions
- Basic workflow implementation
### Notion Ref
- (To be added after sync)
'''
README_TEMPLATE = '''# OurDigital {title}
{description}
## Installation
This skill is part of the OurDigital custom skills package.
## Usage
### Claude Desktop
The skill activates when you mention "ourdigital {name}".
### Claude Code
```bash
# The skill activates via SKILL.md directive
```
## Structure
```
{number}-ourdigital-{name}/
├── code/SKILL.md
├── desktop/SKILL.md
├── shared/
│ └── references/
├── docs/
│ └── CHANGELOG.md
└── README.md
```
## Version
- Current: 1.0.0
- Author: OurDigital
'''
def create_skill(name: str, number: str, description: str = "", environment: str = "Both"):
"""Create a new skill directory structure."""
base_path = Path(__file__).parent.parent.parent.parent
skill_dir = base_path / f"{number}-ourdigital-{name}"
if skill_dir.exists():
print(f"Skill directory already exists: {skill_dir}")
return False
# Create directories
dirs = [
skill_dir / "code",
skill_dir / "desktop",
skill_dir / "shared" / "references",
skill_dir / "shared" / "templates",
skill_dir / "shared" / "scripts",
skill_dir / "docs" / "logs",
]
for d in dirs:
d.mkdir(parents=True, exist_ok=True)
print(f"Created: {d}")
# Title case for display
title = name.replace("-", " ").title()
trigger = name.replace("-", " ")
feature = f"Core {title} functionality"
date = datetime.now().strftime("%Y-%m-%d")
if not description:
description = f"OurDigital {title} skill for Claude."
# Create SKILL.md for desktop
desktop_skill = SKILL_TEMPLATE.format(
name=name,
title=title,
description=description,
trigger=trigger,
feature=feature,
environment="Desktop"
)
(skill_dir / "desktop" / "SKILL.md").write_text(desktop_skill)
print(f"Created: desktop/SKILL.md")
# Create SKILL.md for code
code_skill = SKILL_TEMPLATE.format(
name=name,
title=title,
description=description,
trigger=trigger,
feature=feature,
environment="Code"
)
(skill_dir / "code" / "SKILL.md").write_text(code_skill)
print(f"Created: code/SKILL.md")
# Create CHANGELOG.md
changelog = CHANGELOG_TEMPLATE.format(date=date)
(skill_dir / "docs" / "CHANGELOG.md").write_text(changelog)
print(f"Created: docs/CHANGELOG.md")
# Create README.md
readme = README_TEMPLATE.format(
title=title,
name=name,
number=number,
description=description
)
(skill_dir / "README.md").write_text(readme)
print(f"Created: README.md")
print(f"\nSkill created successfully: {skill_dir}")
return True
def main():
parser = argparse.ArgumentParser(description="Initialize a new OurDigital skill")
parser.add_argument("name", help="Skill name (e.g., 'blog', 'designer')")
parser.add_argument("--number", required=True, help="Skill number (e.g., '02', '07')")
parser.add_argument("--description", default="", help="Skill description")
parser.add_argument("--environment", default="Both",
choices=["Desktop", "Code", "Both"],
help="Target environment")
args = parser.parse_args()
success = create_skill(
name=args.name,
number=args.number,
description=args.description,
environment=args.environment
)
return 0 if success else 1
if __name__ == "__main__":
exit(main())

View File

@@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""
Validate an OurDigital skill structure and content.
Usage:
python validate_skill.py {skill-directory}
python validate_skill.py 02-ourdigital-blog
"""
import argparse
import re
from pathlib import Path
class SkillValidator:
def __init__(self, skill_path: Path):
self.skill_path = skill_path
self.errors = []
self.warnings = []
def validate(self) -> bool:
"""Run all validations."""
self._check_directory_structure()
self._check_skill_files()
self._check_frontmatter()
self._check_content_length()
self._check_ourdigital_triggers()
return len(self.errors) == 0
def _check_directory_structure(self):
"""Verify required directories exist."""
required_dirs = [
"code",
"desktop",
]
recommended_dirs = [
"shared",
"docs",
]
for d in required_dirs:
if not (self.skill_path / d).is_dir():
self.errors.append(f"Missing required directory: {d}/")
for d in recommended_dirs:
if not (self.skill_path / d).is_dir():
self.warnings.append(f"Missing recommended directory: {d}/")
def _check_skill_files(self):
"""Verify SKILL.md files exist."""
skill_files = [
"code/SKILL.md",
"desktop/SKILL.md",
]
for f in skill_files:
if not (self.skill_path / f).is_file():
self.errors.append(f"Missing required file: {f}")
def _check_frontmatter(self):
"""Verify YAML frontmatter in SKILL.md files."""
for env in ["code", "desktop"]:
skill_file = self.skill_path / env / "SKILL.md"
if not skill_file.is_file():
continue
content = skill_file.read_text()
# Check for YAML frontmatter
if not content.startswith("---"):
self.errors.append(f"{env}/SKILL.md: Missing YAML frontmatter")
continue
# Check required fields
required_fields = ["name", "description", "version", "author", "environment"]
for field in required_fields:
if f"{field}:" not in content.split("---")[1]:
self.warnings.append(f"{env}/SKILL.md: Missing frontmatter field '{field}'")
def _check_content_length(self):
"""Verify SKILL.md body is within word limit."""
for env in ["code", "desktop"]:
skill_file = self.skill_path / env / "SKILL.md"
if not skill_file.is_file():
continue
content = skill_file.read_text()
# Extract body (after frontmatter)
parts = content.split("---")
if len(parts) >= 3:
body = "---".join(parts[2:])
word_count = len(body.split())
if word_count < 200:
self.warnings.append(
f"{env}/SKILL.md: Body too short ({word_count} words, recommended 800-1200)"
)
elif word_count > 1500:
self.warnings.append(
f"{env}/SKILL.md: Body too long ({word_count} words, recommended 800-1200)"
)
def _check_ourdigital_triggers(self):
"""Verify 'ourdigital' keyword in triggers."""
for env in ["code", "desktop"]:
skill_file = self.skill_path / env / "SKILL.md"
if not skill_file.is_file():
continue
content = skill_file.read_text().lower()
# Check for ourdigital in description/triggers
if "ourdigital" not in content:
self.errors.append(
f"{env}/SKILL.md: Missing 'ourdigital' keyword in triggers"
)
def report(self):
"""Print validation report."""
print(f"\nValidation Report: {self.skill_path.name}")
print("=" * 50)
if self.errors:
print(f"\nERRORS ({len(self.errors)}):")
for e in self.errors:
print(f" [X] {e}")
if self.warnings:
print(f"\nWARNINGS ({len(self.warnings)}):")
for w in self.warnings:
print(f" [!] {w}")
if not self.errors and not self.warnings:
print("\n All checks passed!")
print("\n" + "=" * 50)
status = "PASS" if not self.errors else "FAIL"
print(f"Status: {status}")
return not self.errors
def main():
parser = argparse.ArgumentParser(description="Validate an OurDigital skill")
parser.add_argument("skill_dir", help="Skill directory name or path")
args = parser.parse_args()
# Handle relative or absolute path
skill_path = Path(args.skill_dir)
if not skill_path.is_absolute():
# Try relative to custom-skills directory
base_path = Path(__file__).parent.parent.parent.parent
skill_path = base_path / args.skill_dir
if not skill_path.is_dir():
print(f"Error: Skill directory not found: {skill_path}")
return 1
validator = SkillValidator(skill_path)
validator.validate()
success = validator.report()
return 0 if success else 1
if __name__ == "__main__":
exit(main())

View File

@@ -0,0 +1,56 @@
---
name: ourdigital-{skill-name}
description: |
{Brief description of the skill's purpose}
Activated with "ourdigital" keyword.
Triggers:
- "ourdigital {trigger1}", "ourdigital {trigger2}"
- "ourdigital-{skill-name} {action}"
Features:
- {Feature 1}
- {Feature 2}
version: "1.0"
author: OurDigital
environment: {Desktop | Code | Both}
---
# OurDigital {Skill Name}
{One-paragraph description of what this skill does.}
## Activation
Only activate when user includes "ourdigital" keyword:
- "ourdigital {example trigger 1}"
- "ourdigital {example trigger 2}"
## Workflow
### Phase 1: {Phase Name}
{Description of first phase}
### Phase 2: {Phase Name}
{Description of second phase}
### Phase 3: {Phase Name}
{Description of third phase}
## Output
{Describe the expected outputs}
## References
- `shared/references/{file}.md` - {Description}
## Quick Commands
| Command | Action |
|---------|--------|
| "ourdigital {cmd1}" | {Action 1} |
| "ourdigital {cmd2}" | {Action 2} |