claude-skills-cli 0.0.1
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/README.md +455 -0
- package/dist/commands/init.js +70 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/package.js +133 -0
- package/dist/commands/package.js.map +1 -0
- package/dist/commands/validate.js +48 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/templates.js +90 -0
- package/dist/core/templates.js.map +1 -0
- package/dist/core/validator.js +185 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/fs.js +25 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/output.js +9 -0
- package/dist/utils/output.js.map +1 -0
- package/docs/SKILL-DEVELOPMENT.md +457 -0
- package/docs/SKILL-EXAMPLES.md +518 -0
- package/docs/SKILLS-ARCHITECTURE.md +380 -0
- package/package.json +58 -0
- package/skills/skill-creator/SKILL.md +345 -0
- package/skills/skill-creator/references/skill-examples.md +403 -0
- package/skills/skill-creator/references/writing-guide.md +594 -0
package/README.md
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
# claude-skills-cli
|
|
2
|
+
|
|
3
|
+
TypeScript CLI toolkit for creating, validating, and packaging Claude skills.
|
|
4
|
+
|
|
5
|
+
**Status:** š§ In Development - See implementation plan below
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What This Is
|
|
10
|
+
|
|
11
|
+
A portable command-line tool for managing Claude Agent Skills, inspired by tools like `create-next-app` and `create-vite`. Install once, use anywhere:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpx claude-skills-cli init --name my-skill --description "..."
|
|
15
|
+
pnpx claude-skills-cli validate .claude/skills/my-skill
|
|
16
|
+
pnpx claude-skills-cli package .claude/skills/my-skill
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This replaces the Python scripts that were previously in project `.claude/scripts/` directories.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Repository Structure (Planned)
|
|
24
|
+
|
|
25
|
+
Following the **mcpick** pattern:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
claude-skills-cli/
|
|
29
|
+
āāā package.json # CLI package config
|
|
30
|
+
āāā tsconfig.json # TypeScript ES modules config
|
|
31
|
+
āāā README.md # This file
|
|
32
|
+
āāā .gitignore # Ignore node_modules, dist, etc.
|
|
33
|
+
āāā .prettierrc # Code formatting
|
|
34
|
+
āāā .changeset/ # Version management
|
|
35
|
+
ā āāā README.md
|
|
36
|
+
ā āāā config.json
|
|
37
|
+
āāā src/
|
|
38
|
+
ā āāā index.ts # CLI entry (#!/usr/bin/env node)
|
|
39
|
+
ā āāā types.ts # TypeScript type definitions
|
|
40
|
+
ā āāā commands/
|
|
41
|
+
ā ā āāā init.ts # Create new skill structure
|
|
42
|
+
ā ā āāā validate.ts # Validate skill format
|
|
43
|
+
ā ā āāā package.ts # Package skill to zip
|
|
44
|
+
ā āāā core/
|
|
45
|
+
ā ā āāā templates.ts # SKILL.md templates as strings
|
|
46
|
+
ā ā āāā validator.ts # Validation logic (class-based)
|
|
47
|
+
ā āāā utils/
|
|
48
|
+
ā āāā fs.ts # File system helpers
|
|
49
|
+
ā āāā output.ts # Emoji/formatting (chalk)
|
|
50
|
+
āāā templates/ # Copied from devhub-crm
|
|
51
|
+
ā āāā SKILL-TEMPLATE.md
|
|
52
|
+
ā āāā skill-structure/
|
|
53
|
+
ā āāā README.md
|
|
54
|
+
ā āāā references/
|
|
55
|
+
ā āāā scripts/
|
|
56
|
+
ā āāā assets/
|
|
57
|
+
āāā docs/ # Copied from devhub-crm
|
|
58
|
+
ā āāā SKILLS-ARCHITECTURE.md
|
|
59
|
+
ā āāā SKILL-DEVELOPMENT.md
|
|
60
|
+
ā āāā SKILL-EXAMPLES.md
|
|
61
|
+
āāā skills/ # Portable example skills
|
|
62
|
+
āāā skill-creator/ # Meta-skill from devhub-crm
|
|
63
|
+
āāā SKILL.md
|
|
64
|
+
āāā references/
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Files to Move from devhub-crm
|
|
70
|
+
|
|
71
|
+
The `.claude/` directory was copied wholesale, but needs reorganization:
|
|
72
|
+
|
|
73
|
+
### ā
Keep and Move to Root:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
devhub-crm/.claude/docs/ ā claude-skills-cli/docs/
|
|
77
|
+
devhub-crm/.claude/templates/ ā claude-skills-cli/templates/
|
|
78
|
+
devhub-crm/.claude/skills/skill-creator/ ā claude-skills-cli/skills/skill-creator/
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### ā
Convert to TypeScript:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
devhub-crm/.claude/scripts/init_skill.py ā src/commands/init.ts
|
|
85
|
+
devhub-crm/.claude/scripts/validate_skill.py ā src/commands/validate.ts
|
|
86
|
+
devhub-crm/.claude/scripts/package_skill.py ā src/commands/package.ts
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### ā Delete (Not Needed):
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
devhub-crm/.claude/settings.local.json # Project-specific
|
|
93
|
+
devhub-crm/.claude/skills/database-patterns/ # Project-specific
|
|
94
|
+
devhub-crm/.claude/TYPESCRIPT-CONVERSION-PROMPT.md # Completed
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## package.json Configuration
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"name": "claude-skills-cli",
|
|
104
|
+
"version": "0.0.1",
|
|
105
|
+
"description": "CLI toolkit for creating and managing Claude Agent Skills",
|
|
106
|
+
"type": "module",
|
|
107
|
+
"main": "./dist/index.js",
|
|
108
|
+
"bin": {
|
|
109
|
+
"claude-skills-cli": "./dist/index.js"
|
|
110
|
+
},
|
|
111
|
+
"engines": {
|
|
112
|
+
"node": ">=22.0.0"
|
|
113
|
+
},
|
|
114
|
+
"scripts": {
|
|
115
|
+
"build": "tsc",
|
|
116
|
+
"dev": "tsc --watch",
|
|
117
|
+
"start": "node ./dist/index.js",
|
|
118
|
+
"format": "prettier --write .",
|
|
119
|
+
"format:check": "prettier --check .",
|
|
120
|
+
"changeset": "changeset",
|
|
121
|
+
"version": "changeset version",
|
|
122
|
+
"release": "pnpm run build && changeset publish"
|
|
123
|
+
},
|
|
124
|
+
"keywords": ["claude", "skills", "cli", "agent", "anthropic", "claude-code"],
|
|
125
|
+
"author": "Scott Spence",
|
|
126
|
+
"license": "MIT",
|
|
127
|
+
"dependencies": {
|
|
128
|
+
"@clack/prompts": "^0.11.0",
|
|
129
|
+
"chalk": "^5.3.0",
|
|
130
|
+
"archiver": "^7.0.0"
|
|
131
|
+
},
|
|
132
|
+
"devDependencies": {
|
|
133
|
+
"@changesets/cli": "^2.29.7",
|
|
134
|
+
"@types/node": "^24.7.0",
|
|
135
|
+
"@types/archiver": "^6.0.0",
|
|
136
|
+
"prettier": "^3.6.2",
|
|
137
|
+
"typescript": "^5.9.3"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## tsconfig.json Configuration
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"compilerOptions": {
|
|
149
|
+
"target": "ES2022",
|
|
150
|
+
"module": "nodenext",
|
|
151
|
+
"moduleResolution": "nodenext",
|
|
152
|
+
"strict": true,
|
|
153
|
+
"outDir": "./dist",
|
|
154
|
+
"sourceMap": true,
|
|
155
|
+
"esModuleInterop": true,
|
|
156
|
+
"allowSyntheticDefaultImports": true,
|
|
157
|
+
"skipLibCheck": true
|
|
158
|
+
},
|
|
159
|
+
"include": ["src/**/*"],
|
|
160
|
+
"exclude": ["node_modules", "dist"]
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Dependencies Explained
|
|
167
|
+
|
|
168
|
+
### Runtime Dependencies:
|
|
169
|
+
|
|
170
|
+
- **@clack/prompts** - Interactive CLI prompts (like mcpick uses)
|
|
171
|
+
- **chalk** - Terminal string styling and colors
|
|
172
|
+
- **archiver** - Create zip files (replaces Python's zipfile)
|
|
173
|
+
|
|
174
|
+
### Dev Dependencies:
|
|
175
|
+
|
|
176
|
+
- **@changesets/cli** - Version management and changelog
|
|
177
|
+
- **@types/node** - TypeScript types for Node.js
|
|
178
|
+
- **@types/archiver** - TypeScript types for archiver
|
|
179
|
+
- **prettier** - Code formatting
|
|
180
|
+
- **typescript** - TypeScript compiler
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## CLI Interface (Must Match Python Version)
|
|
185
|
+
|
|
186
|
+
### Command: init
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
claude-skills init --name my-skill --description "What it does and when to use it"
|
|
190
|
+
claude-skills init --path /custom/path/my-skill
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Creates:**
|
|
194
|
+
|
|
195
|
+
- SKILL.md with YAML frontmatter
|
|
196
|
+
- README.md
|
|
197
|
+
- references/detailed-guide.md
|
|
198
|
+
- scripts/example.py (executable)
|
|
199
|
+
- assets/ directory
|
|
200
|
+
|
|
201
|
+
**Output:**
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
ā
Skill created at: .claude/skills/my-skill
|
|
205
|
+
|
|
206
|
+
Next steps:
|
|
207
|
+
1. Edit .claude/skills/my-skill/SKILL.md with your skill instructions
|
|
208
|
+
2. Add detailed documentation to references/
|
|
209
|
+
3. Add executable scripts to scripts/
|
|
210
|
+
4. Remove example files you don't need
|
|
211
|
+
|
|
212
|
+
Validate with: claude-skills validate .claude/skills/my-skill
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Command: validate
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
claude-skills validate .claude/skills/my-skill
|
|
219
|
+
claude-skills validate .claude/skills/my-skill --strict
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Checks:**
|
|
223
|
+
|
|
224
|
+
- SKILL.md exists
|
|
225
|
+
- YAML frontmatter format
|
|
226
|
+
- Required fields (name, description)
|
|
227
|
+
- Name format (kebab-case, max 64 chars)
|
|
228
|
+
- Description length (max 1024 chars)
|
|
229
|
+
- References mentioned in SKILL.md
|
|
230
|
+
- Scripts are executable
|
|
231
|
+
- No TODO placeholders
|
|
232
|
+
|
|
233
|
+
**Output:**
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
š Validating skill: my-skill
|
|
237
|
+
============================================================
|
|
238
|
+
|
|
239
|
+
ā ļø Warnings:
|
|
240
|
+
ā ļø Reference file 'schema.md' not mentioned in SKILL.md
|
|
241
|
+
|
|
242
|
+
ā
Skill is valid (with warnings)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Exit codes:**
|
|
246
|
+
|
|
247
|
+
- 0 = success
|
|
248
|
+
- 1 = validation failed
|
|
249
|
+
- 1 with --strict = warnings treated as errors
|
|
250
|
+
|
|
251
|
+
### Command: package
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
claude-skills package .claude/skills/my-skill
|
|
255
|
+
claude-skills package .claude/skills/my-skill --output dist/
|
|
256
|
+
claude-skills package .claude/skills/my-skill --skip-validation
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Creates:**
|
|
260
|
+
|
|
261
|
+
- Zip file with skill contents
|
|
262
|
+
- Excludes hidden files, .pyc, **pycache**, etc.
|
|
263
|
+
- Runs validation first (unless --skip-validation)
|
|
264
|
+
|
|
265
|
+
**Output:**
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
š Validating skill...
|
|
269
|
+
ā
Skill is valid!
|
|
270
|
+
|
|
271
|
+
š¦ Packaging skill: my-skill
|
|
272
|
+
+ my-skill/SKILL.md
|
|
273
|
+
+ my-skill/README.md
|
|
274
|
+
+ my-skill/references/detailed-guide.md
|
|
275
|
+
|
|
276
|
+
ā
Skill packaged successfully!
|
|
277
|
+
File: dist/my-skill.zip
|
|
278
|
+
Size: 12.3 KB
|
|
279
|
+
|
|
280
|
+
š¤ Upload to Claude.ai: Settings > Features > Skills > Upload
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Implementation Roadmap
|
|
286
|
+
|
|
287
|
+
### Phase 1: Setup (You're here!)
|
|
288
|
+
|
|
289
|
+
- [x] Create claude-skills-cli repo
|
|
290
|
+
- [x] Copy .claude/ from devhub-crm
|
|
291
|
+
- [ ] Create package.json
|
|
292
|
+
- [ ] Create tsconfig.json
|
|
293
|
+
- [ ] Setup .gitignore, .prettierrc
|
|
294
|
+
- [ ] Install dependencies: `pnpm install`
|
|
295
|
+
|
|
296
|
+
### Phase 2: Reorganize Files
|
|
297
|
+
|
|
298
|
+
- [ ] Move `docs/` to root
|
|
299
|
+
- [ ] Move `templates/` to root
|
|
300
|
+
- [ ] Move `skills/skill-creator/` to root
|
|
301
|
+
- [ ] Delete `.claude/settings.local.json`
|
|
302
|
+
- [ ] Delete `.claude/skills/database-patterns/`
|
|
303
|
+
|
|
304
|
+
### Phase 3: Convert Python ā TypeScript
|
|
305
|
+
|
|
306
|
+
#### init.ts (from init_skill.py)
|
|
307
|
+
|
|
308
|
+
- [ ] Import types, fs, path, chalk
|
|
309
|
+
- [ ] Create template strings (SKILL.md, README.md, etc.)
|
|
310
|
+
- [ ] Implement createSkill() function
|
|
311
|
+
- Use fs.mkdirSync(path, { recursive: true })
|
|
312
|
+
- Use fs.writeFileSync()
|
|
313
|
+
- Use fs.chmodSync(scriptPath, 0o755) for executable
|
|
314
|
+
- [ ] Use @clack/prompts for interactive mode (optional)
|
|
315
|
+
- [ ] Match Python output format exactly (emoji, messages)
|
|
316
|
+
|
|
317
|
+
#### validate.ts (from validate_skill.py)
|
|
318
|
+
|
|
319
|
+
- [ ] Create SkillValidator class
|
|
320
|
+
- errors: string[]
|
|
321
|
+
- warnings: string[]
|
|
322
|
+
- [ ] Implement validation methods:
|
|
323
|
+
- validateDirectory()
|
|
324
|
+
- validateSkillMd() - parse YAML frontmatter
|
|
325
|
+
- validateReferences()
|
|
326
|
+
- validateScripts() - check executable with fs.statSync()
|
|
327
|
+
- validateAssets()
|
|
328
|
+
- [ ] Use chalk for colored output
|
|
329
|
+
- [ ] Match Python emoji output exactly
|
|
330
|
+
- [ ] Support --strict flag
|
|
331
|
+
|
|
332
|
+
#### package.ts (from package_skill.py)
|
|
333
|
+
|
|
334
|
+
- [ ] Import archiver for zip creation
|
|
335
|
+
- [ ] Call validate.ts first (child_process.spawnSync)
|
|
336
|
+
- [ ] Create zip with exclusions:
|
|
337
|
+
- Hidden files (starts with .)
|
|
338
|
+
- .pyc, .pyo, .swp, ~
|
|
339
|
+
- **pycache**, .DS_Store
|
|
340
|
+
- [ ] Report file size in KB
|
|
341
|
+
- [ ] Match Python output format
|
|
342
|
+
|
|
343
|
+
### Phase 4: CLI Entry Point
|
|
344
|
+
|
|
345
|
+
#### index.ts
|
|
346
|
+
|
|
347
|
+
- [ ] Add shebang: `#!/usr/bin/env node`
|
|
348
|
+
- [ ] Import @clack/prompts
|
|
349
|
+
- [ ] Import commands (init, validate, package)
|
|
350
|
+
- [ ] Create interactive menu (like mcpick)
|
|
351
|
+
- "Create new skill"
|
|
352
|
+
- "Validate skill"
|
|
353
|
+
- "Package skill"
|
|
354
|
+
- "Exit"
|
|
355
|
+
- [ ] Handle command-line arguments (for non-interactive)
|
|
356
|
+
- [ ] Error handling with try/catch
|
|
357
|
+
|
|
358
|
+
### Phase 5: Testing
|
|
359
|
+
|
|
360
|
+
- [ ] Build: `pnpm build`
|
|
361
|
+
- [ ] Test init: `node dist/index.js init --name test-skill`
|
|
362
|
+
- [ ] Test validate: `node dist/index.js validate skills/skill-creator`
|
|
363
|
+
- [ ] Test package: `node dist/index.js package skills/skill-creator`
|
|
364
|
+
- [ ] Verify output matches Python version
|
|
365
|
+
|
|
366
|
+
### Phase 6: Publishing
|
|
367
|
+
|
|
368
|
+
- [ ] Setup .changeset config
|
|
369
|
+
- [ ] Add initial changeset
|
|
370
|
+
- [ ] Test with `pnpx` locally
|
|
371
|
+
- [ ] Publish to npm: `pnpm release`
|
|
372
|
+
- [ ] Update devhub-crm to use `pnpx claude-skills-cli`
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Design Decisions
|
|
377
|
+
|
|
378
|
+
### Why @clack/prompts instead of commander?
|
|
379
|
+
|
|
380
|
+
- mcpick uses @clack/prompts for beautiful interactive menus
|
|
381
|
+
- Provides better UX than raw commander arguments
|
|
382
|
+
- Still support non-interactive mode with args
|
|
383
|
+
|
|
384
|
+
### Why archiver instead of node:zlib?
|
|
385
|
+
|
|
386
|
+
- archiver is battle-tested for creating zips
|
|
387
|
+
- Handles file permissions, directory structure
|
|
388
|
+
- Direct replacement for Python's zipfile
|
|
389
|
+
|
|
390
|
+
### Why chalk for colors?
|
|
391
|
+
|
|
392
|
+
- Match Python's emoji output (ā
ā ā ļø)
|
|
393
|
+
- Better terminal color support
|
|
394
|
+
- Widely used, stable
|
|
395
|
+
|
|
396
|
+
### Why ES modules (type: "module")?
|
|
397
|
+
|
|
398
|
+
- Modern Node.js best practice
|
|
399
|
+
- Matches mcpick setup
|
|
400
|
+
- Better tree-shaking, cleaner imports
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Testing Checklist
|
|
405
|
+
|
|
406
|
+
Before publishing v1.0.0:
|
|
407
|
+
|
|
408
|
+
- [ ] All three commands work (init, validate, package)
|
|
409
|
+
- [ ] Output matches Python version exactly
|
|
410
|
+
- [ ] Exit codes match (0 = success, 1 = error)
|
|
411
|
+
- [ ] Emoji indicators work (ā
ā ā ļø)
|
|
412
|
+
- [ ] --strict mode works on validate
|
|
413
|
+
- [ ] --skip-validation works on package
|
|
414
|
+
- [ ] Created skills validate successfully
|
|
415
|
+
- [ ] Packaged zips can be uploaded to Claude.ai
|
|
416
|
+
- [ ] Works via `pnpx claude-skills-cli`
|
|
417
|
+
- [ ] Works when installed globally
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Resources
|
|
422
|
+
|
|
423
|
+
### Official Anthropic Documentation:
|
|
424
|
+
|
|
425
|
+
- [Agent Skills Overview](https://www.anthropic.com/news/skills)
|
|
426
|
+
- [Engineering Blog: Agent Skills](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills)
|
|
427
|
+
- [Claude Docs: Skills](https://docs.claude.com/en/docs/agents-and-tools/agent-skills/overview)
|
|
428
|
+
- [Anthropic Skills Repo](https://github.com/anthropics/skills)
|
|
429
|
+
|
|
430
|
+
### Included Documentation:
|
|
431
|
+
|
|
432
|
+
- [docs/SKILLS-ARCHITECTURE.md](docs/SKILLS-ARCHITECTURE.md) - Progressive disclosure system
|
|
433
|
+
- [docs/SKILL-DEVELOPMENT.md](docs/SKILL-DEVELOPMENT.md) - 6-step creation workflow
|
|
434
|
+
- [docs/SKILL-EXAMPLES.md](docs/SKILL-EXAMPLES.md) - Real-world examples
|
|
435
|
+
|
|
436
|
+
### Reference Implementation:
|
|
437
|
+
|
|
438
|
+
- [mcpick](https://github.com/spences10/mcpick) - Similar CLI structure to follow
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Notes for Next Chat Session
|
|
443
|
+
|
|
444
|
+
1. **Start with setup:** Create package.json and tsconfig.json first
|
|
445
|
+
2. **Install deps:** `pnpm install` to get @clack/prompts, chalk, archiver
|
|
446
|
+
3. **Reorganize files:** Move docs/, templates/, skills/ from .claude/ to root
|
|
447
|
+
4. **Convert Python scripts one by one:** Start with init.ts (simplest), then validate.ts, then package.ts
|
|
448
|
+
5. **Create index.ts:** Wire up commands with @clack/prompts menu
|
|
449
|
+
6. **Test everything:** Build and run against skill-creator to verify
|
|
450
|
+
|
|
451
|
+
**Key principle:** Match Python output and behavior EXACTLY. Users should not notice any difference except it's faster and more portable.
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
**Ready to build!** š
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { SKILL_MD_TEMPLATE, REFERENCE_TEMPLATE, SCRIPT_TEMPLATE, README_TEMPLATE, } from '../core/templates.js';
|
|
3
|
+
import { ensure_dir, write_file, make_executable, to_title_case, is_lowercase, } from '../utils/fs.js';
|
|
4
|
+
import { success, error } from '../utils/output.js';
|
|
5
|
+
export function init_command(options) {
|
|
6
|
+
let skill_path;
|
|
7
|
+
let name;
|
|
8
|
+
let description;
|
|
9
|
+
// Determine path and name
|
|
10
|
+
if (options.path) {
|
|
11
|
+
skill_path = options.path;
|
|
12
|
+
name = skill_path.split('/').pop() || '';
|
|
13
|
+
description = options.description || 'TODO: Add description';
|
|
14
|
+
}
|
|
15
|
+
else if (options.name) {
|
|
16
|
+
name = options.name;
|
|
17
|
+
description = options.description || 'TODO: Add description';
|
|
18
|
+
// Default to .claude/skills/ directory
|
|
19
|
+
skill_path = join('.claude', 'skills', name);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
error('Either --name or --path must be provided');
|
|
23
|
+
console.log('\nUsage:');
|
|
24
|
+
console.log(' claude-skills init --name my-skill --description "Description"');
|
|
25
|
+
console.log(' claude-skills init --path /custom/path/my-skill');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
// Validate name format
|
|
29
|
+
const alphanumeric_check = name.replace(/-/g, '').replace(/_/g, '');
|
|
30
|
+
if (!/^[a-z0-9]+$/.test(alphanumeric_check)) {
|
|
31
|
+
error(`Skill name must be kebab-case alphanumeric: ${name}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
if (!is_lowercase(name)) {
|
|
35
|
+
error(`Skill name must be lowercase: ${name}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// Create skill
|
|
39
|
+
create_skill(skill_path, name, description);
|
|
40
|
+
}
|
|
41
|
+
function create_skill(path, name, description) {
|
|
42
|
+
// Create directories
|
|
43
|
+
ensure_dir(path);
|
|
44
|
+
ensure_dir(join(path, 'references'));
|
|
45
|
+
ensure_dir(join(path, 'scripts'));
|
|
46
|
+
ensure_dir(join(path, 'assets'));
|
|
47
|
+
// Create SKILL.md
|
|
48
|
+
const title = to_title_case(name);
|
|
49
|
+
const skill_md = SKILL_MD_TEMPLATE(name, description, title);
|
|
50
|
+
write_file(join(path, 'SKILL.md'), skill_md);
|
|
51
|
+
// Create example reference
|
|
52
|
+
const reference_md = REFERENCE_TEMPLATE(title);
|
|
53
|
+
write_file(join(path, 'references', 'detailed-guide.md'), reference_md);
|
|
54
|
+
// Create example script
|
|
55
|
+
const script_py = SCRIPT_TEMPLATE('example.py');
|
|
56
|
+
const script_path = join(path, 'scripts', 'example.py');
|
|
57
|
+
write_file(script_path, script_py);
|
|
58
|
+
make_executable(script_path);
|
|
59
|
+
// Create README
|
|
60
|
+
const readme_md = README_TEMPLATE(title, description);
|
|
61
|
+
write_file(join(path, 'README.md'), readme_md);
|
|
62
|
+
success(`Skill created at: ${path}`);
|
|
63
|
+
console.log('\nNext steps:');
|
|
64
|
+
console.log(`1. Edit ${path}/SKILL.md with your skill instructions`);
|
|
65
|
+
console.log(`2. Add detailed documentation to references/`);
|
|
66
|
+
console.log(`3. Add executable scripts to scripts/`);
|
|
67
|
+
console.log(`4. Remove example files you don't need`);
|
|
68
|
+
console.log(`\nValidate with: claude-skills validate ${path}`);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { basename, join } from 'path';
|
|
2
|
+
import { existsSync, statSync, readdirSync } from 'fs';
|
|
3
|
+
import archiver from 'archiver';
|
|
4
|
+
import { createWriteStream } from 'fs';
|
|
5
|
+
import { SkillValidator } from '../core/validator.js';
|
|
6
|
+
import { ensure_dir } from '../utils/fs.js';
|
|
7
|
+
import { error, success, package_, upload, search, step, } from '../utils/output.js';
|
|
8
|
+
function validate_skill(skill_path) {
|
|
9
|
+
search('Validating skill...');
|
|
10
|
+
const validator = new SkillValidator(skill_path);
|
|
11
|
+
const result = validator.validate_all();
|
|
12
|
+
if (result.errors.length > 0) {
|
|
13
|
+
console.log('\nā Errors:');
|
|
14
|
+
for (const err of result.errors) {
|
|
15
|
+
console.log(` ${err}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (result.warnings.length > 0) {
|
|
19
|
+
console.log('\nā ļø Warnings:');
|
|
20
|
+
for (const warn of result.warnings) {
|
|
21
|
+
console.log(` ${warn}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (result.is_valid) {
|
|
25
|
+
success('Skill is valid!');
|
|
26
|
+
console.log('');
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
error('Validation failed. Fix errors before packaging.');
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function package_skill(skill_path, output_dir) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const skill_name = basename(skill_path);
|
|
37
|
+
const output_file = join(output_dir, `${skill_name}.zip`);
|
|
38
|
+
package_(`Packaging skill: ${skill_name}`);
|
|
39
|
+
// Ensure output directory exists
|
|
40
|
+
ensure_dir(output_dir);
|
|
41
|
+
// Create output stream
|
|
42
|
+
const output = createWriteStream(output_file);
|
|
43
|
+
const archive = archiver('zip', {
|
|
44
|
+
zlib: { level: 9 },
|
|
45
|
+
});
|
|
46
|
+
// Listen for all archive data to be written
|
|
47
|
+
output.on('close', () => {
|
|
48
|
+
resolve(output_file);
|
|
49
|
+
});
|
|
50
|
+
// Handle errors
|
|
51
|
+
archive.on('error', (err) => {
|
|
52
|
+
reject(err);
|
|
53
|
+
});
|
|
54
|
+
// Pipe archive data to the file
|
|
55
|
+
archive.pipe(output);
|
|
56
|
+
// Add files recursively
|
|
57
|
+
function add_files(dir_path, base_path) {
|
|
58
|
+
const items = readdirSync(dir_path);
|
|
59
|
+
for (const item of items) {
|
|
60
|
+
const item_path = join(dir_path, item);
|
|
61
|
+
const stats = statSync(item_path);
|
|
62
|
+
// Skip hidden files and directories
|
|
63
|
+
if (item.startsWith('.')) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Skip common temporary files
|
|
67
|
+
if (item.endsWith('.pyc') ||
|
|
68
|
+
item.endsWith('.pyo') ||
|
|
69
|
+
item.endsWith('.swp') ||
|
|
70
|
+
item.endsWith('~')) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (item === '__pycache__' || item === '.DS_Store') {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (stats.isDirectory()) {
|
|
77
|
+
add_files(item_path, base_path);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const relative_path = item_path.replace(base_path + '/', '');
|
|
81
|
+
archive.file(item_path, { name: relative_path });
|
|
82
|
+
step(`+ ${relative_path}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
add_files(skill_path, skill_path.substring(0, skill_path.lastIndexOf('/')));
|
|
87
|
+
// Finalize the archive
|
|
88
|
+
archive.finalize();
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export async function package_command(options) {
|
|
92
|
+
const { skill_path, output, skip_validation } = options;
|
|
93
|
+
// Validate path
|
|
94
|
+
if (!existsSync(skill_path)) {
|
|
95
|
+
error(`Skill directory does not exist: ${skill_path}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
const stats = statSync(skill_path);
|
|
99
|
+
if (!stats.isDirectory()) {
|
|
100
|
+
error(`Path is not a directory: ${skill_path}`);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
// Check for SKILL.md
|
|
104
|
+
if (!existsSync(join(skill_path, 'SKILL.md'))) {
|
|
105
|
+
error(`SKILL.md not found in ${skill_path}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
// Validate skill
|
|
109
|
+
if (!skip_validation) {
|
|
110
|
+
if (!validate_skill(skill_path)) {
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Package skill
|
|
115
|
+
try {
|
|
116
|
+
const output_dir = output || 'dist';
|
|
117
|
+
const output_file = await package_skill(skill_path, output_dir);
|
|
118
|
+
// Print success
|
|
119
|
+
const file_stats = statSync(output_file);
|
|
120
|
+
const size_kb = file_stats.size / 1024;
|
|
121
|
+
console.log('');
|
|
122
|
+
success('Skill packaged successfully!');
|
|
123
|
+
console.log(` File: ${output_file}`);
|
|
124
|
+
console.log(` Size: ${size_kb.toFixed(1)} KB`);
|
|
125
|
+
console.log('');
|
|
126
|
+
upload('Upload to Claude.ai: Settings > Features > Skills > Upload');
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
error(`Failed to package skill: ${err}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/commands/package.ts"],"names":[],"mappings":"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"}
|