ai-agent-skills 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -202,7 +202,10 @@ function parseArgs(args) {
202
202
 
203
203
  // ============ SAFE FILE OPERATIONS ============
204
204
 
205
- function copyDir(src, dest, currentSize = { total: 0 }) {
205
+ function copyDir(src, dest, currentSize = { total: 0 }, rootSrc = null) {
206
+ // Track root source to prevent path escape attacks
207
+ if (rootSrc === null) rootSrc = src;
208
+
206
209
  try {
207
210
  if (fs.existsSync(dest)) {
208
211
  fs.rmSync(dest, { recursive: true });
@@ -218,12 +221,25 @@ function copyDir(src, dest, currentSize = { total: 0 }) {
218
221
  // Skip unnecessary files/folders
219
222
  if (skipList.includes(entry.name)) continue;
220
223
 
224
+ // Skip symlinks to prevent path escape attacks
225
+ if (entry.isSymbolicLink()) {
226
+ warn(`Skipping symlink: ${entry.name}`);
227
+ continue;
228
+ }
229
+
221
230
  const srcPath = path.join(src, entry.name);
222
231
  const destPath = path.join(dest, entry.name);
223
232
 
233
+ // Verify resolved path stays within source directory (prevent path traversal)
234
+ const resolvedSrc = fs.realpathSync(srcPath);
235
+ if (!resolvedSrc.startsWith(fs.realpathSync(rootSrc))) {
236
+ warn(`Skipping file outside source directory: ${entry.name}`);
237
+ continue;
238
+ }
239
+
224
240
  if (entry.isDirectory()) {
225
- copyDir(srcPath, destPath, currentSize);
226
- } else {
241
+ copyDir(srcPath, destPath, currentSize, rootSrc);
242
+ } else if (entry.isFile()) {
227
243
  const stat = fs.statSync(srcPath);
228
244
  currentSize.total += stat.size;
229
245
 
@@ -233,6 +249,7 @@ function copyDir(src, dest, currentSize = { total: 0 }) {
233
249
 
234
250
  fs.copyFileSync(srcPath, destPath);
235
251
  }
252
+ // Skip any other special file types (sockets, devices, etc.)
236
253
  }
237
254
  } catch (e) {
238
255
  // Clean up partial install on failure
@@ -401,7 +418,6 @@ function getInstalledSkills(agent = 'claude') {
401
418
  function listInstalledSkills(agent = 'claude') {
402
419
  const installed = getInstalledSkills(agent);
403
420
  const destDir = AGENT_PATHS[agent] || AGENT_PATHS.claude;
404
- const data = loadSkillsJson();
405
421
 
406
422
  if (installed.length === 0) {
407
423
  warn(`No skills installed for ${agent}`);
@@ -412,43 +428,12 @@ function listInstalledSkills(agent = 'claude') {
412
428
  log(`\n${colors.bold}Installed Skills${colors.reset} (${installed.length} for ${agent})\n`);
413
429
  log(`${colors.dim}Location: ${destDir}${colors.reset}\n`);
414
430
 
415
- // Check for updates
416
- let updatesAvailable = 0;
417
-
418
431
  installed.forEach(name => {
419
- const skill = data.skills.find(s => s.name === name);
420
- const hasUpdate = skill && skill.lastUpdated && isUpdateAvailable(name, agent, skill.lastUpdated);
421
-
422
- if (hasUpdate) {
423
- updatesAvailable++;
424
- log(` ${colors.green}${name}${colors.reset} ${colors.yellow}(update available)${colors.reset}`);
425
- } else {
426
- log(` ${colors.green}${name}${colors.reset}`);
427
- }
432
+ log(` ${colors.green}${name}${colors.reset}`);
428
433
  });
429
434
 
430
- if (updatesAvailable > 0) {
431
- log(`\n${colors.yellow}${updatesAvailable} update(s) available.${colors.reset}`);
432
- log(`${colors.dim}Run: npx ai-agent-skills update <name> --agent ${agent}${colors.reset}`);
433
- }
434
-
435
- log(`\n${colors.dim}Uninstall: npx ai-agent-skills uninstall <name> --agent ${agent}${colors.reset}`);
436
- }
437
-
438
- function isUpdateAvailable(skillName, agent, repoLastUpdated) {
439
- // Simple check based on file modification time
440
- const destDir = AGENT_PATHS[agent] || AGENT_PATHS.claude;
441
- const skillPath = path.join(destDir, skillName, 'SKILL.md');
442
-
443
- try {
444
- if (!fs.existsSync(skillPath)) return false;
445
- const stat = fs.statSync(skillPath);
446
- const installedTime = stat.mtime.getTime();
447
- const repoTime = new Date(repoLastUpdated).getTime();
448
- return repoTime > installedTime;
449
- } catch {
450
- return false;
451
- }
435
+ log(`\n${colors.dim}Update: npx ai-agent-skills update <name> --agent ${agent}${colors.reset}`);
436
+ log(`${colors.dim}Uninstall: npx ai-agent-skills uninstall <name> --agent ${agent}${colors.reset}`);
452
437
  }
453
438
 
454
439
  function updateSkill(skillName, agent = 'claude', dryRun = false) {
@@ -779,13 +764,23 @@ function isGitHubUrl(source) {
779
764
  !source.startsWith('./') &&
780
765
  !source.startsWith('../') &&
781
766
  !source.startsWith('/') &&
782
- !source.startsWith('~');
767
+ !source.startsWith('~') &&
768
+ !isWindowsPath(source);
769
+ }
770
+
771
+ function isWindowsPath(source) {
772
+ // Match Windows absolute paths like C:\, D:\, etc.
773
+ return /^[a-zA-Z]:[\\\/]/.test(source);
783
774
  }
784
775
 
785
776
  function isLocalPath(source) {
786
- // Only explicit local paths: ./ or / or ~/
787
- // NOT ../ (that's path traversal, should be rejected)
788
- return source.startsWith('./') || source.startsWith('/') || source.startsWith('~/');
777
+ // Explicit local paths: ./ or / or ~/ or Windows paths like C:\
778
+ // Also accept ../ as local path (will be resolved)
779
+ return source.startsWith('./') ||
780
+ source.startsWith('../') ||
781
+ source.startsWith('/') ||
782
+ source.startsWith('~/') ||
783
+ isWindowsPath(source);
789
784
  }
790
785
 
791
786
  function expandPath(p) {
@@ -795,8 +790,23 @@ function expandPath(p) {
795
790
  return path.resolve(p);
796
791
  }
797
792
 
793
+ // Validate GitHub owner/repo names (alphanumeric, hyphens, underscores, dots)
794
+ function validateGitHubName(name, type = 'name') {
795
+ if (!name || typeof name !== 'string') {
796
+ throw new Error(`Invalid GitHub ${type}`);
797
+ }
798
+ // GitHub allows: alphanumeric, hyphens, underscores, dots (no leading/trailing dots for repos)
799
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name)) {
800
+ throw new Error(`Invalid GitHub ${type}: "${name}" contains invalid characters`);
801
+ }
802
+ if (name.length > 100) {
803
+ throw new Error(`GitHub ${type} too long: ${name.length} > 100 characters`);
804
+ }
805
+ return true;
806
+ }
807
+
798
808
  async function installFromGitHub(source, agent = 'claude', dryRun = false) {
799
- const { execSync } = require('child_process');
809
+ const { execFileSync } = require('child_process');
800
810
 
801
811
  // Parse owner/repo format
802
812
  const parts = source.split('/');
@@ -809,6 +819,18 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
809
819
  const repo = parts[1];
810
820
  const skillName = parts[2]; // Optional specific skill
811
821
 
822
+ // Validate owner and repo to prevent injection attacks
823
+ try {
824
+ validateGitHubName(owner, 'owner');
825
+ validateGitHubName(repo, 'repository');
826
+ if (skillName) {
827
+ validateSkillName(skillName);
828
+ }
829
+ } catch (e) {
830
+ error(e.message);
831
+ return false;
832
+ }
833
+
812
834
  const repoUrl = `https://github.com/${owner}/${repo}.git`;
813
835
  const tempDir = path.join(os.tmpdir(), `ai-skills-${Date.now()}`);
814
836
 
@@ -822,7 +844,8 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
822
844
 
823
845
  try {
824
846
  info(`Cloning ${owner}/${repo}...`);
825
- execSync(`git clone --depth 1 ${repoUrl} ${tempDir}`, { stdio: 'pipe' });
847
+ // Use execFileSync with args array to prevent shell injection
848
+ execFileSync('git', ['clone', '--depth', '1', repoUrl, tempDir], { stdio: 'pipe' });
826
849
 
827
850
  // Find skills in the cloned repo
828
851
  const skillsDir = fs.existsSync(path.join(tempDir, 'skills'))
@@ -853,7 +876,17 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
853
876
  info(`Location: ${destPath}`);
854
877
  } else if (isRootSkill) {
855
878
  // Repo itself is a single skill
856
- const skillName = repo;
879
+ // Sanitize repo name to valid skill name (lowercase, alphanumeric + hyphens)
880
+ const skillName = repo.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
881
+
882
+ try {
883
+ validateSkillName(skillName);
884
+ } catch (e) {
885
+ error(`Cannot install: repo name "${repo}" cannot be converted to valid skill name`);
886
+ fs.rmSync(tempDir, { recursive: true });
887
+ return false;
888
+ }
889
+
857
890
  const destDir = AGENT_PATHS[agent] || AGENT_PATHS.claude;
858
891
  const destPath = path.join(destDir, skillName);
859
892
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-agent-skills",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Install curated AI agent skills with one command. Works with Claude Code, Cursor, Amp, VS Code, and all Agent Skills compatible tools.",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  "skills": "./cli.js"
9
9
  },
10
10
  "engines": {
11
- "node": ">=14.0.0"
11
+ "node": ">=14.14.0"
12
12
  },
13
13
  "scripts": {
14
14
  "test": "node test.js",
package/skills.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.1",
2
+ "version": "1.2.2",
3
3
  "updated": "2025-12-25T00:00:00Z",
4
4
  "total": 39,
5
5
  "skills": [
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Vlad-Alexandru Nicolescu
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,188 +0,0 @@
1
- # create-expert-skill
2
-
3
- > Transform expert conversations into production-grade Claude Skills. Whith this enhanced "skill-creator" skill you can capture domain knowledge and system-specific ontologies through structured roleplay. It also packages deterministic scripts alongside flexible guidance, and loads expertise progressively, turning AI assistants into specialists.
4
-
5
- ## Why This Exists
6
-
7
- Anthropic released a basic "skill-creator", however, it doesn't utilize the entire range of what's possible within a Skill. This enhanced skill creator makes use of resources, examples, templates, scripts, progressive disclosure and system architecture knowledge to deliver elaborate skills, zipped and ready to upload.
8
-
9
- ## Why the "Expert" Part Matters
10
-
11
- AI assistants struggle in production for two reasons:
12
-
13
- 1. **Missing domain expertise** — Generic models don't know or aren't primed with your industry's edge cases, terminology, or unwritten rules.
14
- 2. **Missing ontology understanding** — They don't grasp your specific data structures, entity relationships, or system constraints
15
-
16
- This skill solves both by helping you:
17
- - **Interview experts** (or yourself) to extract implicit domain knowledge
18
- - **Map system ontologies** — company-specific structures, codes, and relationships
19
- - **Separate deterministic work** (validation, parsing, math) from flexible interpretation
20
- - **Load knowledge progressively** — only what's needed, when it's needed
21
-
22
- The result: Claude works like a trained specialist who understands both the domain AND your specific systems.
23
-
24
- ## Installation
25
-
26
- ### Claude Desktop (Recommended)
27
-
28
- The packaged `.zip` file is included in this repository for easy installation:
29
-
30
- 1. Download `create-expert-skill-v2.2.zip` from this repository
31
- 2. Open Claude Desktop → **Settings** → **Capabilities**
32
- 3. Under Skills, click **Upload Skill**
33
- 4. Drag and drop the `.zip` file (no need to unzip)
34
-
35
- ### Claude Code
36
-
37
- Skills can be installed at user or project level:
38
-
39
- **Personal skills** (available in all projects):
40
- ```bash
41
- # Unzip and copy to your personal skills directory
42
- unzip create-expert-skill-v2.2.zip -d ~/.claude/skills/
43
- ```
44
-
45
- **Project skills** (shared with team via git):
46
- ```bash
47
- # Unzip into your project's .claude/skills/ directory
48
- unzip create-expert-skill-v2.2.zip -d ./.claude/skills/
49
- git add .claude/skills/create-expert-skill
50
- git commit -m "Add create-expert-skill"
51
- ```
52
-
53
- Claude Code automatically discovers skills in these locations.
54
-
55
- ### Claude Agent SDK
56
-
57
- For programmatic usage with the Agent SDK:
58
-
59
- 1. Create skills directory in your project: `.claude/skills/`
60
- 2. Unzip the skill into that directory
61
- 3. Enable skills in your configuration by adding `"Skill"` to `allowed_tools`
62
-
63
- ```python
64
- from claude_agent_sdk import query, ClaudeAgentOptions
65
-
66
- options = ClaudeAgentOptions(
67
- allowed_tools=["Skill", "Read", "Write", "Bash"],
68
- # Skills are auto-discovered from .claude/skills/
69
- )
70
- ```
71
-
72
- See [Agent Skills in the SDK](https://platform.claude.com/docs/en/agent-sdk/skills) for full documentation.
73
-
74
- ## Usage
75
-
76
- Start a conversation:
77
- > "I want to create a skill for validating LEDES billing files"
78
-
79
- Claude guides you through:
80
- ```
81
- Assess → Is this worth creating? (3+ uses, consistent procedure)
82
- Discover → What's the domain expertise? What are the system ontologies?
83
- Design → What needs scripts vs guidance vs reference material?
84
- Create → Generate the skill
85
- Refine → Iterate until complete
86
- Ship → Package for deployment
87
- ```
88
-
89
- ## How It Works
90
-
91
- ### Two Knowledge Streams
92
-
93
- Production-ready skills require BOTH:
94
-
95
- **Domain Expertise** — Industry knowledge that applies universally:
96
- - Standards and their versions (e.g., LEDES 98B vs XML 2.0)
97
- - Professional conventions and edge cases
98
- - Validation rules from specifications
99
-
100
- **Ontology Understanding** — System-specific structures:
101
- - Company policies and constraints
102
- - Entity relationships (timekeepers → IDs → rates)
103
- - Data format variations unique to your systems
104
-
105
- ### Progressive Disclosure Architecture
106
-
107
- Skills load knowledge in layers, not all at once:
108
-
109
- ```
110
- Layer 0 (~25 tokens) → Description only, always visible
111
- Layer 1 (~500 tokens) → Core procedures in SKILL.md, loaded when triggered
112
- Layer 2 (~1000+ tokens) → Deep reference in resources/, loaded selectively
113
- ```
114
-
115
- **Why this matters:** A 2,000-token skill that loads everything wastes context. A layered skill loads 25 tokens until needed, then 500, then more only if required.
116
-
117
- ### Deterministic Scripts
118
-
119
- Anything that can be computed exactly should be:
120
-
121
- | Task | Without Script | With Script |
122
- |------|---------------|-------------|
123
- | Validate date format | LLM guesses (sometimes wrong) | `python validate.py` (always right) |
124
- | Sum line items | LLM approximates | Script calculates exactly |
125
- | Check against schema | LLM interprets | Script returns pass/fail |
126
-
127
- Scripts run at **zero token cost** — Claude executes them and uses the output.
128
-
129
- ### Skill Structure
130
-
131
- ```
132
- my-skill/
133
- ├── SKILL.md # Layer 1: Core procedures (300-500 tokens)
134
- ├── scripts/ # Layer 0: Deterministic automation
135
- │ └── validate.py
136
- └── resources/ # Layer 2: Deep reference (loaded selectively)
137
- ├── schemas/
138
- └── ADVANCED.md
139
- ```
140
-
141
- ## Token Optimization
142
-
143
- | Technique | Before | After | Savings |
144
- |-----------|--------|-------|---------|
145
- | Scripts | 500 tokens explaining logic | `python scripts/validate.py` | ~450 |
146
- | Reference files | Inline schema (200 tokens) | Link to file | ~185 |
147
- | Layer 2 split | Everything in SKILL.md | Split to resources/ | ~750 |
148
-
149
- ## Packaging
150
-
151
- **This skill includes an automated zipping procedure** In most cases, it runs on its own once the expert skill is finished, returning the plug-and-play .zip of the skill directly in conversation. If this doesn't run automatically, simply ask Claude to deliver the packaged skill.
152
-
153
- ## Files
154
-
155
- ```
156
- create-expert-skill/
157
- ├── SKILL.md # Main skill (Layer 1)
158
- ├── README.md # This file
159
- ├── LICENSE # MIT
160
- ├── create-expert-skill-v2.2.zip # Ready-to-install package
161
- ├── scripts/
162
- │ ├── package_skill.py # Packaging automation
163
- │ └── README.md
164
- └── resources/
165
- ├── templates/
166
- │ └── TEMPLATES.md # Skill templates (minimal/enhanced/script)
167
- └── examples/
168
- └── EXAMPLES.md # Domain patterns (billing, API, schemas)
169
- ```
170
-
171
- ## Contributing
172
-
173
- Found a bug or want to improve the skill?
174
- - Open an issue for bugs or feature requests
175
- - PRs welcome for templates, examples, or documentation
176
-
177
- ## License
178
-
179
- MIT — use freely, modify as needed.
180
-
181
- ## Author
182
-
183
- [Vlad-Alexandru Nicolescu](https://github.com/vnicolescu)
184
-
185
- ---
186
-
187
- **Version:** 2.2
188
- **Tested with:** Claude Desktop
@@ -1,131 +0,0 @@
1
- ---
2
- name: create-expert-skill
3
- description: Create production-ready skills from expert knowledge. Extracts domain expertise and system ontologies, uses scripts for deterministic work, loads knowledge progressively. Use when building skills that must work reliably in production.
4
- version: 2.2
5
- ---
6
-
7
- # Expert Skill Creation
8
-
9
- Transform expert knowledge into production-ready skills that combine domain expertise with system-specific understanding.
10
-
11
- ## Why Skills Fail in Production
12
-
13
- AI assistants fail not because they lack intelligence, but because they lack:
14
-
15
- 1. **Domain Expertise** — Industry-specific rules, edge cases, unwritten conventions
16
- 2. **Ontology Understanding** — How YOUR systems, data structures, and workflows actually work
17
-
18
- **Both are required.** Domain knowledge without system context produces generic output. System knowledge without domain expertise produces structurally correct but semantically wrong results.
19
-
20
- ## Workflow
21
-
22
- ```
23
- Assess → Discover (Expertise + Ontology) → Design → Create → Refine → Ship
24
- ```
25
-
26
- ## Quick Assessment
27
-
28
- **Create a skill when:**
29
- - Used 3+ times (or will be)
30
- - Follows consistent procedure
31
- - Saves >300 tokens per use
32
- - Requires specialized knowledge not in Claude's training
33
- - Must produce trusted output (not "close enough")
34
-
35
- **Don't create for:** one-time tasks, basic knowledge Claude already has, rapidly changing content.
36
-
37
- ## Discovery: Two Streams
38
-
39
- ### Stream 1: Domain Expertise
40
-
41
- Deep knowledge that transcends any specific company:
42
- - Industry standards and their versions
43
- - Professional conventions and best practices
44
- - Edge cases only practitioners know
45
- - Validation rules from specifications
46
-
47
- *Example (LEDES validation):* LEDES 98B vs XML 2.0 formats, UTBMS code taxonomy, date format requirements, required vs optional fields.
48
-
49
- ### Stream 2: Ontology Understanding
50
-
51
- How the skill maps to specific systems and organizations:
52
- - Company-specific policies and constraints
53
- - Data structures and identifiers unique to the system
54
- - Cross-references between entities (timekeepers → IDs → rates)
55
- - Workflow states and transitions
56
-
57
- *Example (LEDES validation):* Firm-specific timekeeper codes, matter numbering conventions, approved billing rates, outside counsel guideline requirements.
58
-
59
- ### Discovery Questions
60
-
61
- When starting, I'll ask about:
62
- 1. **Domain & Purpose** — What problem? What industry standards apply?
63
- 2. **Ontology Requirements** — What system-specific structures must the skill understand?
64
- 3. **Content Source** — Conversation, docs, specifications, or files to distill from?
65
- 4. **Automation Potential** — What can be deterministic (scripts)? What needs interpretation (LLM)?
66
- 5. **Complexity Level** — Simple (SKILL.md only), Enhanced (+scripts), or Full (+resources)?
67
-
68
- ## Skill Architecture
69
-
70
- ```
71
- skill-name/
72
- ├── SKILL.md # Layer 1: Core (300-500 tokens)
73
- ├── scripts/ # Layer 0: Automation (0 tokens to run)
74
- │ └── validate.py
75
- └── resources/ # Layer 2: Details (loaded selectively)
76
- └── ADVANCED.md
77
- ```
78
-
79
- **Layer 0** (Scripts): Free execution, structured JSON output
80
- **Layer 1** (SKILL.md): Loaded when triggered - keep lean
81
- **Layer 2** (Resources): Fetched only when specific section needed
82
-
83
- ## Token Optimization
84
-
85
- | Technique | Instead of | Do this | Savings |
86
- |-----------|-----------|---------|---------|
87
- | Scripts | 500 tokens explaining validation | `python scripts/validate.py` | ~450 tokens |
88
- | Reference | Inline schema (200 tokens) | Link to `resources/schema.json` | ~185 tokens |
89
- | Layer 2 | Everything in SKILL.md | Link to `resources/ADVANCED.md` | ~750 tokens |
90
-
91
- ## Description Formula
92
-
93
- `<Action> <Object> for <Purpose>. Use when <Trigger>.`
94
-
95
- Example: "Validate billing data for system migration. Use before importing invoices."
96
-
97
- ## Shipping
98
-
99
- When content is finalized:
100
-
101
- ```bash
102
- python scripts/package_skill.py skill-name 1.0
103
- ```
104
-
105
- Creates `skill-name-v1.0.zip` with:
106
- - DIRECTORY_STRUCTURE.txt (auto-generated)
107
- - README.md with deployment instructions
108
- - All skill files properly organized
109
-
110
- ## Templates & Examples
111
-
112
- See `resources/templates/` for:
113
- - Minimal skill template
114
- - Enhanced skill template
115
- - Script template
116
-
117
- See `resources/examples/` for domain-specific patterns.
118
-
119
- ## Quality Checklist
120
-
121
- Before shipping:
122
- - [ ] Description <30 tokens
123
- - [ ] SKILL.md <500 tokens (Layer 1)
124
- - [ ] Scripts for deterministic operations
125
- - [ ] Advanced content in resources/ (Layer 2)
126
- - [ ] Version in frontmatter
127
- - [ ] All referenced files exist
128
-
129
- ---
130
-
131
- **Version:** 2.2 | **Target:** <500 tokens Layer 1