skillsets 0.9.1 → 0.9.3

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 CHANGED
@@ -51,7 +51,7 @@ cli/
51
51
  | `search.ts` | Fuzzy search by name, description, tags | [Docs](./docs_cli/commands/search.md) |
52
52
  | `view.ts` | View a skillset README before installing | [Docs](./docs_cli/commands/view.md) |
53
53
  | `install.ts` | Install skillset via degit + MCP/deps warnings + verify checksums | [Docs](./docs_cli/commands/install.md) |
54
- | `init.ts` | Scaffold new skillset with QUICKSTART.md | [Docs](./docs_cli/commands/init.md) |
54
+ | `init.ts` | Scaffold new skillset with QUICKSTART_<NAME>.md | [Docs](./docs_cli/commands/init.md) |
55
55
  | `audit.ts` | Validate skillset + MCP + runtime deps before submission | [Docs](./docs_cli/commands/audit.md) |
56
56
  | `audit-report.ts` | Audit report generation utilities | [Docs](./docs_cli/commands/audit-report.md) |
57
57
  | `submit.ts` | Open PR to registry | [Docs](./docs_cli/commands/submit.md) |
@@ -74,17 +74,18 @@ function isBinaryFile(filePath) {
74
74
  return false;
75
75
  }
76
76
  }
