proskills-cli 0.1.0 → 0.2.0
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 +99 -83
- package/dist/cli.js +26 -21
- package/dist/scancmd.js +5 -0
- package/package.json +49 -49
package/README.md
CHANGED
|
@@ -1,83 +1,99 @@
|
|
|
1
|
-
# proskills-cli
|
|
2
|
-
|
|
3
|
-
Install [ProSkills](https://proskills.dev) agent skills in one command, and scan any `SKILL.md` folder in CI.
|
|
4
|
-
|
|
5
|
-
Node 18 or newer. One dependency (`jszip`).
|
|
6
|
-
|
|
7
|
-
## Use it
|
|
8
|
-
|
|
9
|
-
No install needed:
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npx proskills-cli list # every skill, price and scan score
|
|
13
|
-
npx proskills-cli add humanizer # install a free skill into this project
|
|
14
|
-
npx proskills-cli add grill-me hook-lab # several at once
|
|
15
|
-
npx proskills-cli scan # score the skills already in this repo
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Or install it: `npm i -g proskills`.
|
|
19
|
-
|
|
20
|
-
### `proskills list [--collection <slug>]`
|
|
21
|
-
|
|
22
|
-
Prints a table of skills with price (or `Free`) and scan score.
|
|
23
|
-
|
|
24
|
-
### `proskills add <skill-id...>`
|
|
25
|
-
|
|
26
|
-
| Flag | Meaning |
|
|
27
|
-
|---|---|
|
|
28
|
-
| `--agent claude\|cursor\|codex\|gemini\|all` | Which agent to install for. Default: `.claude/` found, then Claude Code; else `.agents/` found, then `.agents/skills`; else Claude Code. |
|
|
29
|
-
| `--global` | Install for every project (your home folder) instead of this one. |
|
|
30
|
-
| `--order <id>` | Order id from your receipt (`cs_live_...`). Also read from env `PROSKILLS_ORDER`. Required for paid skills. |
|
|
31
|
-
| `--dir <path>` | Use this folder instead of the current one (instead of your home folder with `--global`). |
|
|
32
|
-
| `--force` | Replace a skill folder that already exists. Without it, nothing is overwritten. |
|
|
33
|
-
| `--answers file.json` | Send your saved answers so `profile.md` is filled in. Optional. |
|
|
34
|
-
|
|
35
|
-
Paid skill without an order id: the command stops and prints the link to buy it (`https://proskills.dev/library/<collection>`).
|
|
36
|
-
|
|
37
|
-
### `proskills scan [paths...] [--min 80] [--json]`
|
|
38
|
-
|
|
39
|
-
Scores skill folders against the Agent Skills spec, token budget, clarity and security. A path is a skill folder (has `SKILL.md`) or a folder of skill folders. Default: `.claude/skills` and `.agents/skills`. Exits `1` when any skill is grade F (any critical finding) or scores under `--min`, `2` on usage errors. Scanning runs locally; nothing is uploaded.
|
|
40
|
-
|
|
41
|
-
### Everywhere
|
|
42
|
-
|
|
43
|
-
`--base <url>` (or env `PROSKILLS_URL`) points at another host. Default `https://proskills.dev`. `--help`, `--version`.
|
|
44
|
-
|
|
45
|
-
## CI
|
|
46
|
-
|
|
47
|
-
Block a pull request that adds a weak or unsafe skill:
|
|
48
|
-
|
|
49
|
-
```yaml
|
|
50
|
-
name: skills
|
|
51
|
-
on: [pull_request]
|
|
52
|
-
jobs:
|
|
53
|
-
scan:
|
|
54
|
-
runs-on: ubuntu-latest
|
|
55
|
-
steps:
|
|
56
|
-
- uses: actions/checkout@v4
|
|
57
|
-
- uses: actions/setup-node@v4
|
|
58
|
-
with: { node-version: 20 }
|
|
59
|
-
- run: npx proskills-cli scan --min 80
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Add paths to scan something else: `npx proskills-cli scan ./skills --min 90 --json`.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
# proskills-cli
|
|
2
|
+
|
|
3
|
+
Install [ProSkills](https://proskills.dev) agent skills in one command, and scan any `SKILL.md` folder in CI.
|
|
4
|
+
|
|
5
|
+
Node 18 or newer. One dependency (`jszip`).
|
|
6
|
+
|
|
7
|
+
## Use it
|
|
8
|
+
|
|
9
|
+
No install needed:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npx proskills-cli list # every skill, price and scan score
|
|
13
|
+
npx proskills-cli add humanizer # install a free skill into this project
|
|
14
|
+
npx proskills-cli add grill-me hook-lab # several at once
|
|
15
|
+
npx proskills-cli scan # score the skills already in this repo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or install it: `npm i -g proskills`.
|
|
19
|
+
|
|
20
|
+
### `proskills list [--collection <slug>]`
|
|
21
|
+
|
|
22
|
+
Prints a table of skills with price (or `Free`) and scan score.
|
|
23
|
+
|
|
24
|
+
### `proskills add <skill-id...>`
|
|
25
|
+
|
|
26
|
+
| Flag | Meaning |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `--agent claude\|cursor\|codex\|gemini\|all` | Which agent to install for. Default: `.claude/` found, then Claude Code; else `.agents/` found, then `.agents/skills`; else Claude Code. |
|
|
29
|
+
| `--global` | Install for every project (your home folder) instead of this one. |
|
|
30
|
+
| `--order <id>` | Order id from your receipt (`cs_live_...`). Also read from env `PROSKILLS_ORDER`. Required for paid skills. |
|
|
31
|
+
| `--dir <path>` | Use this folder instead of the current one (instead of your home folder with `--global`). |
|
|
32
|
+
| `--force` | Replace a skill folder that already exists. Without it, nothing is overwritten. |
|
|
33
|
+
| `--answers file.json` | Send your saved answers so `profile.md` is filled in. Optional. |
|
|
34
|
+
|
|
35
|
+
Paid skill without an order id: the command stops and prints the link to buy it (`https://proskills.dev/library/<collection>`).
|
|
36
|
+
|
|
37
|
+
### `proskills scan [paths...] [--min 80] [--json] [--badge]`
|
|
38
|
+
|
|
39
|
+
Scores skill folders against the Agent Skills spec, token budget, clarity and security. A path is a skill folder (has `SKILL.md`) or a folder of skill folders. Default: `.claude/skills` and `.agents/skills`. Exits `1` when any skill is grade F (any critical finding) or scores under `--min`, `2` on usage errors. `--badge` prints a README badge snippet after the scan, using the lowest score across the scanned skills (with `--json` it is a `badge` field instead). Scanning runs locally; nothing is uploaded.
|
|
40
|
+
|
|
41
|
+
### Everywhere
|
|
42
|
+
|
|
43
|
+
`--base <url>` (or env `PROSKILLS_URL`) points at another host. Default `https://proskills.dev`. `--help`, `--version`.
|
|
44
|
+
|
|
45
|
+
## CI
|
|
46
|
+
|
|
47
|
+
Block a pull request that adds a weak or unsafe skill:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
name: skills
|
|
51
|
+
on: [pull_request]
|
|
52
|
+
jobs:
|
|
53
|
+
scan:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
- uses: actions/setup-node@v4
|
|
58
|
+
with: { node-version: 20 }
|
|
59
|
+
- run: npx proskills-cli scan --min 80
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Add paths to scan something else: `npx proskills-cli scan ./skills --min 90 --json`.
|
|
63
|
+
|
|
64
|
+
Or use the GitHub Action from the [public repo](https://github.com/yungprimer/proskills), which also prints the badge in the job summary:
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
- uses: yungprimer/proskills@v1
|
|
68
|
+
with:
|
|
69
|
+
min: 80
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Badge
|
|
73
|
+
|
|
74
|
+
`npx proskills-cli scan --badge` prints this for your README (the number is your lowest skill score):
|
|
75
|
+
|
|
76
|
+
```md
|
|
77
|
+
[](https://proskills.dev/scan)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## What it writes, and where
|
|
81
|
+
|
|
82
|
+
Each skill becomes one folder, with `SKILL.md`, `profile.md` and any files the skill reads:
|
|
83
|
+
|
|
84
|
+
| Agent | This project | With `--global` |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| Claude Code | `.claude/skills/<id>/` | `~/.claude/skills/<id>/` |
|
|
87
|
+
| Cursor | `.agents/skills/<id>/` | `~/.cursor/skills/<id>/` |
|
|
88
|
+
| Codex | `.agents/skills/<id>/` | `~/.agents/skills/<id>/` |
|
|
89
|
+
| Gemini CLI | `.agents/skills/<id>/` | `~/.gemini/skills/<id>/` |
|
|
90
|
+
|
|
91
|
+
It writes only inside that skills folder. Archive entries with `..`, absolute paths or drive letters are rejected before anything is written. Restart your agent afterwards.
|
|
92
|
+
|
|
93
|
+
## Privacy
|
|
94
|
+
|
|
95
|
+
`list` and `add` send only the skill ids you ask for, plus the order id if you give one. Your saved answers are not sent unless you pass `--answers file.json`. No telemetry, no accounts, no other network calls. `scan` makes none at all.
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -5,27 +5,29 @@ import { parseArgs } from "node:util";
|
|
|
5
5
|
import { CliError, fetchCatalog } from "./api.js";
|
|
6
6
|
import { install } from "./install.js";
|
|
7
7
|
import { pickAgents, resolveTargets } from "./paths.js";
|
|
8
|
-
import { DEFAULT_SCAN_DIRS, isFailing, scanDirs } from "./scancmd.js";
|
|
8
|
+
import { DEFAULT_SCAN_DIRS, badgeMarkdown, isFailing, scanDirs } from "./scancmd.js";
|
|
9
9
|
export const DEFAULT_BASE = "https://proskills.dev";
|
|
10
|
-
export const HELP = `proskills - install ProSkills agent skills and scan any skill folder
|
|
11
|
-
|
|
12
|
-
Usage
|
|
13
|
-
proskills list [--collection <slug>]
|
|
14
|
-
proskills add <skill-id...> [--agent claude|cursor|codex|gemini|all] [--global]
|
|
15
|
-
[--order <id>] [--dir <path>] [--force] [--answers file.json]
|
|
16
|
-
proskills scan [paths...] [--min 80] [--json]
|
|
17
|
-
|
|
18
|
-
Options
|
|
19
|
-
--base <url> Another host (default ${DEFAULT_BASE}, or env PROSKILLS_URL)
|
|
20
|
-
--order <id> Order id from your receipt (or env PROSKILLS_ORDER)
|
|
21
|
-
--dir <path> Base folder instead of the current one (home folder with --global)
|
|
22
|
-
--
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
npx proskills-cli
|
|
10
|
+
export const HELP = `proskills - install ProSkills agent skills and scan any skill folder
|
|
11
|
+
|
|
12
|
+
Usage
|
|
13
|
+
proskills list [--collection <slug>]
|
|
14
|
+
proskills add <skill-id...> [--agent claude|cursor|codex|gemini|all] [--global]
|
|
15
|
+
[--order <id>] [--dir <path>] [--force] [--answers file.json]
|
|
16
|
+
proskills scan [paths...] [--min 80] [--json] [--badge]
|
|
17
|
+
|
|
18
|
+
Options
|
|
19
|
+
--base <url> Another host (default ${DEFAULT_BASE}, or env PROSKILLS_URL)
|
|
20
|
+
--order <id> Order id from your receipt (or env PROSKILLS_ORDER)
|
|
21
|
+
--dir <path> Base folder instead of the current one (home folder with --global)
|
|
22
|
+
--badge After a scan, print a README badge snippet using the lowest score
|
|
23
|
+
across the scanned skills (with --json: a "badge" field)
|
|
24
|
+
--help Show this help
|
|
25
|
+
--version Show the version
|
|
26
|
+
|
|
27
|
+
Examples
|
|
28
|
+
npx proskills-cli add humanizer
|
|
29
|
+
npx proskills-cli add grill-me --agent all --global
|
|
30
|
+
npx proskills-cli scan --min 80
|
|
29
31
|
`;
|
|
30
32
|
const OPTIONS = {
|
|
31
33
|
help: { type: "boolean", short: "h" },
|
|
@@ -40,6 +42,7 @@ const OPTIONS = {
|
|
|
40
42
|
collection: { type: "string" },
|
|
41
43
|
min: { type: "string" },
|
|
42
44
|
json: { type: "boolean" },
|
|
45
|
+
badge: { type: "boolean" },
|
|
43
46
|
};
|
|
44
47
|
export function parseCli(argv) {
|
|
45
48
|
const { values, positionals } = parseArgs({ args: argv, options: OPTIONS, allowPositionals: true, strict: true });
|
|
@@ -138,7 +141,7 @@ export async function run(argv, io) {
|
|
|
138
141
|
throw new CliError(explicit ? "No skill folders (containing SKILL.md) found in the given paths." : `No skills found in ${DEFAULT_SCAN_DIRS.join(" or ")}. Pass a path: proskills scan ./my-skill`, 2);
|
|
139
142
|
const failed = results.filter((r) => isFailing(r, min));
|
|
140
143
|
if (values.json) {
|
|
141
|
-
io.out(JSON.stringify({ min, ok: failed.length === 0, skills: results.map((r) => ({ dir: r.dir.replace(/\\/g, "/"), failed: isFailing(r, min), ...r.report })) }, null, 2));
|
|
144
|
+
io.out(JSON.stringify({ min, ok: failed.length === 0, ...(values.badge ? { badge: badgeMarkdown(results.map((r) => r.report.score)) } : {}), skills: results.map((r) => ({ dir: r.dir.replace(/\\/g, "/"), failed: isFailing(r, min), ...r.report })) }, null, 2));
|
|
142
145
|
}
|
|
143
146
|
else {
|
|
144
147
|
for (const { dir, report: r } of results) {
|
|
@@ -147,6 +150,8 @@ export async function run(argv, io) {
|
|
|
147
150
|
io.out(` ${f.severity.padEnd(8)} ${f.rule.padEnd(24)} ${f.file ?? ""}${f.line ? ":" + f.line : ""} ${f.message}`);
|
|
148
151
|
}
|
|
149
152
|
io.out(`\n${results.length} skills scanned, ${failed.length} below the gate (min ${min}, grade F always fails).`);
|
|
153
|
+
if (values.badge)
|
|
154
|
+
io.out(`\nREADME badge (lowest score: ${Math.min(...results.map((r) => r.report.score))}):\n${badgeMarkdown(results.map((r) => r.report.score))}`);
|
|
150
155
|
}
|
|
151
156
|
return failed.length ? 1 : 0;
|
|
152
157
|
}
|
package/dist/scancmd.js
CHANGED
|
@@ -48,3 +48,8 @@ export function scanDirs(roots, cwd) {
|
|
|
48
48
|
export function isFailing(r, min) {
|
|
49
49
|
return r.report.grade === "F" || r.report.score < min;
|
|
50
50
|
}
|
|
51
|
+
/** README badge for a scan. Uses the lowest score, so one weak skill cannot hide behind a strong one. */
|
|
52
|
+
export function badgeMarkdown(scores) {
|
|
53
|
+
const score = Math.max(0, Math.min(100, Math.round(Math.min(...scores))));
|
|
54
|
+
return `[](https://proskills.dev/scan)`;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "proskills-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Install ProSkills agent skills in one command and scan any SKILL.md folder in CI.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"agent-skills",
|
|
7
|
-
"skill.md",
|
|
8
|
-
"claude-code",
|
|
9
|
-
"cursor",
|
|
10
|
-
"codex",
|
|
11
|
-
"gemini-cli",
|
|
12
|
-
"cli"
|
|
13
|
-
],
|
|
14
|
-
"homepage": "https://proskills.dev",
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/yungprimer/proskills.git",
|
|
18
|
-
"directory": "cli"
|
|
19
|
-
},
|
|
20
|
-
"bugs": {
|
|
21
|
-
"url": "https://github.com/yungprimer/proskills/issues"
|
|
22
|
-
},
|
|
23
|
-
"author": "ProSkills (https://proskills.dev)",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"type": "module",
|
|
26
|
-
"bin": {
|
|
27
|
-
"proskills": "dist/index.js"
|
|
28
|
-
},
|
|
29
|
-
"files": [
|
|
30
|
-
"dist",
|
|
31
|
-
"README.md"
|
|
32
|
-
],
|
|
33
|
-
"engines": {
|
|
34
|
-
"node": ">=18"
|
|
35
|
-
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"prebuild": "node scripts/copy-scan.mjs",
|
|
38
|
-
"build": "tsc -p tsconfig.json",
|
|
39
|
-
"test": "node --test test/cli.test.mjs",
|
|
40
|
-
"prepublishOnly": "npm run build && npm test"
|
|
41
|
-
},
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"jszip": "^3.10.1"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/node": "^20",
|
|
47
|
-
"typescript": "^5"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "proskills-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Install ProSkills agent skills in one command and scan any SKILL.md folder in CI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent-skills",
|
|
7
|
+
"skill.md",
|
|
8
|
+
"claude-code",
|
|
9
|
+
"cursor",
|
|
10
|
+
"codex",
|
|
11
|
+
"gemini-cli",
|
|
12
|
+
"cli"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://proskills.dev",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/yungprimer/proskills.git",
|
|
18
|
+
"directory": "cli"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/yungprimer/proskills/issues"
|
|
22
|
+
},
|
|
23
|
+
"author": "ProSkills (https://proskills.dev)",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"type": "module",
|
|
26
|
+
"bin": {
|
|
27
|
+
"proskills": "dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"prebuild": "node scripts/copy-scan.mjs",
|
|
38
|
+
"build": "tsc -p tsconfig.json",
|
|
39
|
+
"test": "node --test test/cli.test.mjs",
|
|
40
|
+
"prepublishOnly": "npm run build && npm test"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"jszip": "^3.10.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20",
|
|
47
|
+
"typescript": "^5"
|
|
48
|
+
}
|
|
49
|
+
}
|