skillsets 0.2.4 → 0.2.5

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
@@ -1,62 +1,60 @@
1
1
  # Skillsets CLI
2
2
 
3
+ ## Purpose
3
4
  Command-line tool for discovering, installing, and contributing verified Claude Code skillsets.
4
5
 
5
- ## Quick Start
6
-
7
- ```bash
8
- # Browse available skillsets
9
- npx skillsets list
10
-
11
- # Sort by popularity
12
- npx skillsets list --sort downloads
13
-
14
- # Search by keyword
15
- npx skillsets search "sdlc"
16
-
17
- # Install a skillset
18
- npx skillsets install @supercollectible/The_Skillset
6
+ ## Architecture
19
7
  ```
20
-
21
- ## Commands
22
-
23
- | Command | Purpose |
24
- |---------|---------|
25
- | `list` | Browse all skillsets with live star/download counts |
26
- | `search <query>` | Fuzzy search by name, description, or tags |
27
- | `install <id>` | Install skillset to current directory (verifies checksums) |
28
- | `init` | Scaffold a new skillset for contribution |
29
- | `audit` | Validate skillset before submission |
30
- | `submit` | Open PR to registry (requires `gh` CLI) |
31
-
32
- ## Options
33
-
34
- ### list
35
- - `-l, --limit <n>` - Limit number of results
36
- - `-s, --sort <field>` - Sort by: `name`, `stars`, `downloads`, `recent`
37
- - `--json` - Output as JSON
38
-
39
- ### search
40
- - `-t, --tags <tags...>` - Filter by tags
41
- - `-l, --limit <n>` - Limit results (default: 10)
42
-
43
- ### install
44
- - `-f, --force` - Overwrite existing files
45
- - `-b, --backup` - Backup existing files before install
46
-
47
- ## Live Stats
48
-
49
- The CLI fetches live star and download counts from the API, so you always see current numbers (not stale build-time data).
50
-
51
- ## Development
52
-
53
- ```bash
54
- npm install # Install dependencies
55
- npm run build # Build TypeScript
56
- npm test # Run tests
8
+ cli/
9
+ ├── src/
10
+ │ ├── index.ts # CLI entry point
11
+ │ ├── commands/ # Command implementations
12
+ │ │ ├── list.ts
13
+ │ │ ├── search.ts
14
+ │ │ ├── install.ts
15
+ │ │ ├── init.ts
16
+ │ │ ├── audit.ts
17
+ │ │ └── submit.ts
18
+ │ ├── lib/ # Shared utilities
19
+ │ │ ├── api.ts
20
+ │ │ ├── checksum.ts
21
+ │ │ ├── constants.ts
22
+ │ │ ├── errors.ts
23
+ │ │ ├── filesystem.ts
24
+ │ │ └── versions.ts
25
+ │ └── types/
26
+ │ └── index.ts
27
+ └── docs_cli/ # Documentation
28
+ ├── ARC_cli.md
29
+ ├── commands/
30
+ └── lib/
57
31
  ```
58
32
 
59
- ## Documentation
60
-
61
- - [CLI Style Guide](../.claude/resources/cli_styleguide.md) - Development patterns
62
- - [CLAUDE.md](../CLAUDE.md) - Project overview
33
+ ## Files
34
+
35
+ | File | Purpose | Documentation |
36
+ |------|---------|---------------|
37
+ | — | Architecture, data flow, key patterns | [ARC_cli.md](./docs_cli/ARC_cli.md) |
38
+
39
+ ### Commands
40
+ | File | Purpose | Documentation |
41
+ |------|---------|---------------|
42
+ | `list.ts` | Browse all skillsets with live stats | [Docs](./docs_cli/commands/list.md) |
43
+ | `search.ts` | Fuzzy search by name, description, tags | [Docs](./docs_cli/commands/search.md) |
44
+ | `install.ts` | Install skillset via degit + verify checksums | [Docs](./docs_cli/commands/install.md) |
45
+ | `init.ts` | Scaffold new skillset for contribution | [Docs](./docs_cli/commands/init.md) |
46
+ | `audit.ts` | Validate skillset before submission | [Docs](./docs_cli/commands/audit.md) |
47
+ | `submit.ts` | Open PR to registry | [Docs](./docs_cli/commands/submit.md) |
48
+
49
+ ### Lib
50
+ | File | Purpose | Documentation |
51
+ |------|---------|---------------|
52
+ | `api.ts` | API client for skillsets.cc | [Docs](./docs_cli/lib/api.md) |
53
+ | `checksum.ts` | SHA-256 verification | [Docs](./docs_cli/lib/checksum.md) |
54
+ | `constants.ts` | Shared constants | [Docs](./docs_cli/lib/constants.md) |
55
+ | `errors.ts` | Error types | [Docs](./docs_cli/lib/errors.md) |
56
+ | `filesystem.ts` | File utilities | [Docs](./docs_cli/lib/filesystem.md) |
57
+ | `versions.ts` | Semver comparison | [Docs](./docs_cli/lib/versions.md) |
58
+
59
+ ## Related Documentation
60
+ - [CLI Style Guide](../.claude/resources/cli_styleguide.md)
@@ -1,26 +1,10 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
- import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'fs';
3
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync, openSync, readSync, closeSync } from 'fs';
4
4
  import { join, relative } from 'path';