77
- /** Find the README_<NAME>.md file in content/ */
78
- function findReadme(cwd) {
77
+ /** Find a content file matching <PREFIX>_<NAME>.md pattern */
78
+ function findContentFile(cwd, prefix) {
79
79
  const contentDir = join(cwd, 'content');
80
80
  if (!existsSync(contentDir))
81
81
  return null;
82
82
  const entries = readdirSync(contentDir);
83
- const readme = entries.find(f => /^README_[^/]+\.md$/i.test(f));
84
- return readme ? join(contentDir, readme) : null;
83
+ const pattern = new RegExp(`^${prefix}_[^/]+\\.md$`, 'i');
84
+ const match = entries.find(f => pattern.test(f));
85
+ return match ? join(contentDir, match) : null;
85
86
  }
86
87
  function scanReadmeLinks(cwd) {
87
- const readmePath = findReadme(cwd);
88
+ const readmePath = findContentFile(cwd, 'README');
88
89
  if (!readmePath)
89
90
  return [];
90
91
  const relativeLinks = [];
@@ -284,9 +285,9 @@ export async function audit(options = {}) {
284
285
  // 2. Required files
285
286
  spinner.text = 'Checking required files...';
286
287
  const hasContent = existsSync(join(cwd, 'content'));
287
- const hasReadme = !!findReadme(cwd);
288
- const hasQuickstart = existsSync(join(cwd, 'content', 'QUICKSTART.md'));
289
- const hasInstallNotes = existsSync(join(cwd, 'content', 'INSTALL_NOTES.md'));
288
+ const hasReadme = !!findContentFile(cwd, 'README');
289
+ const hasQuickstart = !!findContentFile(cwd, 'QUICKSTART');
290
+ const hasInstallNotes = !!findContentFile(cwd, 'INSTALL_NOTES');
290
291
  const hasLicense = existsSync(join(cwd, 'content', 'LICENSE'));
291
292
  const hasSkillsetYaml = existsSync(join(cwd, 'skillset.yaml'));
292
293
  const missingFiles = [];
@@ -297,9 +298,9 @@ export async function audit(options = {}) {
297
298
  if (!hasReadme)
298
299
  missingFiles.push('content/README_<NAME>.md');
299
300
  if (!hasQuickstart)
300
- missingFiles.push('content/QUICKSTART.md');
301
+ missingFiles.push('content/QUICKSTART_<NAME>.md');
301
302
  if (!hasInstallNotes)
302
- missingFiles.push('content/INSTALL_NOTES.md');
303
+ missingFiles.push('content/INSTALL_NOTES_<NAME>.md');
303
304
  if (!hasLicense)
304
305
  missingFiles.push('content/LICENSE');
305
306
  if (missingFiles.length === 0) {
@@ -315,7 +316,8 @@ export async function audit(options = {}) {
315
316
  // 2b. Install notes validation
316
317
  spinner.text = 'Validating install notes...';
317
318
  if (hasInstallNotes) {
318
- const installNotesContent = readFileSync(join(cwd, 'content', 'INSTALL_NOTES.md'), 'utf-8');
319
+ const installNotesPath = findContentFile(cwd, 'INSTALL_NOTES');
320
+ const installNotesContent = readFileSync(installNotesPath, 'utf-8');
319
321
  if (installNotesContent.length > 4000) {
320
322
  results.installNotes = {
321
323
  status: 'FAIL',
@@ -89,6 +89,7 @@ After installing via \`npx skillsets install {{AUTHOR_HANDLE}}/{{NAME}}\`, custo
89
89
  your-project/
90
90
  ├── .claude/ # Skills, agents, resources
91
91
  ├── CLAUDE.md # Project config ← START HERE
92
+ ├── QUICKSTART_{{NAME}}.md # Post-install guide
92
93
  └── README_{{NAME}}.md # Skillset documentation
93
94
  \`\`\`
94
95
 
@@ -353,8 +354,7 @@ export async function init(options) {
353
354
  }
354
355
  // Auto-detect existing files — core skillset files and primitives
355
356
  const coreFiles = [
356
- 'CLAUDE.md', 'QUICKSTART.md', 'INSTALL_NOTES.md',
357
- '.claude/', '.mcp.json',
357
+ 'CLAUDE.md', '.claude/', '.mcp.json',
358
358
  ];
359
359
  const detectedCore = coreFiles.filter((f) => {
360
360
  const checkPath = f.endsWith('/') ? f.slice(0, -1) : f;
@@ -423,18 +423,20 @@ export async function init(options) {
423
423
  .replace(/\{\{AUTHOR_HANDLE\}\}/g, authorHandle);
424
424
  writeFileSync(join(cwd, 'content', readmeFilename), readme);
425
425
  }
426
- // Generate content/QUICKSTART.md (if not copying existing)
427
- if (!existsSync(join(cwd, 'content', 'QUICKSTART.md'))) {
426
+ // Generate content/QUICKSTART_<NAME>.md (if not already present)
427
+ const quickstartFilename = `QUICKSTART_${name.toUpperCase()}.md`;
428
+ if (!existsSync(join(cwd, 'content', quickstartFilename))) {
428
429
  const quickstart = QUICKSTART_TEMPLATE
429
430
  .replace(/\{\{NAME\}\}/g, name)
430
431
  .replace(/\{\{AUTHOR_HANDLE\}\}/g, authorHandle);
431
- writeFileSync(join(cwd, 'content', 'QUICKSTART.md'), quickstart);
432
+ writeFileSync(join(cwd, 'content', quickstartFilename), quickstart);
432
433
  }
433
- // Generate content/INSTALL_NOTES.md (if not copying existing)
434
- if (!existsSync(join(cwd, 'content', 'INSTALL_NOTES.md'))) {
434
+ // Generate content/INSTALL_NOTES_<NAME>.md (if not already present)
435
+ const installNotesFilename = `INSTALL_NOTES_${name.toUpperCase()}.md`;
436
+ if (!existsSync(join(cwd, 'content', installNotesFilename))) {
435
437
  const installNotes = INSTALL_NOTES_TEMPLATE
436
438
  .replace(/\{\{NAME\}\}/g, name);
437
- writeFileSync(join(cwd, 'content', 'INSTALL_NOTES.md'), installNotes);
439
+ writeFileSync(join(cwd, 'content', installNotesFilename), installNotes);
438
440
  }
439
441
  // Generate empty content/LICENSE (if not copying existing)
440
442
  if (!existsSync(join(cwd, 'content', 'LICENSE'))) {
@@ -446,8 +448,8 @@ export async function init(options) {
446
448
  console.log(' skillset.yaml - Manifest (edit as needed)');
447
449
  console.log(' content/ - Installable files');
448
450
  console.log(` ├── ${readmeFilename} - Documentation`);
449
- console.log(' ├── QUICKSTART.md - Post-install guide');
450
- console.log(' ├── INSTALL_NOTES.md - Pre-install notes');
451
+ console.log(` ├── ${quickstartFilename} - Post-install guide`);
452
+ console.log(` ├── ${installNotesFilename} - Pre-install notes`);
451
453
  console.log(' ├── LICENSE - License (populate before audit)');
452
454
  if (filesToCopy.length > 0) {
453
455
  filesToCopy.forEach((f) => console.log(` └── ${f}`));
@@ -456,7 +458,7 @@ export async function init(options) {
456
458
  console.log(' └── (add your .claude/ and/or CLAUDE.md here)');
457
459
  }
458
460
  console.log(chalk.cyan('\nNext steps:'));
459
- console.log(' 1. Edit content/INSTALL_NOTES.md with install notes');
461
+ console.log(` 1. Edit content/${installNotesFilename} with install notes`);
460
462
  console.log(' 2. Ensure content/ has your skillset files');
461
463
  console.log(' 3. Run: npx skillsets audit');
462
464
  console.log(' 4. Run: /audit-skill [AUDIT_REPORT.md] [path/to/reference-repo]');
@@ -145,6 +145,12 @@ export async function install(skillsetId, options) {
145
145
  await rm(tempDir, { recursive: true, force: true });
146
146
  throw new Error('Checksum verification failed - files may be corrupted');
147
147
  }
148
+ // Strip redirect README.md if a README_*.md exists (avoid clobbering user's README)
149
+ const tempEntries = await readdir(tempDir);
150
+ const hasNamedReadme = tempEntries.some(f => /^README_[^/]+\.md$/i.test(f));
151
+ if (hasNamedReadme && tempEntries.includes('README.md')) {
152
+ await rm(join(tempDir, 'README.md'));
153
+ }
148
154
  // Checksums valid — move verified content to cwd
149
155
  spinner.text = 'Installing verified content...';
150
156
  const entries = await readdir(tempDir, { withFileTypes: true });
@@ -171,6 +177,7 @@ export async function install(skillsetId, options) {
171
177
  console.log(chalk.green('\n✓ Installation complete!'));
172
178
  console.log(chalk.gray('\nNext steps:'));
173
179
  console.log(' 1. Ask Opus to verify the skillset matches its claims');
174
- console.log(' 2. Read QUICKSTART.md to customize for your project');
180
+ const skillsetName = skillsetId.split('/')[1];
181
+ console.log(` 2. Read QUICKSTART_${skillsetName.toUpperCase()}.md to customize for your project`);
175
182
  console.log(' 3. Run: claude');
176
183
  }
@@ -235,7 +235,7 @@ Submitted via \`npx skillsets submit\`
235
235
 
236
236
  - [x] \`skillset.yaml\` validated against schema
237
237
  - [x] \`README_${skillset.name.toUpperCase()}.md\` with installation and usage instructions
238
- - [x] \`content/INSTALL_NOTES.md\` with install notes
238
+ - [x] \`content/INSTALL_NOTES_${skillset.name.toUpperCase()}.md\` with install notes
239
239
  - [x] \`content/LICENSE\` populated
240
240
  - [x] \`AUDIT_REPORT.md\` generated and passing
241
241
  - [x] \`content/\` directory with skillset files
@@ -1,4 +1,4 @@
1
1
  export declare const SKILLSET_YAML_TEMPLATE = "schema_version: \"1.0\"\nbatch_id: \"{{BATCH_ID}}\"\n\n# Identity\nname: \"{{NAME}}\"\nversion: \"1.0.0\"\ndescription: \"{{DESCRIPTION}}\"\n\nauthor:\n handle: \"{{AUTHOR_HANDLE}}\"\n url: \"{{AUTHOR_URL}}\"\n\n# Verification\nverification:\n production_links:\n - url: \"{{PRODUCTION_URL}}\"\n audit_report: \"./AUDIT_REPORT.md\"\n\n# Discovery\ntags:\n{{TAGS}}\n\ncompatibility:\n claude_code_version: \">=1.0.0\"\n languages:\n - \"any\"\n\n# Lifecycle\nstatus: \"active\"\n\n# Content\nentry_point: \"./content/CLAUDE.md\"\n";
2
2
  export declare const README_TEMPLATE = "# {{NAME}}\n\n{{DESCRIPTION}}\n\n## Installation\n\n```bash\nnpx skillsets install {{AUTHOR_HANDLE}}/{{NAME}}\n```\n\n## Usage\n\n[Describe how to use your skillset]\n\n## What's Included\n\n[List the key files and their purposes]\n\n";
3
- export declare const QUICKSTART_TEMPLATE = "# Quickstart\n\nAfter installing via `npx skillsets install {{AUTHOR_HANDLE}}/{{NAME}}`, customize the workflow for your project.\n\n---\n\n## What Was Installed\n\n```\nyour-project/\n\u251C\u2500\u2500 .claude/ # Skills, agents, resources\n\u251C\u2500\u2500 CLAUDE.md # Project config \u2190 START HERE\n\u2514\u2500\u2500 README_{{NAME}}.md # Skillset documentation\n```\n\n---\n\n## Getting Started\n\n1. **Edit CLAUDE.md** \u2014 Replace placeholder content with your project's specifics\n2. **Customize .claude/** \u2014 Adapt skills, agents, and resources for your stack\n3. **Run** \u2014 `claude` to start using the skillset\n\n---\n\n## Customization Checklist\n\n- [ ] Update Identity & Constraints in CLAUDE.md\n- [ ] Configure style guides in .claude/resources/\n- [ ] Adapt agent definitions in .claude/agents/\n- [ ] Set up any required infrastructure (Docker, API keys, etc.)\n\n---\n\n## Resources\n\n[Add links to documentation, examples, or support channels]\n";
3
+ export declare const QUICKSTART_TEMPLATE = "# Quickstart\n\nAfter installing via `npx skillsets install {{AUTHOR_HANDLE}}/{{NAME}}`, customize the workflow for your project.\n\n---\n\n## What Was Installed\n\n```\nyour-project/\n\u251C\u2500\u2500 .claude/ # Skills, agents, resources\n\u251C\u2500\u2500 CLAUDE.md # Project config \u2190 START HERE\n\u251C\u2500\u2500 QUICKSTART_{{NAME}}.md # Post-install guide\n\u2514\u2500\u2500 README_{{NAME}}.md # Skillset documentation\n```\n\n---\n\n## Getting Started\n\n1. **Edit CLAUDE.md** \u2014 Replace placeholder content with your project's specifics\n2. **Customize .claude/** \u2014 Adapt skills, agents, and resources for your stack\n3. **Run** \u2014 `claude` to start using the skillset\n\n---\n\n## Customization Checklist\n\n- [ ] Update Identity & Constraints in CLAUDE.md\n- [ ] Configure style guides in .claude/resources/\n- [ ] Adapt agent definitions in .claude/agents/\n- [ ] Set up any required infrastructure (Docker, API keys, etc.)\n\n---\n\n## Resources\n\n[Add links to documentation, examples, or support channels]\n";
4
4
  export declare const INSTALL_NOTES_TEMPLATE = "# {{NAME}}\n\n<!--\nInstall notes for pre-install display. Max 4000 characters total.\nWhat does this skillset do? What should users know before installing?\nThe dependency section below is populated by /audit-skill during review.\n-->\n\n## Dependencies\n\n<!-- Populated automatically by /audit-skill -->\n";
@@ -62,6 +62,7 @@ After installing via \`npx skillsets install {{AUTHOR_HANDLE}}/{{NAME}}\`, custo
62
62
  your-project/
63
63
  ├── .claude/ # Skills, agents, resources
64
64
  ├── CLAUDE.md # Project config ← START HERE
65
+ ├── QUICKSTART_{{NAME}}.md # Post-install guide
65
66
  └── README_{{NAME}}.md # Skillset documentation
66
67
  \`\`\`
67
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillsets",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "CLI tool for discovering and installing verified skillsets",
5
5
  "type": "module",
6
6
  "bin": {