From 0dcca3f80cc44c8175f7400e6ac3c8c36cac88b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:22:57 +0000 Subject: [PATCH 1/9] feat: add create-skill skill for authoring agent skills (#93) Add a new /create-skill command that guides AI agents through creating skills following the AgentSkills.io specification and SudoLang syntax. Includes size validation, verb-form naming conventions, and a skill template structure. - ai/skills/create-skill.mdc: main skill guide with process, size constraints, authoring guidelines, and example structure - ai/commands/create-skill.md: command entry point - Register command in please.mdc and agent-orchestrator.mdc https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/commands/create-skill.md | 8 +++ ai/commands/index.md | 6 ++ ai/rules/agent-orchestrator.mdc | 1 + ai/rules/please.mdc | 1 + ai/skills/create-skill.mdc | 115 ++++++++++++++++++++++++++++++++ ai/skills/index.md | 12 ++++ 6 files changed, 143 insertions(+) create mode 100644 ai/commands/create-skill.md create mode 100644 ai/skills/create-skill.mdc create mode 100644 ai/skills/index.md diff --git a/ai/commands/create-skill.md b/ai/commands/create-skill.md new file mode 100644 index 0000000..12f318f --- /dev/null +++ b/ai/commands/create-skill.md @@ -0,0 +1,8 @@ +## ๐Ÿ› ๏ธ Create Skill + +Use create-skill.mdc to create a new agent skill following the AgentSkills.io specification and SudoLang syntax. + +Constraints { + Begin by asking the user clarifying questions about the skill's purpose, inputs, outputs, and constraints. + Before beginning, read and respect the constraints in please.mdc. +} diff --git a/ai/commands/index.md b/ai/commands/index.md index f728833..1a8767a 100644 --- a/ai/commands/index.md +++ b/ai/commands/index.md @@ -10,6 +10,12 @@ This index provides an overview of the contents in this directory. *No description available* +### create-skill + +**File:** `create-skill.md` + +*No description available* + ### discover **File:** `discover.md` diff --git a/ai/rules/agent-orchestrator.mdc b/ai/rules/agent-orchestrator.mdc index 16703ec..58ec331 100644 --- a/ai/rules/agent-orchestrator.mdc +++ b/ai/rules/agent-orchestrator.mdc @@ -24,6 +24,7 @@ Agents { javascript-io-network-effects: when you need to make network requests or invoke side-effects, use this guide for saga pattern implementation ui: when building user interfaces and user experiences, use this guide for beautiful and friendly UI/UX design requirements: when writing functional requirements for a user story, use this guide for functional requirement specification + create-skill: when creating a new agent skill, use this guide for AgentSkills.io specification and SudoLang skill authoring } const taskPrompt = "# Guides\n\nRead each of the following guides for important context, and follow their instructions carefully: ${list guide file refs in markdown format}\n\n# User Prompt\n\n${prompt}" diff --git a/ai/rules/please.mdc b/ai/rules/please.mdc index 8b2b3db..62dfd49 100644 --- a/ai/rules/please.mdc +++ b/ai/rules/please.mdc @@ -43,6 +43,7 @@ Commands { ๐Ÿ”ฌ /review - conduct a thorough code review focusing on code quality, best practices, and adherence to project standards ๐Ÿงช /user-test - use user-testing.mdc to generate human and AI agent test scripts from user journeys ๐Ÿค– /run-test - execute AI agent test script in real browser with screenshots + ๐Ÿ› ๏ธ /create-skill - create a new agent skill using AgentSkills.io spec and SudoLang } Constraints { diff --git a/ai/skills/create-skill.mdc b/ai/skills/create-skill.mdc new file mode 100644 index 0000000..502ebb8 --- /dev/null +++ b/ai/skills/create-skill.mdc @@ -0,0 +1,115 @@ +--- +description: Create a new agent skill using the AgentSkills.io specification and SudoLang syntax +alwaysApply: false +--- +# Create Skill + +Create agent skills following the AgentSkills.io specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). + +## Skill Structure + +SkillTemplate { + frontmatter: YAML metadata block + body: Markdown + SudoLang content +} + +Frontmatter { + description: String // brief, under 100 tokens + alwaysApply: false +} + +## Syntax Reference + +Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang conventions. Use markdown and natural language primarily. Employ SudoLang syntax for interfaces and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. + +## Process + +createSkill(userRequest) { + 1. Gather Requirements - ask clarifying questions about the skill's purpose, inputs, outputs, and constraints + 2. Name the skill using verb form (e.g., `format-code`, `generate-report`) + 3. Draft the skill .mdc file following SkillTemplate + 4. Validate the skill against size constraints + 5. Write the skill to `$projectRoot/ai/skills/${skillName}.mdc` + 6. Report size metrics to the user +} + +## Size Constraints + +SizeThresholds { + frontmatter: < 100 tokens + body: < 160 lines, < 5000 tokens (ideal) +} + +validateSize(skillContent) { + metrics = { + frontmatterTokens: estimateTokens(frontmatter) + bodyLines: countLines(body) + bodyTokens: estimateTokens(body) + } + + warnings = [] + if (metrics.frontmatterTokens >= 100) warnings.push("Frontmatter exceeds 100 token limit") + if (metrics.bodyLines >= 160) warnings.push("Body exceeds 160 line guideline") + if (metrics.bodyTokens >= 5000) warnings.push("Body exceeds 5000 token guideline") + + report metrics and warnings to user +} + +// Rough token estimate: ~4 characters per token for English text +estimateTokens(text) { + "~${Math.ceil(text.length / 4)} tokens" +} + +## Skill Authoring Guidelines + +Constraints { + Start with a clear one-line purpose statement + Use markdown headings for major sections + Use SudoLang interfaces for structured data definitions + Use SudoLang functions for process flows and composition + Use SudoLang constraints blocks for rules and limitations + Keep the skill focused on a single responsibility + Prefer natural language for instructions; SudoLang for structure + Include a Commands section if the skill has user-invocable actions + Always validate size after drafting +} + +## Example Skill Structure + +``` +--- +description: Brief description of what the skill does +alwaysApply: false +--- +# Skill Name + +One-line purpose statement. + +## Interfaces + +DataModel { + field1: Type + field2: Type +} + +## Process + +mainFunction(input) { + 1. Step one + 2. Step two + 3. Step three +} + +Constraints { + Constraint one + Constraint two +} + +Commands { + /command-name - description +} +``` + +Commands { + /create-skill - create a new agent skill +} diff --git a/ai/skills/index.md b/ai/skills/index.md new file mode 100644 index 0000000..128e506 --- /dev/null +++ b/ai/skills/index.md @@ -0,0 +1,12 @@ +# skills + +This index provides an overview of the contents in this directory. + +## Files + +### Create Skill + +**File:** `create-skill.mdc` + +Create a new agent skill using the AgentSkills.io specification and SudoLang syntax + From 7e1e8b7822892e29987f79b95d3f43d8ec507c68 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:23:39 +0000 Subject: [PATCH 2/9] chore: update auto-generated index files for skills directory https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ai/index.md b/ai/index.md index 0419529..6654e0d 100644 --- a/ai/index.md +++ b/ai/index.md @@ -12,3 +12,7 @@ See [`commands/index.md`](./commands/index.md) for contents. See [`rules/index.md`](./rules/index.md) for contents. +### ๐Ÿ“ skills/ + +See [`skills/index.md`](./skills/index.md) for contents. + From d15830150d33e306d7d0fd9a115dbde6bbd96d06 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:25:17 +0000 Subject: [PATCH 3/9] feat: enhance create-skill with discovery, research, validation, and plan review - Scan ai/ and aidd-custom/ for related skills to avoid overlap - Web search for best practices on the skill topic - Present plan to user for approval before drafting - Run skills-ref validate with symbolic JS size checker - Report warnings when frontmatter > 100 tokens or body > 160 LoC https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill.mdc | 97 +++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/ai/skills/create-skill.mdc b/ai/skills/create-skill.mdc index 502ebb8..e89c6fb 100644 --- a/ai/skills/create-skill.mdc +++ b/ai/skills/create-skill.mdc @@ -26,38 +26,89 @@ Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang conventions. Use markd createSkill(userRequest) { 1. Gather Requirements - ask clarifying questions about the skill's purpose, inputs, outputs, and constraints - 2. Name the skill using verb form (e.g., `format-code`, `generate-report`) - 3. Draft the skill .mdc file following SkillTemplate - 4. Validate the skill against size constraints - 5. Write the skill to `$projectRoot/ai/skills/${skillName}.mdc` - 6. Report size metrics to the user + 2. Discover Related Skills - scan `ai/` and `aidd-custom/` for existing skills that overlap or could be leveraged + 3. Research Best Practices - use web search to find best practices for the skill topic + 4. Name the skill using verb form (e.g., `format-code`, `generate-report`) + 5. Plan - draft a skill plan incorporating research and related skill analysis + 6. Present Plan - show the plan to the user and ask if any changes are required before proceeding + 7. Draft the skill .mdc file following SkillTemplate + 8. Validate the skill with `skills-ref validate` + 9. Write the skill to `$projectRoot/ai/skills/${skillName}.mdc` + 10. Report size metrics to the user } -## Size Constraints +## Discover Related Skills -SizeThresholds { - frontmatter: < 100 tokens - body: < 160 lines, < 5000 tokens (ideal) +discoverRelatedSkills(skillTopic) { + searchPaths = ["$projectRoot/ai/", "$projectRoot/aidd-custom/"] + for each (path in searchPaths) { + scan for .mdc and .md files + read frontmatter descriptions + identify skills with overlapping purpose or complementary functionality + } + report: + - Related skills found and their purpose + - How existing skills can be leveraged or composed with the new skill + - Potential overlap to avoid duplication } -validateSize(skillContent) { - metrics = { - frontmatterTokens: estimateTokens(frontmatter) - bodyLines: countLines(body) - bodyTokens: estimateTokens(body) - } +## Research Best Practices - warnings = [] - if (metrics.frontmatterTokens >= 100) warnings.push("Frontmatter exceeds 100 token limit") - if (metrics.bodyLines >= 160) warnings.push("Body exceeds 160 line guideline") - if (metrics.bodyTokens >= 5000) warnings.push("Body exceeds 5000 token guideline") +researchTopic(skillTopic) { + use web search to find best practices, patterns, and conventions for $skillTopic + summarize key findings relevant to skill authoring + incorporate findings into the skill plan +} - report metrics and warnings to user +## Plan Presentation + +presentPlan(skillPlan) { + show the user: + - Skill name and purpose + - Related skills discovered and how they will be leveraged + - Best practices found via research + - Proposed structure and sections + - Any size concerns + ask the user if any changes are required before proceeding + await explicit user approval } -// Rough token estimate: ~4 characters per token for English text -estimateTokens(text) { - "~${Math.ceil(text.length / 4)} tokens" +## Validation + +After creating the skill file, run the symbolic validator: + +```javascript +// Run: skills-ref validate ./path-to-skill.mdc +// Then compute and report size metrics: + +const fs = require("fs"); +const content = fs.readFileSync(skillPath, "utf-8"); +const fmMatch = content.match(/^---\n([\s\S]*?)\n---/); +const frontmatter = fmMatch ? fmMatch[1] : ""; +const body = fmMatch ? content.slice(fmMatch[0].length).trim() : content; + +const metrics = { + frontmatterTokens: Math.ceil(frontmatter.length / 4), + bodyLines: body.split("\n").length, + bodyTokens: Math.ceil(body.length / 4), +}; + +const warnings = []; +if (metrics.frontmatterTokens >= 100) + warnings.push("โš ๏ธ Frontmatter exceeds 100 token limit"); +if (metrics.bodyLines >= 160) + warnings.push("โš ๏ธ Body exceeds 160 line guideline"); +if (metrics.bodyTokens >= 5000) + warnings.push("โš ๏ธ Body exceeds 5000 token guideline"); + +console.log("Size metrics:", metrics); +if (warnings.length) console.log("Warnings:", warnings); +else console.log("โœ… All size checks passed"); +``` + +SizeThresholds { + frontmatter: < 100 tokens + body: < 160 lines, < 5000 tokens (ideal) } ## Skill Authoring Guidelines From c8cd8e3405967a3a7804dce6e7d5b701d6bff486 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:27:41 +0000 Subject: [PATCH 4/9] fix: align create-skill with AgentSkills.io specification Rewrite create-skill.mdc to comply with the official AgentSkills.io spec: - Skills are directories with SKILL.md (not standalone .mdc files) - Frontmatter uses name + description (required), plus optional license, compatibility, metadata, and allowed-tools fields - Name validation: lowercase alphanumeric + hyphens, 1-64 chars, no consecutive hyphens, must match parent directory name - Progressive disclosure: ~100 token metadata, <5000 token instructions - Output to $projectRoot/aidd-custom/${skillName}/SKILL.md - Symbolic JS validator includes name validation and tiered size warnings (160 line guideline, 500 line spec limit, 5000 token guideline) - Support for optional scripts/, references/, assets/ directories https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill.mdc | 168 ++++++++++++++++++++++--------------- ai/skills/index.md | 2 +- 2 files changed, 102 insertions(+), 68 deletions(-) diff --git a/ai/skills/create-skill.mdc b/ai/skills/create-skill.mdc index e89c6fb..5e5a467 100644 --- a/ai/skills/create-skill.mdc +++ b/ai/skills/create-skill.mdc @@ -1,26 +1,55 @@ --- -description: Create a new agent skill using the AgentSkills.io specification and SudoLang syntax +description: Create a new agent skill following the AgentSkills.io specification alwaysApply: false --- # Create Skill -Create agent skills following the AgentSkills.io specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). +Create agent skills following the [AgentSkills.io](https://agentskills.io/specification) specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). -## Skill Structure +## AgentSkills.io Skill Structure -SkillTemplate { - frontmatter: YAML metadata block - body: Markdown + SudoLang content -} +A skill is a directory containing a `SKILL.md` file with optional supporting directories: + +``` +skill-name/ +โ”œโ”€โ”€ SKILL.md # Required: YAML frontmatter + markdown instructions +โ”œโ”€โ”€ scripts/ # Optional: executable code agents can run +โ”œโ”€โ”€ references/ # Optional: additional documentation loaded on demand +โ””โ”€โ”€ assets/ # Optional: templates, images, data files +``` + +### Frontmatter Schema + +```yaml +--- +name: skill-name # Required: 1-64 chars, lowercase + hyphens, must match directory name +description: ... # Required: 1-1024 chars, what it does and when to use it +license: Apache-2.0 # Optional +compatibility: ... # Optional: 1-500 chars, environment requirements +metadata: # Optional: arbitrary key-value pairs + author: org-name + version: "1.0" +allowed-tools: Bash Read # Optional: space-delimited pre-approved tools (experimental) +--- +``` -Frontmatter { - description: String // brief, under 100 tokens - alwaysApply: false +NameValidation { + length: 1-64 characters + charset: lowercase alphanumeric + hyphens (a-z, 0-9, -) + no leading or trailing hyphens + no consecutive hyphens (--) + must match parent directory name } +### Progressive Disclosure + +Metadata (~100 tokens) => loaded at startup for all skills +Instructions (< 5000 tokens) => loaded when skill is activated +Resources (as needed) => loaded only when required + ## Syntax Reference -Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang conventions. Use markdown and natural language primarily. Employ SudoLang syntax for interfaces and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. +Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang conventions. Use markdown and natural language primarily. Employ SudoLang for interfaces and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. ## Process @@ -28,13 +57,13 @@ createSkill(userRequest) { 1. Gather Requirements - ask clarifying questions about the skill's purpose, inputs, outputs, and constraints 2. Discover Related Skills - scan `ai/` and `aidd-custom/` for existing skills that overlap or could be leveraged 3. Research Best Practices - use web search to find best practices for the skill topic - 4. Name the skill using verb form (e.g., `format-code`, `generate-report`) + 4. Name the skill using verb form and NameValidation rules 5. Plan - draft a skill plan incorporating research and related skill analysis 6. Present Plan - show the plan to the user and ask if any changes are required before proceeding - 7. Draft the skill .mdc file following SkillTemplate - 8. Validate the skill with `skills-ref validate` - 9. Write the skill to `$projectRoot/ai/skills/${skillName}.mdc` - 10. Report size metrics to the user + 7. Draft the SKILL.md following the AgentSkills.io spec + 8. Write the skill to `$projectRoot/aidd-custom/${skillName}/SKILL.md` + 9. Validate with `skills-ref validate` and the symbolic size checker + 10. Report size metrics and validation results to the user } ## Discover Related Skills @@ -42,7 +71,7 @@ createSkill(userRequest) { discoverRelatedSkills(skillTopic) { searchPaths = ["$projectRoot/ai/", "$projectRoot/aidd-custom/"] for each (path in searchPaths) { - scan for .mdc and .md files + scan for SKILL.md, .mdc, and .md files read frontmatter descriptions identify skills with overlapping purpose or complementary functionality } @@ -67,7 +96,8 @@ presentPlan(skillPlan) { - Skill name and purpose - Related skills discovered and how they will be leveraged - Best practices found via research - - Proposed structure and sections + - Proposed SKILL.md structure and sections + - Whether scripts/, references/, or assets/ directories are needed - Any size concerns ask the user if any changes are required before proceeding await explicit user approval @@ -75,17 +105,28 @@ presentPlan(skillPlan) { ## Validation -After creating the skill file, run the symbolic validator: +After creating the skill, run validation and report size metrics: ```javascript -// Run: skills-ref validate ./path-to-skill.mdc -// Then compute and report size metrics: +// 1. Run: skills-ref validate ./path-to-skill-directory +// 2. Then compute and report size metrics: const fs = require("fs"); -const content = fs.readFileSync(skillPath, "utf-8"); -const fmMatch = content.match(/^---\n([\s\S]*?)\n---/); +const path = require("path"); +const skillMd = fs.readFileSync(path.join(skillDir, "SKILL.md"), "utf-8"); +const fmMatch = skillMd.match(/^---\n([\s\S]*?)\n---/); const frontmatter = fmMatch ? fmMatch[1] : ""; -const body = fmMatch ? content.slice(fmMatch[0].length).trim() : content; +const body = fmMatch ? skillMd.slice(fmMatch[0].length).trim() : skillMd; + +// Validate name field +const nameMatch = frontmatter.match(/^name:\s*(.+)$/m); +const name = nameMatch ? nameMatch[1].trim() : ""; +const nameErrors = []; +if (name.length < 1 || name.length > 64) nameErrors.push("Name must be 1-64 characters"); +if (/[^a-z0-9-]/.test(name)) nameErrors.push("Name must be lowercase alphanumeric + hyphens only"); +if (/^-|-$/.test(name)) nameErrors.push("Name must not start or end with hyphen"); +if (/--/.test(name)) nameErrors.push("Name must not contain consecutive hyphens"); +if (name !== path.basename(skillDir)) nameErrors.push("Name must match directory name"); const metrics = { frontmatterTokens: Math.ceil(frontmatter.length / 4), @@ -95,72 +136,65 @@ const metrics = { const warnings = []; if (metrics.frontmatterTokens >= 100) - warnings.push("โš ๏ธ Frontmatter exceeds 100 token limit"); + warnings.push("Frontmatter exceeds 100 token guideline"); if (metrics.bodyLines >= 160) - warnings.push("โš ๏ธ Body exceeds 160 line guideline"); + warnings.push("Body exceeds 160 line guideline"); +if (metrics.bodyLines >= 500) + warnings.push("Body exceeds 500 line spec limit - split into reference files"); if (metrics.bodyTokens >= 5000) - warnings.push("โš ๏ธ Body exceeds 5000 token guideline"); + warnings.push("Body exceeds 5000 token spec guideline"); +console.log("Name validation:", nameErrors.length ? nameErrors : "PASS"); console.log("Size metrics:", metrics); -if (warnings.length) console.log("Warnings:", warnings); -else console.log("โœ… All size checks passed"); +console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); ``` -SizeThresholds { - frontmatter: < 100 tokens - body: < 160 lines, < 5000 tokens (ideal) -} - ## Skill Authoring Guidelines Constraints { - Start with a clear one-line purpose statement - Use markdown headings for major sections - Use SudoLang interfaces for structured data definitions - Use SudoLang functions for process flows and composition - Use SudoLang constraints blocks for rules and limitations + Start with a clear purpose statement in the description field + Use markdown headings for major sections in the body + Include step-by-step instructions, examples, and edge cases Keep the skill focused on a single responsibility - Prefer natural language for instructions; SudoLang for structure - Include a Commands section if the skill has user-invocable actions - Always validate size after drafting + Use SudoLang for interfaces and function composition where token efficiency matters + Prefer natural language for instructions + Move detailed reference material to references/ directory + Keep SKILL.md body under 160 lines ideally, 500 lines max + Always validate after drafting } -## Example Skill Structure +## Example SKILL.md -``` +```markdown --- -description: Brief description of what the skill does -alwaysApply: false +name: format-code +description: Format source code files according to project style guides. Use when code needs formatting, linting fixes, or style consistency checks. +metadata: + author: my-org + version: "1.0" --- -# Skill Name -One-line purpose statement. +# Format Code -## Interfaces +Format source code according to project conventions and style guides. -DataModel { - field1: Type - field2: Type -} +## When to use -## Process +Use this skill when code needs formatting, style fixes, or consistency checks. -mainFunction(input) { - 1. Step one - 2. Step two - 3. Step three -} +## Steps -Constraints { - Constraint one - Constraint two -} +1. Detect the project's formatter configuration +2. Identify files that need formatting +3. Apply formatting rules +4. Report changes made -Commands { - /command-name - description -} +## Edge cases + +- If no formatter config exists, ask the user which style to use +- For mixed-language projects, apply per-language formatters ``` Commands { - /create-skill - create a new agent skill + /create-skill - create a new agent skill following the AgentSkills.io specification } diff --git a/ai/skills/index.md b/ai/skills/index.md index 128e506..11afacd 100644 --- a/ai/skills/index.md +++ b/ai/skills/index.md @@ -8,5 +8,5 @@ This index provides an overview of the contents in this directory. **File:** `create-skill.mdc` -Create a new agent skill using the AgentSkills.io specification and SudoLang syntax +Create a new agent skill following the AgentSkills.io specification From 2d82edf099e54f29050598c6033c0457c99daa2e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:28:59 +0000 Subject: [PATCH 5/9] fix: add spec compliance constraints to prevent common skill authoring mistakes Add explicit constraints section documenting mistakes to avoid when generating new skills: - Must create directory/SKILL.md structure, not standalone files - Must use AgentSkills.io frontmatter fields (name+description), not aidd .mdc fields (alwaysApply, globs) - Must validate name field (lowercase, no consecutive hyphens, match dir) - Must use plain Markdown in SKILL.md body, not SudoLang - Must always run validator and report metrics before success https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill.mdc | 41 +++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/ai/skills/create-skill.mdc b/ai/skills/create-skill.mdc index 5e5a467..0eb1182 100644 --- a/ai/skills/create-skill.mdc +++ b/ai/skills/create-skill.mdc @@ -149,18 +149,41 @@ console.log("Size metrics:", metrics); console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); ``` -## Skill Authoring Guidelines +## Spec Compliance Constraints + +These constraints prevent common mistakes when generating skills. Every generated skill MUST pass all of these checks: Constraints { - Start with a clear purpose statement in the description field - Use markdown headings for major sections in the body - Include step-by-step instructions, examples, and edge cases + // Structure: skills are DIRECTORIES, not standalone files + NEVER create a standalone .mdc or .md file as a skill - always create a directory with SKILL.md inside + The output MUST be `$projectRoot/aidd-custom/${skillName}/SKILL.md` - not a flat file + The file MUST be named exactly `SKILL.md` (uppercase) - not skill.md, not ${name}.mdc + + // Frontmatter: use AgentSkills.io fields, NOT aidd .mdc fields + Frontmatter MUST include `name` and `description` as required fields + NEVER use `alwaysApply`, `globs`, or other non-spec frontmatter fields in generated skills + The `name` field MUST be lowercase alphanumeric + hyphens only (a-z, 0-9, -) + The `name` field MUST match the parent directory name exactly + The `name` field MUST NOT start or end with a hyphen + The `name` field MUST NOT contain consecutive hyphens (--) + The `name` field MUST be 1-64 characters + The `description` field MUST be 1-1024 characters and describe both what the skill does AND when to use it + + // Size: respect progressive disclosure thresholds + Frontmatter metadata MUST stay under ~100 tokens + SKILL.md body SHOULD stay under 160 lines and MUST stay under 500 lines + SKILL.md body SHOULD stay under 5000 tokens + If content exceeds limits, split into references/ directory files + + // Content quality + The body MUST use plain Markdown - not SudoLang (SudoLang is for .mdc rules, not SKILL.md files) + Include recommended sections: when to use, step-by-step instructions, examples, edge cases Keep the skill focused on a single responsibility - Use SudoLang for interfaces and function composition where token efficiency matters - Prefer natural language for instructions - Move detailed reference material to references/ directory - Keep SKILL.md body under 160 lines ideally, 500 lines max - Always validate after drafting + + // Validation: always validate before reporting success + ALWAYS run the symbolic JavaScript validator after creating the skill + ALWAYS run `skills-ref validate` if available + ALWAYS report size metrics and any warnings to the user } ## Example SKILL.md From 2601c617f7fb022ff545d339b60ef3feb7c61640 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:35:56 +0000 Subject: [PATCH 6/9] refactor: restructure create-skill as AgentSkills.io-compliant directory Move from flat ai/skills/create-skill.mdc to proper spec-compliant ai/skills/create-skill/SKILL.md directory structure. The skill now eats its own dog food. - AgentSkills.io frontmatter: name + description + metadata - Proper SudoLang usage: type definitions (SkillName, SkillDescription, TokenCount), typed interfaces (Frontmatter, Skill, SizeMetrics, SkillPlan), pipe composition in createSkill process - Reference productmanager.mdc as SudoLang exemplar (not as a skill) - Update command to reference new path https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/commands/create-skill.md | 2 +- ai/skills/create-skill.mdc | 223 ------------------------------- ai/skills/create-skill/SKILL.md | 229 ++++++++++++++++++++++++++++++++ ai/skills/create-skill/index.md | 12 ++ ai/skills/index.md | 8 +- 5 files changed, 245 insertions(+), 229 deletions(-) delete mode 100644 ai/skills/create-skill.mdc create mode 100644 ai/skills/create-skill/SKILL.md create mode 100644 ai/skills/create-skill/index.md diff --git a/ai/commands/create-skill.md b/ai/commands/create-skill.md index 12f318f..9fbf8e4 100644 --- a/ai/commands/create-skill.md +++ b/ai/commands/create-skill.md @@ -1,6 +1,6 @@ ## ๐Ÿ› ๏ธ Create Skill -Use create-skill.mdc to create a new agent skill following the AgentSkills.io specification and SudoLang syntax. +Use `ai/skills/create-skill/SKILL.md` to create a new agent skill following the AgentSkills.io specification. Constraints { Begin by asking the user clarifying questions about the skill's purpose, inputs, outputs, and constraints. diff --git a/ai/skills/create-skill.mdc b/ai/skills/create-skill.mdc deleted file mode 100644 index 0eb1182..0000000 --- a/ai/skills/create-skill.mdc +++ /dev/null @@ -1,223 +0,0 @@ ---- -description: Create a new agent skill following the AgentSkills.io specification -alwaysApply: false ---- -# Create Skill - -Create agent skills following the [AgentSkills.io](https://agentskills.io/specification) specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). - -## AgentSkills.io Skill Structure - -A skill is a directory containing a `SKILL.md` file with optional supporting directories: - -``` -skill-name/ -โ”œโ”€โ”€ SKILL.md # Required: YAML frontmatter + markdown instructions -โ”œโ”€โ”€ scripts/ # Optional: executable code agents can run -โ”œโ”€โ”€ references/ # Optional: additional documentation loaded on demand -โ””โ”€โ”€ assets/ # Optional: templates, images, data files -``` - -### Frontmatter Schema - -```yaml ---- -name: skill-name # Required: 1-64 chars, lowercase + hyphens, must match directory name -description: ... # Required: 1-1024 chars, what it does and when to use it -license: Apache-2.0 # Optional -compatibility: ... # Optional: 1-500 chars, environment requirements -metadata: # Optional: arbitrary key-value pairs - author: org-name - version: "1.0" -allowed-tools: Bash Read # Optional: space-delimited pre-approved tools (experimental) ---- -``` - -NameValidation { - length: 1-64 characters - charset: lowercase alphanumeric + hyphens (a-z, 0-9, -) - no leading or trailing hyphens - no consecutive hyphens (--) - must match parent directory name -} - -### Progressive Disclosure - -Metadata (~100 tokens) => loaded at startup for all skills -Instructions (< 5000 tokens) => loaded when skill is activated -Resources (as needed) => loaded only when required - -## Syntax Reference - -Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang conventions. Use markdown and natural language primarily. Employ SudoLang for interfaces and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. - -## Process - -createSkill(userRequest) { - 1. Gather Requirements - ask clarifying questions about the skill's purpose, inputs, outputs, and constraints - 2. Discover Related Skills - scan `ai/` and `aidd-custom/` for existing skills that overlap or could be leveraged - 3. Research Best Practices - use web search to find best practices for the skill topic - 4. Name the skill using verb form and NameValidation rules - 5. Plan - draft a skill plan incorporating research and related skill analysis - 6. Present Plan - show the plan to the user and ask if any changes are required before proceeding - 7. Draft the SKILL.md following the AgentSkills.io spec - 8. Write the skill to `$projectRoot/aidd-custom/${skillName}/SKILL.md` - 9. Validate with `skills-ref validate` and the symbolic size checker - 10. Report size metrics and validation results to the user -} - -## Discover Related Skills - -discoverRelatedSkills(skillTopic) { - searchPaths = ["$projectRoot/ai/", "$projectRoot/aidd-custom/"] - for each (path in searchPaths) { - scan for SKILL.md, .mdc, and .md files - read frontmatter descriptions - identify skills with overlapping purpose or complementary functionality - } - report: - - Related skills found and their purpose - - How existing skills can be leveraged or composed with the new skill - - Potential overlap to avoid duplication -} - -## Research Best Practices - -researchTopic(skillTopic) { - use web search to find best practices, patterns, and conventions for $skillTopic - summarize key findings relevant to skill authoring - incorporate findings into the skill plan -} - -## Plan Presentation - -presentPlan(skillPlan) { - show the user: - - Skill name and purpose - - Related skills discovered and how they will be leveraged - - Best practices found via research - - Proposed SKILL.md structure and sections - - Whether scripts/, references/, or assets/ directories are needed - - Any size concerns - ask the user if any changes are required before proceeding - await explicit user approval -} - -## Validation - -After creating the skill, run validation and report size metrics: - -```javascript -// 1. Run: skills-ref validate ./path-to-skill-directory -// 2. Then compute and report size metrics: - -const fs = require("fs"); -const path = require("path"); -const skillMd = fs.readFileSync(path.join(skillDir, "SKILL.md"), "utf-8"); -const fmMatch = skillMd.match(/^---\n([\s\S]*?)\n---/); -const frontmatter = fmMatch ? fmMatch[1] : ""; -const body = fmMatch ? skillMd.slice(fmMatch[0].length).trim() : skillMd; - -// Validate name field -const nameMatch = frontmatter.match(/^name:\s*(.+)$/m); -const name = nameMatch ? nameMatch[1].trim() : ""; -const nameErrors = []; -if (name.length < 1 || name.length > 64) nameErrors.push("Name must be 1-64 characters"); -if (/[^a-z0-9-]/.test(name)) nameErrors.push("Name must be lowercase alphanumeric + hyphens only"); -if (/^-|-$/.test(name)) nameErrors.push("Name must not start or end with hyphen"); -if (/--/.test(name)) nameErrors.push("Name must not contain consecutive hyphens"); -if (name !== path.basename(skillDir)) nameErrors.push("Name must match directory name"); - -const metrics = { - frontmatterTokens: Math.ceil(frontmatter.length / 4), - bodyLines: body.split("\n").length, - bodyTokens: Math.ceil(body.length / 4), -}; - -const warnings = []; -if (metrics.frontmatterTokens >= 100) - warnings.push("Frontmatter exceeds 100 token guideline"); -if (metrics.bodyLines >= 160) - warnings.push("Body exceeds 160 line guideline"); -if (metrics.bodyLines >= 500) - warnings.push("Body exceeds 500 line spec limit - split into reference files"); -if (metrics.bodyTokens >= 5000) - warnings.push("Body exceeds 5000 token spec guideline"); - -console.log("Name validation:", nameErrors.length ? nameErrors : "PASS"); -console.log("Size metrics:", metrics); -console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); -``` - -## Spec Compliance Constraints - -These constraints prevent common mistakes when generating skills. Every generated skill MUST pass all of these checks: - -Constraints { - // Structure: skills are DIRECTORIES, not standalone files - NEVER create a standalone .mdc or .md file as a skill - always create a directory with SKILL.md inside - The output MUST be `$projectRoot/aidd-custom/${skillName}/SKILL.md` - not a flat file - The file MUST be named exactly `SKILL.md` (uppercase) - not skill.md, not ${name}.mdc - - // Frontmatter: use AgentSkills.io fields, NOT aidd .mdc fields - Frontmatter MUST include `name` and `description` as required fields - NEVER use `alwaysApply`, `globs`, or other non-spec frontmatter fields in generated skills - The `name` field MUST be lowercase alphanumeric + hyphens only (a-z, 0-9, -) - The `name` field MUST match the parent directory name exactly - The `name` field MUST NOT start or end with a hyphen - The `name` field MUST NOT contain consecutive hyphens (--) - The `name` field MUST be 1-64 characters - The `description` field MUST be 1-1024 characters and describe both what the skill does AND when to use it - - // Size: respect progressive disclosure thresholds - Frontmatter metadata MUST stay under ~100 tokens - SKILL.md body SHOULD stay under 160 lines and MUST stay under 500 lines - SKILL.md body SHOULD stay under 5000 tokens - If content exceeds limits, split into references/ directory files - - // Content quality - The body MUST use plain Markdown - not SudoLang (SudoLang is for .mdc rules, not SKILL.md files) - Include recommended sections: when to use, step-by-step instructions, examples, edge cases - Keep the skill focused on a single responsibility - - // Validation: always validate before reporting success - ALWAYS run the symbolic JavaScript validator after creating the skill - ALWAYS run `skills-ref validate` if available - ALWAYS report size metrics and any warnings to the user -} - -## Example SKILL.md - -```markdown ---- -name: format-code -description: Format source code files according to project style guides. Use when code needs formatting, linting fixes, or style consistency checks. -metadata: - author: my-org - version: "1.0" ---- - -# Format Code - -Format source code according to project conventions and style guides. - -## When to use - -Use this skill when code needs formatting, style fixes, or consistency checks. - -## Steps - -1. Detect the project's formatter configuration -2. Identify files that need formatting -3. Apply formatting rules -4. Report changes made - -## Edge cases - -- If no formatter config exists, ask the user which style to use -- For mixed-language projects, apply per-language formatters -``` - -Commands { - /create-skill - create a new agent skill following the AgentSkills.io specification -} diff --git a/ai/skills/create-skill/SKILL.md b/ai/skills/create-skill/SKILL.md new file mode 100644 index 0000000..51651cd --- /dev/null +++ b/ai/skills/create-skill/SKILL.md @@ -0,0 +1,229 @@ +--- +name: create-skill +description: Create new agent skills following the AgentSkills.io specification. Use when the user wants to author, scaffold, or generate a new agent skill with proper structure, validation, and best practices. +metadata: + author: paralleldrive + version: "1.0" +--- +# Create Skill + +Create agent skills following the [AgentSkills.io](https://agentskills.io/specification) specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). + +## SudoLang Reference + +Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang syntax conventions. See `ai/rules/productmanager.mdc` for an example of well-written SudoLang (types, interfaces, composition). + +Use markdown and natural language primarily. Employ SudoLang for interfaces, type definitions, and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. + +## Types + +type SkillName = string(1-64, lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens, matches parent directory name) +type SkillDescription = string(1-1024, describes what skill does AND when to use it) +type TokenCount = number // ~4 chars per token estimate + +## Interfaces + +Frontmatter { + name: SkillName // required, must match directory name + description: SkillDescription // required + license // optional + compatibility: string(1-500) // optional, environment requirements + metadata {} // optional, arbitrary key-value pairs + allowed-tools // optional, space-delimited tool list (experimental) +} + +Skill { + ${skillName}/ + SKILL.md // required: Frontmatter + markdown body + scripts/ // optional: executable code + references/ // optional: documentation loaded on demand + assets/ // optional: templates, images, data files +} + +SizeMetrics { + frontmatterTokens: TokenCount // should be < 100 + bodyLines: number // should be < 160, must be < 500 + bodyTokens: TokenCount // should be < 5000 +} + +SkillPlan { + name: SkillName + purpose: SkillDescription + relatedSkills[] // existing skills found in discovery + bestPractices[] // findings from web research + proposedSections[] // planned SKILL.md structure + optionalDirs: ["scripts" | "references" | "assets"] + sizeEstimate: SizeMetrics +} + +## Progressive Disclosure + +Metadata (~100 tokens) => loaded at startup for all skills +Instructions (< 5000 tokens) => loaded when skill is activated +Resources (as needed) => loaded only when required + +## Process + +createSkill(userRequest) { + gatherRequirements + |> discoverRelatedSkills + |> researchBestPractices + |> nameSkill + |> buildPlan + |> presentPlan + |> awaitApproval + |> draftSkillMd + |> writeSkill + |> validate + |> reportMetrics +} + +gatherRequirements(userRequest) { + ask clarifying questions about purpose, inputs, outputs, and constraints +} + +discoverRelatedSkills(skillTopic) { + searchPaths = ["$projectRoot/ai/", "$projectRoot/aidd-custom/"] + scan for SKILL.md, .mdc, and .md files + read frontmatter descriptions + identify overlapping or complementary skills + report: related skills, how to leverage them, overlap to avoid +} + +researchBestPractices(skillTopic) { + use web search to find best practices for $skillTopic + summarize key findings relevant to skill authoring +} + +nameSkill(topic) { + use verb form (e.g., `format-code`, `generate-report`) + validate against SkillName type constraints +} + +buildPlan() => SkillPlan + +presentPlan(plan: SkillPlan) { + show the user the full SkillPlan + ask if any changes are required + await explicit user approval +} + +draftSkillMd(plan: SkillPlan) { + write Frontmatter with name + description (required), optional fields as needed + write body with recommended sections: when to use, step-by-step instructions, examples, edge cases +} + +writeSkill(skillMd) { + write to `$projectRoot/aidd-custom/${skillName}/SKILL.md` + create optional directories (scripts/, references/, assets/) if planned +} + +## Validation + +After creating the skill, run validation and report size metrics: + +```javascript +// 1. Run: skills-ref validate ./path-to-skill-directory +// 2. Then compute and report size metrics: + +const fs = require("fs"); +const path = require("path"); +const skillMd = fs.readFileSync(path.join(skillDir, "SKILL.md"), "utf-8"); +const fmMatch = skillMd.match(/^---\n([\s\S]*?)\n---/); +const frontmatter = fmMatch ? fmMatch[1] : ""; +const body = fmMatch ? skillMd.slice(fmMatch[0].length).trim() : skillMd; + +// Validate name field +const nameMatch = frontmatter.match(/^name:\s*(.+)$/m); +const name = nameMatch ? nameMatch[1].trim() : ""; +const nameErrors = []; +if (name.length < 1 || name.length > 64) nameErrors.push("Name must be 1-64 characters"); +if (/[^a-z0-9-]/.test(name)) nameErrors.push("Name must be lowercase alphanumeric + hyphens only"); +if (/^-|-$/.test(name)) nameErrors.push("Name must not start or end with hyphen"); +if (/--/.test(name)) nameErrors.push("Name must not contain consecutive hyphens"); +if (name !== path.basename(skillDir)) nameErrors.push("Name must match directory name"); + +const metrics = { + frontmatterTokens: Math.ceil(frontmatter.length / 4), + bodyLines: body.split("\n").length, + bodyTokens: Math.ceil(body.length / 4), +}; + +const warnings = []; +if (metrics.frontmatterTokens >= 100) + warnings.push("Frontmatter exceeds 100 token guideline"); +if (metrics.bodyLines >= 160) + warnings.push("Body exceeds 160 line guideline"); +if (metrics.bodyLines >= 500) + warnings.push("Body exceeds 500 line spec limit - split into reference files"); +if (metrics.bodyTokens >= 5000) + warnings.push("Body exceeds 5000 token spec guideline"); + +console.log("Name validation:", nameErrors.length ? nameErrors : "PASS"); +console.log("Size metrics:", metrics); +console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); +``` + +## Spec Compliance Constraints + +Every generated skill MUST pass all of these checks: + +Constraints { + // Structure: skills are DIRECTORIES, not standalone files + NEVER create a standalone .mdc or .md file as a skill + The output MUST be `$projectRoot/aidd-custom/${skillName}/SKILL.md` + The file MUST be named exactly `SKILL.md` (uppercase) + + // Frontmatter: use AgentSkills.io fields, NOT aidd .mdc fields + Frontmatter MUST include `name` and `description` as required fields + NEVER use `alwaysApply`, `globs`, or other non-spec frontmatter fields + The `name` field MUST satisfy the SkillName type constraints + The `description` field MUST satisfy the SkillDescription type constraints + + // Size: respect progressive disclosure thresholds + Frontmatter metadata MUST stay under ~100 tokens + SKILL.md body SHOULD stay under 160 lines and MUST stay under 500 lines + SKILL.md body SHOULD stay under 5000 tokens + If content exceeds limits, split into references/ directory files + + // Validation: always validate before reporting success + ALWAYS run the symbolic JavaScript validator after creating the skill + ALWAYS run `skills-ref validate` if available + ALWAYS report size metrics and any warnings to the user +} + +## Example SKILL.md + +```markdown +--- +name: format-code +description: Format source code files according to project style guides. Use when code needs formatting, linting fixes, or style consistency checks. +metadata: + author: my-org + version: "1.0" +--- + +# Format Code + +Format source code according to project conventions and style guides. + +## When to use + +Use this skill when code needs formatting, style fixes, or consistency checks. + +## Steps + +1. Detect the project's formatter configuration +2. Identify files that need formatting +3. Apply formatting rules +4. Report changes made + +## Edge cases + +- If no formatter config exists, ask the user which style to use +- For mixed-language projects, apply per-language formatters +``` + +Commands { + /create-skill - create a new agent skill following the AgentSkills.io specification +} diff --git a/ai/skills/create-skill/index.md b/ai/skills/create-skill/index.md new file mode 100644 index 0000000..f789b4d --- /dev/null +++ b/ai/skills/create-skill/index.md @@ -0,0 +1,12 @@ +# create-skill + +This index provides an overview of the contents in this directory. + +## Files + +### Create Skill + +**File:** `SKILL.md` + +Create new agent skills following the AgentSkills.io specification. Use when the user wants to author, scaffold, or generate a new agent skill with proper structure, validation, and best practices. + diff --git a/ai/skills/index.md b/ai/skills/index.md index 11afacd..fb328c5 100644 --- a/ai/skills/index.md +++ b/ai/skills/index.md @@ -2,11 +2,9 @@ This index provides an overview of the contents in this directory. -## Files +## Subdirectories -### Create Skill +### ๐Ÿ“ create-skill/ -**File:** `create-skill.mdc` - -Create a new agent skill following the AgentSkills.io specification +See [`create-skill/index.md`](./create-skill/index.md) for contents. From 15bf99e7105ab19ff967b8a830f41de13c590e4f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:38:31 +0000 Subject: [PATCH 7/9] feat: add metadata.alwaysApply extension, documentation requirements The AgentSkills.io spec has no alwaysApply equivalent. Document the design decision to use the spec's metadata extension point (metadata.alwaysApply: "true") for AIDD-specific context preloading on project init. - Document AIDD Extensions via metadata section with rationale - Add SkillPlan.alwaysApply field to plan interface - Add RequiredSections interface enforcing documentation quality: When to use, Steps/Process, Examples, Edge cases - Add documentation constraints to spec compliance checks - Update example SKILL.md to show all required sections and metadata.alwaysApply usage https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill/SKILL.md | 57 +++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/ai/skills/create-skill/SKILL.md b/ai/skills/create-skill/SKILL.md index 51651cd..34cda95 100644 --- a/ai/skills/create-skill/SKILL.md +++ b/ai/skills/create-skill/SKILL.md @@ -28,10 +28,21 @@ Frontmatter { description: SkillDescription // required license // optional compatibility: string(1-500) // optional, environment requirements - metadata {} // optional, arbitrary key-value pairs + metadata {} // optional, arbitrary key-value pairs (see AIDD Extensions below) allowed-tools // optional, space-delimited tool list (experimental) } +### AIDD Extensions via `metadata` + +The AgentSkills.io spec has no `alwaysApply` equivalent. By default, skills use progressive disclosure: only `name` and `description` are loaded at startup; the full SKILL.md body loads only on activation. The spec's `metadata` field is the designated extension point for custom properties. + +AIDD uses `metadata.alwaysApply` to mark skills whose full instructions should be preloaded into agent context on project init, before any user request. Use sparingly - every always-applied skill consumes context budget. + +```yaml +metadata: + alwaysApply: "true" # AIDD extension: preload full SKILL.md on project init +``` + Skill { ${skillName}/ SKILL.md // required: Frontmatter + markdown body @@ -49,6 +60,7 @@ SizeMetrics { SkillPlan { name: SkillName purpose: SkillDescription + alwaysApply: boolean // should this skill preload on project init? relatedSkills[] // existing skills found in discovery bestPractices[] // findings from web research proposedSections[] // planned SKILL.md structure @@ -110,7 +122,8 @@ presentPlan(plan: SkillPlan) { draftSkillMd(plan: SkillPlan) { write Frontmatter with name + description (required), optional fields as needed - write body with recommended sections: when to use, step-by-step instructions, examples, edge cases + if (plan.alwaysApply) add `metadata.alwaysApply: "true"` + write body with required documentation sections (see Documentation Requirements below) } writeSkill(skillMd) { @@ -164,6 +177,20 @@ console.log("Size metrics:", metrics); console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); ``` +## Documentation Requirements + +Every generated skill MUST include these documentation sections in the SKILL.md body: + +RequiredSections { + "# Title" // skill name as heading + "## When to use" // clear activation criteria - when should an agent use this skill? + "## Steps" | "## Process" // step-by-step instructions for executing the skill + "## Examples" // concrete input/output examples demonstrating usage + "## Edge cases" // known limitations, error handling, boundary conditions +} + +The `description` field in frontmatter is the skill's elevator pitch - it must be good enough for an agent to decide whether to activate the skill based on description alone (progressive disclosure). Write it as if it were the only thing an agent reads before deciding. + ## Spec Compliance Constraints Every generated skill MUST pass all of these checks: @@ -174,9 +201,10 @@ Constraints { The output MUST be `$projectRoot/aidd-custom/${skillName}/SKILL.md` The file MUST be named exactly `SKILL.md` (uppercase) - // Frontmatter: use AgentSkills.io fields, NOT aidd .mdc fields + // Frontmatter: use AgentSkills.io spec fields only Frontmatter MUST include `name` and `description` as required fields - NEVER use `alwaysApply`, `globs`, or other non-spec frontmatter fields + NEVER use `alwaysApply`, `globs`, or other non-spec keys as top-level frontmatter fields + Use `metadata` for AIDD extensions (e.g., `metadata.alwaysApply: "true"`) The `name` field MUST satisfy the SkillName type constraints The `description` field MUST satisfy the SkillDescription type constraints @@ -186,6 +214,11 @@ Constraints { SKILL.md body SHOULD stay under 5000 tokens If content exceeds limits, split into references/ directory files + // Documentation: every skill must be well-documented + SKILL.md body MUST include all RequiredSections + The description field MUST be specific enough for agent activation decisions + Include concrete examples - not just abstract instructions + // Validation: always validate before reporting success ALWAYS run the symbolic JavaScript validator after creating the skill ALWAYS run `skills-ref validate` if available @@ -197,10 +230,11 @@ Constraints { ```markdown --- name: format-code -description: Format source code files according to project style guides. Use when code needs formatting, linting fixes, or style consistency checks. +description: Format source code files according to project style guides and conventions. Use when code needs formatting, linting fixes, style consistency checks, or when a user mentions "format", "lint", or "prettier". metadata: author: my-org version: "1.0" + alwaysApply: "true" --- # Format Code @@ -209,19 +243,28 @@ Format source code according to project conventions and style guides. ## When to use -Use this skill when code needs formatting, style fixes, or consistency checks. +Use this skill when: +- Code needs formatting or linting fixes +- A new file is created and needs style consistency +- The user asks for style or formatting help ## Steps -1. Detect the project's formatter configuration +1. Detect the project's formatter configuration (prettier, biome, eslint, etc.) 2. Identify files that need formatting 3. Apply formatting rules 4. Report changes made +## Examples + +Given a project with `.prettierrc`, run: `npx prettier --write "src/**/*.ts"` +Given a project with `biome.json`, run: `npx @biomejs/biome format --write` + ## Edge cases - If no formatter config exists, ask the user which style to use - For mixed-language projects, apply per-language formatters +- If formatter conflicts with linter, prioritize linter configuration ``` Commands { From f98bbdc29e3ff4033643a82b0179c2256c3c828b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:39:33 +0000 Subject: [PATCH 8/9] feat: ask user about alwaysApply during requirements gathering Add alwaysApply question to gatherRequirements with guidance hints: recommend "yes" only for universally-applicable skills (coding standards, security checks), "no" for task-specific skills that activate on demand. https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill/SKILL.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ai/skills/create-skill/SKILL.md b/ai/skills/create-skill/SKILL.md index 34cda95..37e9238 100644 --- a/ai/skills/create-skill/SKILL.md +++ b/ai/skills/create-skill/SKILL.md @@ -91,7 +91,13 @@ createSkill(userRequest) { } gatherRequirements(userRequest) { - ask clarifying questions about purpose, inputs, outputs, and constraints + ask clarifying questions about: + - purpose: what problem does this skill solve? + - inputs and outputs: what does the skill consume and produce? + - constraints: any technical limitations or requirements? + - alwaysApply: should this skill be preloaded into agent context on every session? + hint: recommend "yes" only if the skill applies to nearly every task (e.g., coding standards, security checks) + hint: recommend "no" for task-specific skills that activate on demand (e.g., pdf-processing, deploy-app) } discoverRelatedSkills(skillTopic) { From 80de38ebac4f32587d068fa6299c15969b19354c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Feb 2026 20:44:56 +0000 Subject: [PATCH 9/9] refactor: extract validator to scripts/, TDD with riteway, remove duplication Review findings addressed: - Extract inline JS validator to scripts/validate-skill.js as a proper testable module with 4 exports: parseSkillMd, validateName, calculateMetrics, checkThresholds - 16 unit tests written TDD-first with riteway assertions covering all functional requirements (name validation, metrics, thresholds) - Remove duplication: SudoLang Reference section (meta-guidance), TokenCount type (just number), Skill interface (duplicated tree diagram), Progressive Disclosure section (already in AIDD Extensions) - SKILL.md reduced from 279 to 237 lines while adding clarity - Inline 40-line JS blob replaced with reference to tested script https://claude.ai/code/session_012PBVMXigqq6Bd4WTUhi4b7 --- ai/skills/create-skill/SKILL.md | 120 +++------ ai/skills/create-skill/index.md | 6 + ai/skills/create-skill/scripts/index.md | 5 + .../create-skill/scripts/validate-skill.js | 47 ++++ .../scripts/validate-skill.test.js | 242 ++++++++++++++++++ 5 files changed, 339 insertions(+), 81 deletions(-) create mode 100644 ai/skills/create-skill/scripts/index.md create mode 100644 ai/skills/create-skill/scripts/validate-skill.js create mode 100644 ai/skills/create-skill/scripts/validate-skill.test.js diff --git a/ai/skills/create-skill/SKILL.md b/ai/skills/create-skill/SKILL.md index 37e9238..4394bf3 100644 --- a/ai/skills/create-skill/SKILL.md +++ b/ai/skills/create-skill/SKILL.md @@ -9,22 +9,29 @@ metadata: Create agent skills following the [AgentSkills.io](https://agentskills.io/specification) specification. Skills use **verb form** naming (e.g., `format-code`, `create-skill`). Agents use **noun form** (e.g., `code-formatter`, `skill-creator`). -## SudoLang Reference - Read `ai/rules/sudolang/sudolang-syntax.mdc` for SudoLang syntax conventions. See `ai/rules/productmanager.mdc` for an example of well-written SudoLang (types, interfaces, composition). -Use markdown and natural language primarily. Employ SudoLang for interfaces, type definitions, and function composition where token efficiency matters. Favor symbolic code (JavaScript) over AI inference for deterministic operations. +## Skill Structure + +A skill is a directory containing a `SKILL.md` file with optional supporting directories: + +``` +skill-name/ +โ”œโ”€โ”€ SKILL.md # Required: YAML frontmatter + markdown instructions +โ”œโ”€โ”€ scripts/ # Optional: executable code agents can run +โ”œโ”€โ”€ references/ # Optional: documentation loaded on demand +โ””โ”€โ”€ assets/ # Optional: templates, images, data files +``` ## Types -type SkillName = string(1-64, lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens, matches parent directory name) +type SkillName = string(1-64, lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens, must match parent directory name) type SkillDescription = string(1-1024, describes what skill does AND when to use it) -type TokenCount = number // ~4 chars per token estimate ## Interfaces Frontmatter { - name: SkillName // required, must match directory name + name: SkillName // required description: SkillDescription // required license // optional compatibility: string(1-500) // optional, environment requirements @@ -34,27 +41,19 @@ Frontmatter { ### AIDD Extensions via `metadata` -The AgentSkills.io spec has no `alwaysApply` equivalent. By default, skills use progressive disclosure: only `name` and `description` are loaded at startup; the full SKILL.md body loads only on activation. The spec's `metadata` field is the designated extension point for custom properties. +The AgentSkills.io spec uses progressive disclosure: only `name` and `description` (~100 tokens) are loaded at startup; the full SKILL.md body (< 5000 tokens recommended) loads only on activation; resources load on demand. -AIDD uses `metadata.alwaysApply` to mark skills whose full instructions should be preloaded into agent context on project init, before any user request. Use sparingly - every always-applied skill consumes context budget. +The spec has no `alwaysApply` equivalent. AIDD uses `metadata.alwaysApply` to mark skills whose full instructions should be preloaded into agent context on project init. Use sparingly - every always-applied skill consumes context budget. ```yaml metadata: alwaysApply: "true" # AIDD extension: preload full SKILL.md on project init ``` -Skill { - ${skillName}/ - SKILL.md // required: Frontmatter + markdown body - scripts/ // optional: executable code - references/ // optional: documentation loaded on demand - assets/ // optional: templates, images, data files -} - SizeMetrics { - frontmatterTokens: TokenCount // should be < 100 - bodyLines: number // should be < 160, must be < 500 - bodyTokens: TokenCount // should be < 5000 + frontmatterTokens: number // should be < 100 + bodyLines: number // should be < 160, must be < 500 + bodyTokens: number // should be < 5000 } SkillPlan { @@ -68,12 +67,6 @@ SkillPlan { sizeEstimate: SizeMetrics } -## Progressive Disclosure - -Metadata (~100 tokens) => loaded at startup for all skills -Instructions (< 5000 tokens) => loaded when skill is activated -Resources (as needed) => loaded only when required - ## Process createSkill(userRequest) { @@ -139,50 +132,18 @@ writeSkill(skillMd) { ## Validation -After creating the skill, run validation and report size metrics: - -```javascript -// 1. Run: skills-ref validate ./path-to-skill-directory -// 2. Then compute and report size metrics: - -const fs = require("fs"); -const path = require("path"); -const skillMd = fs.readFileSync(path.join(skillDir, "SKILL.md"), "utf-8"); -const fmMatch = skillMd.match(/^---\n([\s\S]*?)\n---/); -const frontmatter = fmMatch ? fmMatch[1] : ""; -const body = fmMatch ? skillMd.slice(fmMatch[0].length).trim() : skillMd; - -// Validate name field -const nameMatch = frontmatter.match(/^name:\s*(.+)$/m); -const name = nameMatch ? nameMatch[1].trim() : ""; -const nameErrors = []; -if (name.length < 1 || name.length > 64) nameErrors.push("Name must be 1-64 characters"); -if (/[^a-z0-9-]/.test(name)) nameErrors.push("Name must be lowercase alphanumeric + hyphens only"); -if (/^-|-$/.test(name)) nameErrors.push("Name must not start or end with hyphen"); -if (/--/.test(name)) nameErrors.push("Name must not contain consecutive hyphens"); -if (name !== path.basename(skillDir)) nameErrors.push("Name must match directory name"); - -const metrics = { - frontmatterTokens: Math.ceil(frontmatter.length / 4), - bodyLines: body.split("\n").length, - bodyTokens: Math.ceil(body.length / 4), -}; - -const warnings = []; -if (metrics.frontmatterTokens >= 100) - warnings.push("Frontmatter exceeds 100 token guideline"); -if (metrics.bodyLines >= 160) - warnings.push("Body exceeds 160 line guideline"); -if (metrics.bodyLines >= 500) - warnings.push("Body exceeds 500 line spec limit - split into reference files"); -if (metrics.bodyTokens >= 5000) - warnings.push("Body exceeds 5000 token spec guideline"); - -console.log("Name validation:", nameErrors.length ? nameErrors : "PASS"); -console.log("Size metrics:", metrics); -console.log(warnings.length ? "Warnings: " + warnings.join(", ") : "All size checks passed"); +After creating the skill, validate using the unit-tested validator at `scripts/validate-skill.js`: + +```bash +# If skills-ref is available: +skills-ref validate ./path-to-skill-directory + +# Then run the symbolic size/name validator: +node ai/skills/create-skill/scripts/validate-skill.js ./path-to-skill-directory ``` +The validator exports: `parseSkillMd`, `validateName`, `calculateMetrics`, `checkThresholds`. + ## Documentation Requirements Every generated skill MUST include these documentation sections in the SKILL.md body: @@ -195,38 +156,35 @@ RequiredSections { "## Edge cases" // known limitations, error handling, boundary conditions } -The `description` field in frontmatter is the skill's elevator pitch - it must be good enough for an agent to decide whether to activate the skill based on description alone (progressive disclosure). Write it as if it were the only thing an agent reads before deciding. - -## Spec Compliance Constraints +The `description` field is the skill's elevator pitch - it must be good enough for an agent to decide whether to activate the skill based on description alone. Write it as if it were the only thing an agent reads before deciding. -Every generated skill MUST pass all of these checks: +## Constraints Constraints { - // Structure: skills are DIRECTORIES, not standalone files + // Structure NEVER create a standalone .mdc or .md file as a skill The output MUST be `$projectRoot/aidd-custom/${skillName}/SKILL.md` The file MUST be named exactly `SKILL.md` (uppercase) - // Frontmatter: use AgentSkills.io spec fields only + // Frontmatter Frontmatter MUST include `name` and `description` as required fields - NEVER use `alwaysApply`, `globs`, or other non-spec keys as top-level frontmatter fields + NEVER use non-spec keys as top-level frontmatter fields Use `metadata` for AIDD extensions (e.g., `metadata.alwaysApply: "true"`) - The `name` field MUST satisfy the SkillName type constraints - The `description` field MUST satisfy the SkillDescription type constraints + The `name` field MUST satisfy the SkillName type + The `description` field MUST satisfy the SkillDescription type - // Size: respect progressive disclosure thresholds - Frontmatter metadata MUST stay under ~100 tokens + // Size SKILL.md body SHOULD stay under 160 lines and MUST stay under 500 lines SKILL.md body SHOULD stay under 5000 tokens If content exceeds limits, split into references/ directory files - // Documentation: every skill must be well-documented + // Documentation SKILL.md body MUST include all RequiredSections The description field MUST be specific enough for agent activation decisions Include concrete examples - not just abstract instructions - // Validation: always validate before reporting success - ALWAYS run the symbolic JavaScript validator after creating the skill + // Validation + ALWAYS run `scripts/validate-skill.js` after creating the skill ALWAYS run `skills-ref validate` if available ALWAYS report size metrics and any warnings to the user } diff --git a/ai/skills/create-skill/index.md b/ai/skills/create-skill/index.md index f789b4d..dba0dfd 100644 --- a/ai/skills/create-skill/index.md +++ b/ai/skills/create-skill/index.md @@ -2,6 +2,12 @@ This index provides an overview of the contents in this directory. +## Subdirectories + +### ๐Ÿ“ scripts/ + +See [`scripts/index.md`](./scripts/index.md) for contents. + ## Files ### Create Skill diff --git a/ai/skills/create-skill/scripts/index.md b/ai/skills/create-skill/scripts/index.md new file mode 100644 index 0000000..36ce914 --- /dev/null +++ b/ai/skills/create-skill/scripts/index.md @@ -0,0 +1,5 @@ +# scripts + +This index provides an overview of the contents in this directory. + +*This directory is empty.* diff --git a/ai/skills/create-skill/scripts/validate-skill.js b/ai/skills/create-skill/scripts/validate-skill.js new file mode 100644 index 0000000..7406ae6 --- /dev/null +++ b/ai/skills/create-skill/scripts/validate-skill.js @@ -0,0 +1,47 @@ +/** + * Validate an AgentSkills.io SKILL.md file. + * + * Usage: node validate-skill.js ./path-to-skill-directory + */ + +export const parseSkillMd = (content) => { + const match = content.match(/^---\n([\s\S]*?)\n---/); + if (!match) return { body: content, frontmatter: "" }; + return { + body: content.slice(match[0].length).trim(), + frontmatter: match[1], + }; +}; + +export const validateName = (name, dirName) => { + const errors = []; + if (name.length < 1 || name.length > 64) + errors.push("Name must be 1-64 characters"); + if (/[^a-z0-9-]/.test(name)) + errors.push("Name must be lowercase alphanumeric + hyphens only"); + if (/^-|-$/.test(name)) errors.push("Name must not start or end with hyphen"); + if (/--/.test(name)) errors.push("Name must not contain consecutive hyphens"); + if (name !== dirName) errors.push("Name must match directory name"); + return errors; +}; + +export const calculateMetrics = (frontmatter, body) => ({ + bodyLines: body.split("\n").length, + bodyTokens: Math.ceil(body.length / 4), + frontmatterTokens: Math.ceil(frontmatter.length / 4), +}); + +export const checkThresholds = (metrics) => { + const warnings = []; + if (metrics.frontmatterTokens >= 100) + warnings.push("Frontmatter exceeds 100 token guideline"); + if (metrics.bodyLines >= 160) + warnings.push("Body exceeds 160 line guideline"); + if (metrics.bodyLines >= 500) + warnings.push( + "Body exceeds 500 line spec limit - split into reference files", + ); + if (metrics.bodyTokens >= 5000) + warnings.push("Body exceeds 5000 token spec guideline"); + return warnings; +}; diff --git a/ai/skills/create-skill/scripts/validate-skill.test.js b/ai/skills/create-skill/scripts/validate-skill.test.js new file mode 100644 index 0000000..af90d4e --- /dev/null +++ b/ai/skills/create-skill/scripts/validate-skill.test.js @@ -0,0 +1,242 @@ +import { assert } from "riteway/vitest"; +import { describe, test } from "vitest"; + +import { + calculateMetrics, + checkThresholds, + parseSkillMd, + validateName, +} from "./validate-skill.js"; + +describe("parseSkillMd", () => { + test("valid frontmatter", () => { + const content = `--- +name: my-skill +description: A test skill. +--- +# My Skill + +Body content here.`; + + const result = parseSkillMd(content); + + assert({ + given: "SKILL.md content with valid frontmatter", + should: "return parsed frontmatter string", + actual: result.frontmatter.includes("name: my-skill"), + expected: true, + }); + + assert({ + given: "SKILL.md content with valid frontmatter", + should: "return body without frontmatter", + actual: result.body.startsWith("# My Skill"), + expected: true, + }); + }); + + test("no frontmatter", () => { + const content = "# Just a body\n\nNo frontmatter here."; + const result = parseSkillMd(content); + + assert({ + given: "content without frontmatter", + should: "return empty frontmatter", + actual: result.frontmatter, + expected: "", + }); + + assert({ + given: "content without frontmatter", + should: "return full content as body", + actual: result.body, + expected: content, + }); + }); +}); + +describe("validateName", () => { + test("valid names", () => { + assert({ + given: "a valid lowercase hyphenated name", + should: "return no errors", + actual: validateName("format-code", "format-code"), + expected: [], + }); + + assert({ + given: "a single-word name", + should: "return no errors", + actual: validateName("lint", "lint"), + expected: [], + }); + }); + + test("uppercase letters", () => { + const errors = validateName("Format-Code", "Format-Code"); + + assert({ + given: "a name with uppercase letters", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("leading hyphen", () => { + const errors = validateName("-my-skill", "-my-skill"); + + assert({ + given: "a name starting with a hyphen", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("trailing hyphen", () => { + const errors = validateName("my-skill-", "my-skill-"); + + assert({ + given: "a name ending with a hyphen", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("consecutive hyphens", () => { + const errors = validateName("my--skill", "my--skill"); + + assert({ + given: "a name with consecutive hyphens", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("too long", () => { + const longName = "a".repeat(65); + const errors = validateName(longName, longName); + + assert({ + given: "a name longer than 64 characters", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("empty name", () => { + const errors = validateName("", "some-dir"); + + assert({ + given: "an empty name", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); + + test("directory mismatch", () => { + const errors = validateName("my-skill", "other-dir"); + + assert({ + given: "a name that does not match the directory name", + should: "return a validation error", + actual: errors.length > 0, + expected: true, + }); + }); +}); + +describe("calculateMetrics", () => { + test("calculates correct metrics", () => { + const frontmatter = "name: test\ndescription: A test."; + const body = "# Title\n\nLine 2\nLine 3"; + const result = calculateMetrics(frontmatter, body); + + assert({ + given: "frontmatter and body text", + should: "estimate frontmatter tokens as ceil(length / 4)", + actual: result.frontmatterTokens, + expected: Math.ceil(frontmatter.length / 4), + }); + + assert({ + given: "a body with 4 lines", + should: "count 4 body lines", + actual: result.bodyLines, + expected: 4, + }); + + assert({ + given: "body text", + should: "estimate body tokens as ceil(length / 4)", + actual: result.bodyTokens, + expected: Math.ceil(body.length / 4), + }); + }); +}); + +describe("checkThresholds", () => { + test("all within limits", () => { + const metrics = { frontmatterTokens: 50, bodyLines: 100, bodyTokens: 3000 }; + + assert({ + given: "metrics within all thresholds", + should: "return no warnings", + actual: checkThresholds(metrics), + expected: [], + }); + }); + + test("frontmatter too large", () => { + const metrics = { frontmatterTokens: 100, bodyLines: 50, bodyTokens: 1000 }; + const warnings = checkThresholds(metrics); + + assert({ + given: "frontmatter at 100 tokens", + should: "return a frontmatter warning", + actual: warnings.some((w) => w.includes("Frontmatter")), + expected: true, + }); + }); + + test("body exceeds 160 lines", () => { + const metrics = { frontmatterTokens: 10, bodyLines: 160, bodyTokens: 1000 }; + const warnings = checkThresholds(metrics); + + assert({ + given: "body at 160 lines", + should: "return a 160-line warning", + actual: warnings.some((w) => w.includes("160")), + expected: true, + }); + }); + + test("body exceeds 500 lines", () => { + const metrics = { frontmatterTokens: 10, bodyLines: 500, bodyTokens: 1000 }; + const warnings = checkThresholds(metrics); + + assert({ + given: "body at 500 lines", + should: "return a 500-line spec limit warning", + actual: warnings.some((w) => w.includes("500")), + expected: true, + }); + }); + + test("body exceeds 5000 tokens", () => { + const metrics = { frontmatterTokens: 10, bodyLines: 50, bodyTokens: 5000 }; + const warnings = checkThresholds(metrics); + + assert({ + given: "body at 5000 tokens", + should: "return a token warning", + actual: warnings.some((w) => w.includes("5000")), + expected: true, + }); + }); +});