5
5
  import yaml from 'js-yaml';
6
6
  import { fetchSkillsetMetadata } from '../lib/api.js';
7
- /**
8
- * Compare semver versions. Returns:
9
- * -1 if a < b, 0 if a == b, 1 if a > b
10
- */
11
- function compareVersions(a, b) {
12
- const partsA = a.split('.').map(Number);
13
- const partsB = b.split('.').map(Number);
14
- for (let i = 0; i < 3; i++) {
15
- const numA = partsA[i] || 0;
16
- const numB = partsB[i] || 0;
17
- if (numA < numB)
18
- return -1;
19
- if (numA > numB)
20
- return 1;
21
- }
22
- return 0;
23
- }
7
+ import { compareVersions } from '../lib/versions.js';
24
8
  const MAX_FILE_SIZE = 1048576; // 1MB
25
9
  const TEXT_EXTENSIONS = new Set([
26
10
  '.md', '.txt', '.json', '.yaml', '.yml',
@@ -69,9 +53,9 @@ function isBinaryFile(filePath) {
69
53
  // Check for null bytes in first 512 bytes
70
54
  try {
71
55
  const buffer = Buffer.alloc(512);
72
- const fd = require('fs').openSync(filePath, 'r');
73
- require('fs').readSync(fd, buffer, 0, 512, 0);
74
- require('fs').closeSync(fd);
56
+ const fd = openSync(filePath, 'r');
57
+ readSync(fd, buffer, 0, 512, 0);
58
+ closeSync(fd);
75
59
  return buffer.includes(0);
76
60
  }
77
61
  catch {
@@ -152,8 +136,8 @@ function validateManifest(cwd) {
152
136
  if (!data.author?.handle || !/^@[A-Za-z0-9_-]+$/.test(data.author.handle)) {
153
137
  errors.push('author.handle must start with @ (e.g., @username)');
154
138
  }
155
- if (!data.verification?.production_url) {
156
- errors.push('verification.production_url is required');
139
+ if (!Array.isArray(data.verification?.production_links) || data.verification.production_links.length === 0) {
140
+ errors.push('verification.production_links must be an array with at least one entry');
157
141
  }
158
142
  if (!data.verification?.audit_report) {
159
143
  errors.push('verification.audit_report is required');
@@ -16,7 +16,8 @@ author:
16
16
 
17
17
  # Verification
18
18
  verification:
19
- production_url: "{{PRODUCTION_URL}}"
19
+ production_links:
20
+ - url: "{{PRODUCTION_URL}}"
20
21
  production_proof: "./PROOF.md"
21
22
  audit_report: "./AUDIT_REPORT.md"
22
23
 
@@ -6,24 +6,8 @@ import { join } from 'path';
6
6
  import yaml from 'js-yaml';
7
7
  import { tmpdir } from 'os';
8
8
  import { fetchSkillsetMetadata } from '../lib/api.js';
9
+ import { compareVersions } from '../lib/versions.js';
9
10
  const REGISTRY_REPO = 'skillsets-cc/main';
10
- /**
11
- * Compare semver versions. Returns:
12
- * -1 if a < b, 0 if a == b, 1 if a > b
13
- */
14
- function compareVersions(a, b) {
15
- const partsA = a.split('.').map(Number);
16
- const partsB = b.split('.').map(Number);
17
- for (let i = 0; i < 3; i++) {
18
- const numA = partsA[i] || 0;
19
- const numB = partsB[i] || 0;
20
- if (numA < numB)
21
- return -1;
22
- if (numA > numB)
23
- return 1;
24
- }
25
- return 0;
26
- }
27
11
  const REGISTRY_URL = `https://github.com/${REGISTRY_REPO}`;
28
12
  function checkGhCli() {
29
13
  try {
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Compare semver versions. Returns:
3
+ * -1 if a < b, 0 if a == b, 1 if a > b
4
+ */
5
+ export declare function compareVersions(a: string, b: string): number;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Compare semver versions. Returns:
3
+ * -1 if a < b, 0 if a == b, 1 if a > b
4
+ */
5
+ export function compareVersions(a, b) {
6
+ const partsA = a.split('.').map(Number);
7
+ const partsB = b.split('.').map(Number);
8
+ for (let i = 0; i < 3; i++) {
9
+ const numA = partsA[i] || 0;
10
+ const numB = partsB[i] || 0;
11
+ if (numA < numB)
12
+ return -1;
13
+ if (numA > numB)
14
+ return 1;
15
+ }
16
+ return 0;
17
+ }
@@ -17,7 +17,10 @@ export interface SearchIndexEntry {
17
17
  version: string;
18
18
  status: 'active' | 'deprecated' | 'archived';
19
19
  verification: {
20
- production_url: string;
20
+ production_links: Array<{
21
+ url: string;
22
+ label?: string;
23
+ }>;
21
24
  production_proof?: string;
22
25
  audit_report: string;
23
26
  };
@@ -43,7 +46,10 @@ export interface Skillset {
43
46
  url: string;
44
47
  };
45
48
  verification: {
46
- production_url: string;
49
+ production_links: Array<{
50
+ url: string;
51
+ label?: string;
52
+ }>;
47
53
  production_proof?: string;
48
54
  audit_report: string;
49
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillsets",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "CLI tool for discovering and installing verified skillsets",
5
5
  "type": "module",
6
6
  "bin": {