vskill 0.5.138 → 0.5.140
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 +16 -16
- package/agents.json +1 -1
- package/dist/commands/stamp-versions.d.ts +25 -0
- package/dist/commands/stamp-versions.js +153 -0
- package/dist/commands/stamp-versions.js.map +1 -0
- package/dist/eval-server/api-routes.js +13 -5
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/skill-dir-registry.d.ts +15 -0
- package/dist/eval-server/skill-dir-registry.js +34 -0
- package/dist/eval-server/skill-dir-registry.js.map +1 -1
- package/dist/eval-server/skill-resolver.js +6 -1
- package/dist/eval-server/skill-resolver.js.map +1 -1
- package/dist/eval-ui/assets/{CommandPalette-DWl6kb7K.js → CommandPalette-DeEo1aM2.js} +1 -1
- package/dist/eval-ui/assets/{CreateSkillPage-IndkXdwH.js → CreateSkillPage-BGi_wZ1y.js} +1 -1
- package/dist/eval-ui/assets/{FindSkillsPalette-Br5cToMQ.js → FindSkillsPalette-BbJJSef2.js} +2 -2
- package/dist/eval-ui/assets/{SearchPaletteCore-usZJoJGb.js → SearchPaletteCore-BK0cFJb6.js} +1 -1
- package/dist/eval-ui/assets/{SkillDetailPanel-ZGSkm510.js → SkillDetailPanel-DxidXsNP.js} +1 -1
- package/dist/eval-ui/assets/{UpdateDropdown-Borwxx95.js → UpdateDropdown-CcaDVKoz.js} +1 -1
- package/dist/eval-ui/assets/index-ByzTygib.css +1 -0
- package/dist/eval-ui/assets/index-C12VKBb6.js +110 -0
- package/dist/eval-ui/index.html +2 -2
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/eval-ui/assets/index-BOR1gyX9.js +0 -102
- package/dist/eval-ui/assets/index-C8DXCPPg.css +0 -1
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
<br/>
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
npx vskill studio # open the local IDE for AI skills
|
|
22
|
-
npx vskill install remotion-best-practices
|
|
21
|
+
npx vskill@latest studio # open the local IDE for AI skills
|
|
22
|
+
npx vskill@latest install remotion-best-practices
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
<br/>
|
|
@@ -40,7 +40,7 @@ vskill is built around three problems:
|
|
|
40
40
|
## Skill Studio — the local IDE for skills
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
npx vskill studio
|
|
43
|
+
npx vskill@latest studio
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
A localhost workbench opens at a deterministic per-project port. You can:
|
|
@@ -77,13 +77,13 @@ Every install runs the full pipeline. SARIF v2.1.0 output is available for CI (`
|
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
79
|
# Install one skill
|
|
80
|
-
npx vskill install remotion-dev/skills/remotion-best-practices
|
|
80
|
+
npx vskill@latest install remotion-dev/skills/remotion-best-practices
|
|
81
81
|
|
|
82
82
|
# Browse a repo, pick interactively
|
|
83
|
-
npx vskill install remotion-dev/skills
|
|
83
|
+
npx vskill@latest install remotion-dev/skills
|
|
84
84
|
|
|
85
85
|
# Install a Claude Code plugin (full domain bundle)
|
|
86
|
-
npx vskill install --repo anton-abyzov/vskill --plugin frontend
|
|
86
|
+
npx vskill@latest install --repo anton-abyzov/vskill --plugin frontend
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Install globally for repeat use: `npm i -g vskill`
|
|
@@ -115,7 +115,7 @@ Install globally for repeat use: `npm i -g vskill`
|
|
|
115
115
|
| **easychamp** | tournament-manager |
|
|
116
116
|
| **productivity** | survey-passing |
|
|
117
117
|
|
|
118
|
-
Install all eight: `npx vskill install --repo anton-abyzov/vskill --all`
|
|
118
|
+
Install all eight: `npx vskill@latest install --repo anton-abyzov/vskill --all`
|
|
119
119
|
|
|
120
120
|
Browse the full catalog → [verified-skill.com/docs/plugins](https://verified-skill.com/docs/plugins)
|
|
121
121
|
|
|
@@ -124,15 +124,15 @@ Browse the full catalog → [verified-skill.com/docs/plugins](https://verified-s
|
|
|
124
124
|
## Commands you'll actually use
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
|
-
vskill studio
|
|
128
|
-
vskill install <skill
|
|
129
|
-
vskill find <query>
|
|
130
|
-
vskill list --installed
|
|
131
|
-
vskill diff <skill> v1 v2
|
|
132
|
-
vskill skill new
|
|
133
|
-
vskill eval sweep <skill>
|
|
134
|
-
vskill audit --ci
|
|
135
|
-
vskill keys set anthropic
|
|
127
|
+
npx vskill@latest studio # open local IDE
|
|
128
|
+
npx vskill@latest install <skill> # install with full security scan
|
|
129
|
+
npx vskill@latest find <query> # search verified-skill.com registry
|
|
130
|
+
npx vskill@latest list --installed # what's installed where
|
|
131
|
+
npx vskill@latest diff <skill> v1 v2 # compare versions before upgrading
|
|
132
|
+
npx vskill@latest skill new # create a new skill (AI-assisted)
|
|
133
|
+
npx vskill@latest eval sweep <skill> # benchmark across models
|
|
134
|
+
npx vskill@latest audit --ci # SARIF v2.1.0 for CI
|
|
135
|
+
npx vskill@latest keys set anthropic # store API keys in ~/.vskill/keys.env
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
Full reference → [verified-skill.com/docs/cli-reference](https://verified-skill.com/docs/cli-reference)
|
package/agents.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface StampOptions {
|
|
2
|
+
/** Roots to walk. When omitted, defaults to ~/.claude/skills + ~/.claude/plugins/cache. */
|
|
3
|
+
root?: string[];
|
|
4
|
+
/** Default version to stamp when missing. */
|
|
5
|
+
version?: string;
|
|
6
|
+
/** When true, write changes to disk; otherwise dry-run (just report). */
|
|
7
|
+
write?: boolean;
|
|
8
|
+
/** When true, emit one path per line instead of human report. */
|
|
9
|
+
json?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface FileResult {
|
|
12
|
+
path: string;
|
|
13
|
+
action: "stamped" | "skipped-has-version" | "skipped-no-frontmatter" | "error";
|
|
14
|
+
current?: string | null;
|
|
15
|
+
next?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function stampVersionsCommand(opts?: StampOptions): Promise<{
|
|
19
|
+
scanned: number;
|
|
20
|
+
stamped: number;
|
|
21
|
+
alreadyHadVersion: number;
|
|
22
|
+
errors: number;
|
|
23
|
+
results: FileResult[];
|
|
24
|
+
}>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// 0759 Phase 7 (B1) — `vskill stamp-versions` command.
|
|
3
|
+
//
|
|
4
|
+
// Walks local skill installation roots and injects `version: "1.0.0"` into the
|
|
5
|
+
// frontmatter of any SKILL.md that is missing a version field. Opt-in only —
|
|
6
|
+
// never runs automatically. Defaults to dry-run; pass `--write` to actually
|
|
7
|
+
// modify files.
|
|
8
|
+
//
|
|
9
|
+
// Default scopes (when no --root passed):
|
|
10
|
+
// - ~/.claude/skills/ (Claude Code personal skills)
|
|
11
|
+
// - ~/.claude/plugins/cache/*/skills/ (plugin-cached skills)
|
|
12
|
+
//
|
|
13
|
+
// Skips files whose frontmatter already declares a version (idempotent).
|
|
14
|
+
// Skips files outside the user's home dir as a safety check.
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
import { promises as fs } from "node:fs";
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
import { join, resolve, sep } from "node:path";
|
|
19
|
+
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---(?:\n|$)/;
|
|
20
|
+
const VERSION_LINE_RE = /^version:\s*["']?([^"'\n]+?)["']?\s*$/m;
|
|
21
|
+
async function findSkillMdFiles(roots) {
|
|
22
|
+
const found = [];
|
|
23
|
+
for (const root of roots) {
|
|
24
|
+
try {
|
|
25
|
+
await walk(root, found);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Missing root — silently skip.
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return found;
|
|
32
|
+
}
|
|
33
|
+
async function walk(dir, out) {
|
|
34
|
+
let entries;
|
|
35
|
+
try {
|
|
36
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
const full = join(dir, entry.name);
|
|
43
|
+
if (entry.isSymbolicLink())
|
|
44
|
+
continue;
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
await walk(full, out);
|
|
47
|
+
}
|
|
48
|
+
else if (entry.isFile() && entry.name === "SKILL.md") {
|
|
49
|
+
out.push(full);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function injectVersion(content, version) {
|
|
54
|
+
const versionLine = `version: "${version}"`;
|
|
55
|
+
const fm = content.match(FRONTMATTER_RE);
|
|
56
|
+
if (!fm) {
|
|
57
|
+
// No frontmatter at all — prepend a minimal one.
|
|
58
|
+
return `---\n${versionLine}\n---\n${content}`;
|
|
59
|
+
}
|
|
60
|
+
if (VERSION_LINE_RE.test(fm[1])) {
|
|
61
|
+
return content; // already has version → no-op
|
|
62
|
+
}
|
|
63
|
+
const newBlock = `${versionLine}\n${fm[1]}`;
|
|
64
|
+
const closer = fm[0].endsWith("---\n") ? "---\n" : "---";
|
|
65
|
+
const before = content.slice(0, fm.index ?? 0);
|
|
66
|
+
const after = content.slice((fm.index ?? 0) + fm[0].length);
|
|
67
|
+
return `${before}---\n${newBlock}\n${closer}${after}`;
|
|
68
|
+
}
|
|
69
|
+
export async function stampVersionsCommand(opts = {}) {
|
|
70
|
+
const home = homedir();
|
|
71
|
+
const defaultRoots = [
|
|
72
|
+
join(home, ".claude", "skills"),
|
|
73
|
+
join(home, ".claude", "plugins", "cache"),
|
|
74
|
+
];
|
|
75
|
+
const roots = (opts.root && opts.root.length > 0 ? opts.root : defaultRoots).map((r) => resolve(r));
|
|
76
|
+
const version = opts.version ?? "1.0.0";
|
|
77
|
+
const write = !!opts.write;
|
|
78
|
+
// Safety: refuse to walk a root that isn't under $HOME (prevents ./. or /).
|
|
79
|
+
const safeRoots = [];
|
|
80
|
+
for (const r of roots) {
|
|
81
|
+
if (r === home || r === resolve(home)) {
|
|
82
|
+
// Refuse a literal home root — would scan EVERYTHING.
|
|
83
|
+
console.error(`vskill stamp-versions: refusing to walk full home dir: ${r}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (!r.startsWith(home + sep)) {
|
|
87
|
+
console.error(`vskill stamp-versions: refusing to walk outside home: ${r}`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
safeRoots.push(r);
|
|
91
|
+
}
|
|
92
|
+
const files = await findSkillMdFiles(safeRoots);
|
|
93
|
+
const results = [];
|
|
94
|
+
let stamped = 0;
|
|
95
|
+
let already = 0;
|
|
96
|
+
let errors = 0;
|
|
97
|
+
for (const path of files) {
|
|
98
|
+
try {
|
|
99
|
+
const content = await fs.readFile(path, "utf8");
|
|
100
|
+
const fm = content.match(FRONTMATTER_RE);
|
|
101
|
+
if (!fm) {
|
|
102
|
+
// No frontmatter — we'd be creating one. That's invasive; skip in dry-run
|
|
103
|
+
// by default and only act on existing-frontmatter cases for stamp-versions.
|
|
104
|
+
// The full publish flow stamps unconditionally; this CLI is conservative.
|
|
105
|
+
results.push({ path, action: "skipped-no-frontmatter" });
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (VERSION_LINE_RE.test(fm[1])) {
|
|
109
|
+
const m = fm[1].match(VERSION_LINE_RE);
|
|
110
|
+
results.push({ path, action: "skipped-has-version", current: m?.[1] ?? null });
|
|
111
|
+
already++;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const next = injectVersion(content, version);
|
|
115
|
+
if (write) {
|
|
116
|
+
await fs.writeFile(path, next, "utf8");
|
|
117
|
+
}
|
|
118
|
+
results.push({ path, action: "stamped", next: version });
|
|
119
|
+
stamped++;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
123
|
+
results.push({ path, action: "error", error: msg });
|
|
124
|
+
errors++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Reporting
|
|
128
|
+
if (opts.json) {
|
|
129
|
+
process.stdout.write(JSON.stringify({ scanned: files.length, stamped, alreadyHadVersion: already, errors, results, dryRun: !write, version }, null, 2) + "\n");
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const dryNote = write ? "(applied)" : "(dry-run — pass --write to apply)";
|
|
133
|
+
process.stdout.write(`vskill stamp-versions ${dryNote}\n`);
|
|
134
|
+
process.stdout.write(` scanned: ${files.length}\n`);
|
|
135
|
+
process.stdout.write(` stamped: ${stamped} (with version "${version}")\n`);
|
|
136
|
+
process.stdout.write(` already had version: ${already}\n`);
|
|
137
|
+
process.stdout.write(` errors: ${errors}\n`);
|
|
138
|
+
if (stamped > 0) {
|
|
139
|
+
process.stdout.write(`\nFiles ${write ? "stamped" : "would stamp"}:\n`);
|
|
140
|
+
for (const r of results.filter((r) => r.action === "stamped")) {
|
|
141
|
+
process.stdout.write(` + ${r.path}\n`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (errors > 0) {
|
|
145
|
+
process.stdout.write(`\nErrors:\n`);
|
|
146
|
+
for (const r of results.filter((r) => r.action === "error")) {
|
|
147
|
+
process.stdout.write(` ! ${r.path}: ${r.error}\n`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { scanned: files.length, stamped, alreadyHadVersion: already, errors, results };
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=stamp-versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stamp-versions.js","sourceRoot":"","sources":["../../src/commands/stamp-versions.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ import { resolveSkillApiName as resolveSkillApiNameImpl } from "./skill-name-res
|
|
|
14
14
|
import { runBenchmarkSSE, runSingleCaseSSE } from "./benchmark-runner.js";
|
|
15
15
|
import { getSkillSemaphore } from "./concurrency.js";
|
|
16
16
|
import { resolveSkillDir, resolveAllowedSkillDir } from "./skill-resolver.js";
|
|
17
|
-
import { setSkillDirEntry } from "./skill-dir-registry.js";
|
|
17
|
+
import { setSkillDirEntry, ensurePluginCacheEntry } from "./skill-dir-registry.js";
|
|
18
18
|
import { pickInstalledVersion, readSkillMd, sha256Hex, } from "./installed-version.js";
|
|
19
19
|
import { extractFrontmatterVersion } from "../utils/version.js";
|
|
20
20
|
import { classifyOrigin, scanSkillsTriScope, dedupeByDir } from "../eval/skill-scanner.js";
|
|
@@ -1876,12 +1876,20 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1876
1876
|
join(home, ".claude/skills"),
|
|
1877
1877
|
];
|
|
1878
1878
|
};
|
|
1879
|
-
|
|
1879
|
+
// 0769 F-002: cold-server deep links to /api/skills/:plugin/:skill/files (or
|
|
1880
|
+
// /file) hit the route before the user has visited /api/skills, so the
|
|
1881
|
+
// SkillDirRegistry hasn't been populated yet. Lazy-fill it on registry miss
|
|
1882
|
+
// by running scanInstalledPluginSkills once. Subsequent calls hit the fast
|
|
1883
|
+
// path via setSkillDirEntry inside ensurePluginCacheEntry.
|
|
1884
|
+
const resolveSkillDirForFsRoute = async (plugin, skill) => {
|
|
1885
|
+
await ensurePluginCacheEntry(plugin, skill);
|
|
1886
|
+
return resolveAllowedSkillDir(root, plugin, skill, skillFsAllowedRoots());
|
|
1887
|
+
};
|
|
1880
1888
|
// Get skill detail
|
|
1881
1889
|
router.get("/api/skills/:plugin/:skill", async (req, res, params) => {
|
|
1882
1890
|
let skillDir;
|
|
1883
1891
|
try {
|
|
1884
|
-
skillDir = resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1892
|
+
skillDir = await resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1885
1893
|
}
|
|
1886
1894
|
catch (err) {
|
|
1887
1895
|
sendJson(res, { error: err.message }, 400, req);
|
|
@@ -1899,7 +1907,7 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1899
1907
|
router.get("/api/skills/:plugin/:skill/files", async (req, res, params) => {
|
|
1900
1908
|
let skillDir;
|
|
1901
1909
|
try {
|
|
1902
|
-
skillDir = resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1910
|
+
skillDir = await resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1903
1911
|
}
|
|
1904
1912
|
catch (err) {
|
|
1905
1913
|
sendJson(res, { error: err.message }, 400, req);
|
|
@@ -1960,7 +1968,7 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1960
1968
|
router.get("/api/skills/:plugin/:skill/file", async (req, res, params) => {
|
|
1961
1969
|
let skillDir;
|
|
1962
1970
|
try {
|
|
1963
|
-
skillDir = resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1971
|
+
skillDir = await resolveSkillDirForFsRoute(params.plugin, params.skill);
|
|
1964
1972
|
}
|
|
1965
1973
|
catch (err) {
|
|
1966
1974
|
sendJson(res, { error: err.message }, 400, req);
|