vskill 0.1.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.
Files changed (59) hide show
  1. package/README.md +49 -0
  2. package/dist/agents/agents-registry.d.ts +57 -0
  3. package/dist/agents/agents-registry.js +511 -0
  4. package/dist/agents/agents-registry.js.map +1 -0
  5. package/dist/api/client.d.ts +50 -0
  6. package/dist/api/client.js +50 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/commands/add.d.ts +7 -0
  9. package/dist/commands/add.js +126 -0
  10. package/dist/commands/add.js.map +1 -0
  11. package/dist/commands/find.d.ts +1 -0
  12. package/dist/commands/find.js +42 -0
  13. package/dist/commands/find.js.map +1 -0
  14. package/dist/commands/init.d.ts +1 -0
  15. package/dist/commands/init.js +39 -0
  16. package/dist/commands/init.js.map +1 -0
  17. package/dist/commands/list.d.ts +6 -0
  18. package/dist/commands/list.js +79 -0
  19. package/dist/commands/list.js.map +1 -0
  20. package/dist/commands/scan.d.ts +1 -0
  21. package/dist/commands/scan.js +99 -0
  22. package/dist/commands/scan.js.map +1 -0
  23. package/dist/commands/submit.d.ts +5 -0
  24. package/dist/commands/submit.js +34 -0
  25. package/dist/commands/submit.js.map +1 -0
  26. package/dist/commands/update.d.ts +5 -0
  27. package/dist/commands/update.js +114 -0
  28. package/dist/commands/update.js.map +1 -0
  29. package/dist/commands/version.d.ts +1 -0
  30. package/dist/commands/version.js +11 -0
  31. package/dist/commands/version.js.map +1 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.js +68 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lockfile/index.d.ts +2 -0
  36. package/dist/lockfile/index.js +2 -0
  37. package/dist/lockfile/index.js.map +1 -0
  38. package/dist/lockfile/lockfile.d.ts +23 -0
  39. package/dist/lockfile/lockfile.js +70 -0
  40. package/dist/lockfile/lockfile.js.map +1 -0
  41. package/dist/lockfile/types.d.ts +14 -0
  42. package/dist/lockfile/types.js +5 -0
  43. package/dist/lockfile/types.js.map +1 -0
  44. package/dist/scanner/index.d.ts +4 -0
  45. package/dist/scanner/index.js +3 -0
  46. package/dist/scanner/index.js.map +1 -0
  47. package/dist/scanner/patterns.d.ts +25 -0
  48. package/dist/scanner/patterns.js +347 -0
  49. package/dist/scanner/patterns.js.map +1 -0
  50. package/dist/scanner/pipeline/submission-pipeline.d.ts +100 -0
  51. package/dist/scanner/pipeline/submission-pipeline.js +173 -0
  52. package/dist/scanner/pipeline/submission-pipeline.js.map +1 -0
  53. package/dist/scanner/tier1.d.ts +23 -0
  54. package/dist/scanner/tier1.js +83 -0
  55. package/dist/scanner/tier1.js.map +1 -0
  56. package/dist/utils/output.d.ts +15 -0
  57. package/dist/utils/output.js +87 -0
  58. package/dist/utils/output.js.map +1 -0
  59. package/package.json +51 -0
@@ -0,0 +1,50 @@
1
+ export interface SkillSearchResult {
2
+ name: string;
3
+ author: string;
4
+ tier: string;
5
+ score: number;
6
+ installs: number;
7
+ description: string;
8
+ }
9
+ export interface SkillDetail {
10
+ name: string;
11
+ author: string;
12
+ tier: string;
13
+ score: number;
14
+ version: string;
15
+ sha: string;
16
+ description: string;
17
+ content?: string;
18
+ installs: number;
19
+ updatedAt: string;
20
+ }
21
+ export interface SubmissionResponse {
22
+ id: string;
23
+ status: string;
24
+ trackingUrl: string;
25
+ }
26
+ export interface SubmissionRequest {
27
+ repoUrl: string;
28
+ skillName?: string;
29
+ email?: string;
30
+ }
31
+ /**
32
+ * Search for skills in the registry.
33
+ */
34
+ export declare function searchSkills(query: string): Promise<SkillSearchResult[]>;
35
+ /**
36
+ * Get a single skill by name.
37
+ */
38
+ export declare function getSkill(name: string): Promise<SkillDetail>;
39
+ /**
40
+ * Submit a skill for verification.
41
+ */
42
+ export declare function submitSkill(data: SubmissionRequest): Promise<SubmissionResponse>;
43
+ /**
44
+ * Get the status of a submission.
45
+ */
46
+ export declare function getSubmission(id: string): Promise<{
47
+ id: string;
48
+ status: string;
49
+ result?: unknown;
50
+ }>;
@@ -0,0 +1,50 @@
1
+ // ---------------------------------------------------------------------------
2
+ // HTTP client for verified-skill.com API
3
+ // ---------------------------------------------------------------------------
4
+ const BASE_URL = "https://verified-skill.com";
5
+ async function apiRequest(path, options) {
6
+ const url = `${BASE_URL}${path}`;
7
+ const res = await fetch(url, {
8
+ ...options,
9
+ headers: {
10
+ "Content-Type": "application/json",
11
+ "User-Agent": "vskill-cli",
12
+ ...options?.headers,
13
+ },
14
+ });
15
+ if (!res.ok) {
16
+ const body = await res.text().catch(() => "");
17
+ throw new Error(`API request failed: ${res.status} ${res.statusText}${body ? ` - ${body}` : ""}`);
18
+ }
19
+ return res.json();
20
+ }
21
+ /**
22
+ * Search for skills in the registry.
23
+ */
24
+ export async function searchSkills(query) {
25
+ const encoded = encodeURIComponent(query);
26
+ return apiRequest(`/api/v1/skills?search=${encoded}`);
27
+ }
28
+ /**
29
+ * Get a single skill by name.
30
+ */
31
+ export async function getSkill(name) {
32
+ const encoded = encodeURIComponent(name);
33
+ return apiRequest(`/api/v1/skills/${encoded}`);
34
+ }
35
+ /**
36
+ * Submit a skill for verification.
37
+ */
38
+ export async function submitSkill(data) {
39
+ return apiRequest("/api/v1/submissions", {
40
+ method: "POST",
41
+ body: JSON.stringify(data),
42
+ });
43
+ }
44
+ /**
45
+ * Get the status of a submission.
46
+ */
47
+ export async function getSubmission(id) {
48
+ return apiRequest(`/api/v1/submissions/${encodeURIComponent(id)}`);
49
+ }
50
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAE9E,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAoC9C,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,OAAqB;IAErB,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,YAAY,EAAE,YAAY;YAC1B,GAAG,OAAO,EAAE,OAAO;SACpB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,uBAAuB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa;IAEb,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,UAAU,CACf,yBAAyB,OAAO,EAAE,CACnC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,UAAU,CAAc,kBAAkB,OAAO,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAuB;IAEvB,OAAO,UAAU,CAAqB,qBAAqB,EAAE;QAC3D,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAU;IAEV,OAAO,UAAU,CAAC,uBAAuB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,7 @@
1
+ interface AddOptions {
2
+ skill?: string;
3
+ global?: boolean;
4
+ force?: boolean;
5
+ }
6
+ export declare function addCommand(source: string, opts: AddOptions): Promise<void>;
7
+ export {};
@@ -0,0 +1,126 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill add -- install a skill from GitHub with security scanning
3
+ // ---------------------------------------------------------------------------
4
+ import { mkdirSync, writeFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { createHash } from "node:crypto";
7
+ import { detectInstalledAgents } from "../agents/agents-registry.js";
8
+ import { ensureLockfile, writeLockfile } from "../lockfile/index.js";
9
+ import { runTier1Scan } from "../scanner/index.js";
10
+ import { bold, green, red, yellow, dim, cyan, spinner, } from "../utils/output.js";
11
+ async function fetchSkillContent(url) {
12
+ const spin = spinner("Fetching skill");
13
+ try {
14
+ const res = await fetch(url);
15
+ if (!res.ok) {
16
+ spin.stop();
17
+ if (res.status === 404) {
18
+ console.error(red(`SKILL.md not found at ${url}\n`) +
19
+ dim("Make sure the repo exists and has a SKILL.md on the main branch."));
20
+ }
21
+ else {
22
+ console.error(red(`Failed to fetch: ${res.status} ${res.statusText}`));
23
+ }
24
+ return process.exit(1);
25
+ }
26
+ const content = await res.text();
27
+ spin.stop(green("Fetched SKILL.md"));
28
+ return content;
29
+ }
30
+ catch (err) {
31
+ spin.stop();
32
+ console.error(red("Network error: ") + dim(err.message));
33
+ return process.exit(1);
34
+ }
35
+ }
36
+ export async function addCommand(source, opts) {
37
+ // Parse owner/repo
38
+ const parts = source.split("/");
39
+ if (parts.length !== 2) {
40
+ console.error(red("Invalid source format. Use: ") + cyan("owner/repo"));
41
+ process.exit(1);
42
+ }
43
+ const [owner, repo] = parts;
44
+ const skillSubpath = opts.skill
45
+ ? `skills/${opts.skill}/SKILL.md`
46
+ : "SKILL.md";
47
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/main/${skillSubpath}`;
48
+ // Fetch SKILL.md
49
+ const content = await fetchSkillContent(url);
50
+ // Run tier1 scan
51
+ console.log(dim("\nRunning security scan..."));
52
+ const scanResult = runTier1Scan(content);
53
+ const verdictColor = scanResult.verdict === "PASS"
54
+ ? green
55
+ : scanResult.verdict === "CONCERNS"
56
+ ? yellow
57
+ : red;
58
+ console.log(`${bold("Score:")} ${verdictColor(String(scanResult.score))}/100 ` +
59
+ `${bold("Verdict:")} ${verdictColor(scanResult.verdict)}\n`);
60
+ if (scanResult.findings.length > 0) {
61
+ console.log(dim(`Found ${scanResult.findings.length} issue${scanResult.findings.length === 1 ? "" : "s"}: ` +
62
+ `${scanResult.criticalCount} critical, ${scanResult.highCount} high, ${scanResult.mediumCount} medium`));
63
+ }
64
+ // Decision based on verdict
65
+ if (scanResult.verdict === "FAIL" && !opts.force) {
66
+ console.error(red("\nScan FAILED. Refusing to install.\n") +
67
+ dim("Use --force to install anyway (not recommended)."));
68
+ process.exit(1);
69
+ }
70
+ if (scanResult.verdict === "CONCERNS" && !opts.force) {
71
+ console.error(yellow("\nScan found CONCERNS. Refusing to install.\n") +
72
+ dim("Use --force to install anyway."));
73
+ process.exit(1);
74
+ }
75
+ if (scanResult.verdict === "FAIL" && opts.force) {
76
+ console.log(yellow("\n--force: installing despite FAIL verdict.\n"));
77
+ }
78
+ if (scanResult.verdict === "CONCERNS" && opts.force) {
79
+ console.log(yellow("\n--force: installing despite CONCERNS.\n"));
80
+ }
81
+ // Detect installed agents
82
+ const agents = await detectInstalledAgents();
83
+ if (agents.length === 0) {
84
+ console.error(red("No AI agents detected. Run ") +
85
+ cyan("vskill init") +
86
+ red(" first."));
87
+ process.exit(1);
88
+ }
89
+ // Install to each agent
90
+ const skillName = opts.skill || repo;
91
+ const sha = createHash("sha256").update(content).digest("hex").slice(0, 12);
92
+ const locations = [];
93
+ for (const agent of agents) {
94
+ const baseDir = opts.global
95
+ ? agent.globalSkillsDir
96
+ : join(process.cwd(), agent.localSkillsDir);
97
+ const skillDir = join(baseDir, skillName);
98
+ try {
99
+ mkdirSync(skillDir, { recursive: true });
100
+ writeFileSync(join(skillDir, "SKILL.md"), content, "utf-8");
101
+ locations.push(`${agent.displayName}: ${skillDir}`);
102
+ }
103
+ catch (err) {
104
+ console.error(yellow(`Failed to write to ${agent.displayName}: `) +
105
+ dim(err.message));
106
+ }
107
+ }
108
+ // Update lockfile
109
+ const lock = ensureLockfile();
110
+ lock.skills[skillName] = {
111
+ version: "0.0.0",
112
+ sha,
113
+ tier: "SCANNED",
114
+ installedAt: new Date().toISOString(),
115
+ source: `github:${owner}/${repo}`,
116
+ };
117
+ lock.agents = agents.map((a) => a.id);
118
+ writeLockfile(lock);
119
+ // Print summary
120
+ console.log(green(`\nInstalled ${bold(skillName)} to ${locations.length} agent${locations.length === 1 ? "" : "s"}:\n`));
121
+ for (const loc of locations) {
122
+ console.log(` ${dim(">")} ${loc}`);
123
+ }
124
+ console.log(dim(`\nSHA: ${sha}`));
125
+ }
126
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function findCommand(query: string): Promise<void>;
@@ -0,0 +1,42 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill find -- search the verified-skill.com registry
3
+ // ---------------------------------------------------------------------------
4
+ import { searchSkills } from "../api/client.js";
5
+ import { bold, green, yellow, dim, cyan, red, table } from "../utils/output.js";
6
+ export async function findCommand(query) {
7
+ console.log(dim(`Searching for "${query}"...\n`));
8
+ let results;
9
+ try {
10
+ const response = await searchSkills(query);
11
+ results = Array.isArray(response) ? response : [];
12
+ }
13
+ catch (err) {
14
+ console.error(red("Failed to search registry: ") +
15
+ dim(err.message));
16
+ process.exit(1);
17
+ return;
18
+ }
19
+ if (results.length === 0) {
20
+ console.log(dim("No skills found matching your query."));
21
+ console.log(dim(`Try a broader search or visit ${cyan("https://verified-skill.com")}`));
22
+ return;
23
+ }
24
+ const headers = ["Name", "Author", "Tier", "Score", "Installs"];
25
+ const rows = results.map((r) => {
26
+ const tierColor = r.tier === "CERTIFIED"
27
+ ? yellow
28
+ : r.tier === "VERIFIED"
29
+ ? green
30
+ : dim;
31
+ return [
32
+ bold(r.name),
33
+ r.author || "-",
34
+ tierColor(r.tier || "SCANNED"),
35
+ String(r.score ?? "-"),
36
+ String(r.installs ?? 0),
37
+ ];
38
+ });
39
+ console.log(table(headers, rows));
40
+ console.log(dim(`\n${results.length} result${results.length === 1 ? "" : "s"} found`));
41
+ }
42
+ //# sourceMappingURL=find.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../src/commands/find.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wDAAwD;AACxD,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAa;IAC7C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC;IAElD,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,GAAG,CAAC,6BAA6B,CAAC;YAChC,GAAG,CAAE,GAAa,CAAC,OAAO,CAAC,CAC9B,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,iCAAiC,IAAI,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAC3E,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,SAAS,GACb,CAAC,CAAC,IAAI,KAAK,WAAW;YACpB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU;gBACrB,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,GAAG,CAAC;QACZ,OAAO;YACL,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACZ,CAAC,CAAC,MAAM,IAAI,GAAG;YACf,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;YAC9B,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC;YACtB,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;SACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,KAAK,OAAO,CAAC,MAAM,UAAU,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAC1E,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function initCommand(): Promise<void>;
@@ -0,0 +1,39 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill init -- detect agents and create lockfile
3
+ // ---------------------------------------------------------------------------
4
+ import { detectInstalledAgents, TOTAL_AGENTS, } from "../agents/agents-registry.js";
5
+ import { readLockfile, writeLockfile, ensureLockfile } from "../lockfile/index.js";
6
+ import { bold, green, dim, cyan, table } from "../utils/output.js";
7
+ export async function initCommand() {
8
+ console.log(bold("Detecting installed AI agents...\n"));
9
+ const agents = await detectInstalledAgents();
10
+ if (agents.length === 0) {
11
+ console.log(dim(`No agents detected out of ${TOTAL_AGENTS} known agents.`));
12
+ console.log(dim("Install an AI agent (Claude Code, Cursor, etc.) and re-run.\n"));
13
+ }
14
+ else {
15
+ const headers = ["Agent", "Company", "Skills Dir"];
16
+ const rows = agents.map((a) => [
17
+ green(a.displayName),
18
+ dim(a.parentCompany || "-"),
19
+ dim(a.localSkillsDir),
20
+ ]);
21
+ console.log(table(headers, rows));
22
+ console.log(`\n${green(`${agents.length}`)} agent${agents.length === 1 ? "" : "s"} detected out of ${TOTAL_AGENTS} known\n`);
23
+ }
24
+ // Create or update lockfile
25
+ const existing = readLockfile();
26
+ if (existing) {
27
+ existing.agents = agents.map((a) => a.id);
28
+ writeLockfile(existing);
29
+ console.log(dim("Updated existing vskill.lock"));
30
+ }
31
+ else {
32
+ const lock = ensureLockfile();
33
+ lock.agents = agents.map((a) => a.id);
34
+ writeLockfile(lock);
35
+ console.log(green("Created vskill.lock"));
36
+ }
37
+ console.log(dim(`\nRun ${cyan("vskill add <owner/repo>")} to install a skill.`));
38
+ }
39
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mDAAmD;AACnD,8EAA8E;AAE9E,OAAO,EACL,qBAAqB,EACrB,YAAY,GACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAE7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,6BAA6B,YAAY,gBAAgB,CAAC,CAC/D,CAAC;QACF,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,+DAA+D,CAAC,CACrE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC7B,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;YACpB,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,GAAG,CAAC;YAC3B,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;SACtB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,oBAAoB,YAAY,UAAU,CAChH,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1C,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtC,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,SAAS,IAAI,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CACpE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface ListOptions {
2
+ agents?: boolean;
3
+ json?: boolean;
4
+ }
5
+ export declare function listCommand(opts: ListOptions): Promise<void>;
6
+ export {};
@@ -0,0 +1,79 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill list -- show installed skills or detected agents
3
+ // ---------------------------------------------------------------------------
4
+ import { readLockfile } from "../lockfile/index.js";
5
+ import { detectInstalledAgents, AGENTS_REGISTRY, } from "../agents/agents-registry.js";
6
+ import { bold, green, dim, cyan, yellow, table } from "../utils/output.js";
7
+ export async function listCommand(opts) {
8
+ if (opts.agents) {
9
+ await listAgents(opts.json);
10
+ }
11
+ else {
12
+ await listSkills(opts.json);
13
+ }
14
+ }
15
+ async function listAgents(json) {
16
+ const installed = await detectInstalledAgents();
17
+ const installedIds = new Set(installed.map((a) => a.id));
18
+ if (json) {
19
+ const data = AGENTS_REGISTRY.map((a) => ({
20
+ id: a.id,
21
+ name: a.displayName,
22
+ company: a.parentCompany || null,
23
+ installed: installedIds.has(a.id),
24
+ universal: a.isUniversal,
25
+ localDir: a.localSkillsDir,
26
+ }));
27
+ console.log(JSON.stringify(data, null, 2));
28
+ return;
29
+ }
30
+ console.log(bold(`AI Agents (${AGENTS_REGISTRY.length} known)\n`));
31
+ const headers = ["Status", "Agent", "Company", "Type"];
32
+ const rows = AGENTS_REGISTRY.map((a) => [
33
+ installedIds.has(a.id) ? green("*") : dim("-"),
34
+ installedIds.has(a.id) ? bold(a.displayName) : a.displayName,
35
+ dim(a.parentCompany || "-"),
36
+ a.isUniversal ? cyan("universal") : dim("custom"),
37
+ ]);
38
+ console.log(table(headers, rows));
39
+ console.log(`\n${green(`${installed.length}`)} installed ${dim(`${AGENTS_REGISTRY.length} total`)}`);
40
+ }
41
+ async function listSkills(json) {
42
+ const lock = readLockfile();
43
+ if (!lock) {
44
+ console.log(yellow("No vskill.lock found. Run ") +
45
+ cyan("vskill init") +
46
+ yellow(" first."));
47
+ process.exit(1);
48
+ return; // unreachable but satisfies TS
49
+ }
50
+ const skillNames = Object.keys(lock.skills);
51
+ if (json) {
52
+ console.log(JSON.stringify(lock.skills, null, 2));
53
+ return;
54
+ }
55
+ if (skillNames.length === 0) {
56
+ console.log(dim("No skills installed yet."));
57
+ console.log(dim(`Run ${cyan("vskill add <owner/repo>")} to install a skill.`));
58
+ return;
59
+ }
60
+ console.log(bold(`Installed Skills (${skillNames.length})\n`));
61
+ const headers = ["Skill", "Version", "Tier", "Source", "Installed"];
62
+ const rows = skillNames.map((name) => {
63
+ const s = lock.skills[name];
64
+ const tierColor = s.tier === "CERTIFIED"
65
+ ? yellow
66
+ : s.tier === "VERIFIED"
67
+ ? green
68
+ : dim;
69
+ return [
70
+ bold(name),
71
+ s.version || "-",
72
+ tierColor(s.tier || "SCANNED"),
73
+ dim(s.source || "-"),
74
+ dim(s.installedAt ? new Date(s.installedAt).toLocaleDateString() : "-"),
75
+ ];
76
+ });
77
+ console.log(table(headers, rows));
78
+ }
79
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function scanCommand(path: string): Promise<void>;
@@ -0,0 +1,99 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill scan -- run tier1 security scan on a SKILL.md
3
+ // ---------------------------------------------------------------------------
4
+ import { readFileSync, existsSync, statSync } from "node:fs";
5
+ import { join, resolve } from "node:path";
6
+ import { runTier1Scan } from "../scanner/index.js";
7
+ import { bold, green, red, yellow, dim, cyan, table } from "../utils/output.js";
8
+ export async function scanCommand(path) {
9
+ const resolved = resolve(path);
10
+ const filePath = resolveSkillPath(resolved);
11
+ if (!filePath) {
12
+ process.exit(2);
13
+ }
14
+ const content = readFileSync(filePath, "utf-8");
15
+ console.log(bold(`Scanning ${dim(filePath)}\n`));
16
+ const result = runTier1Scan(content);
17
+ // Print verdict
18
+ const verdictColor = result.verdict === "PASS"
19
+ ? green
20
+ : result.verdict === "CONCERNS"
21
+ ? yellow
22
+ : red;
23
+ console.log(`${bold("Score:")} ${verdictColor(String(result.score))}/100 ` +
24
+ `${bold("Verdict:")} ${verdictColor(result.verdict)} ` +
25
+ `${bold("Patterns:")} ${result.patternsChecked} ` +
26
+ `${bold("Time:")} ${result.durationMs}ms\n`);
27
+ // Print findings summary
28
+ if (result.findings.length === 0) {
29
+ console.log(green("No security issues found.\n"));
30
+ }
31
+ else {
32
+ const summary = [
33
+ result.criticalCount > 0
34
+ ? red(`${result.criticalCount} critical`)
35
+ : null,
36
+ result.highCount > 0
37
+ ? yellow(`${result.highCount} high`)
38
+ : null,
39
+ result.mediumCount > 0
40
+ ? cyan(`${result.mediumCount} medium`)
41
+ : null,
42
+ result.lowCount > 0
43
+ ? dim(`${result.lowCount} low`)
44
+ : null,
45
+ result.infoCount > 0
46
+ ? dim(`${result.infoCount} info`)
47
+ : null,
48
+ ]
49
+ .filter(Boolean)
50
+ .join(" ");
51
+ console.log(`${bold("Findings:")} ${summary}\n`);
52
+ // Print detailed findings
53
+ printFindings(result.findings);
54
+ }
55
+ // Exit code
56
+ if (result.verdict === "FAIL")
57
+ process.exit(2);
58
+ if (result.verdict === "CONCERNS")
59
+ process.exit(1);
60
+ process.exit(0);
61
+ }
62
+ function resolveSkillPath(resolved) {
63
+ if (existsSync(resolved) && statSync(resolved).isDirectory()) {
64
+ const candidate = join(resolved, "SKILL.md");
65
+ if (existsSync(candidate)) {
66
+ return candidate;
67
+ }
68
+ console.error(red(`No SKILL.md found in ${resolved}`));
69
+ return null;
70
+ }
71
+ if (existsSync(resolved)) {
72
+ return resolved;
73
+ }
74
+ console.error(red(`File not found: ${resolved}`));
75
+ return null;
76
+ }
77
+ function printFindings(findings) {
78
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
79
+ const sorted = [...findings].sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
80
+ const headers = ["Severity", "Pattern", "Category", "Line", "Match"];
81
+ const rows = sorted.map((f) => {
82
+ const sevColor = f.severity === "critical"
83
+ ? red
84
+ : f.severity === "high"
85
+ ? yellow
86
+ : f.severity === "medium"
87
+ ? cyan
88
+ : dim;
89
+ return [
90
+ sevColor(f.severity.toUpperCase()),
91
+ f.patternName,
92
+ dim(f.category),
93
+ String(f.lineNumber),
94
+ dim(f.match.substring(0, 40)),
95
+ ];
96
+ });
97
+ console.log(table(headers, rows));
98
+ }
99
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ interface SubmitOptions {
2
+ email?: string;
3
+ }
4
+ export declare function submitCommand(source: string, opts: SubmitOptions): Promise<void>;
5
+ export {};
@@ -0,0 +1,34 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill submit -- submit a skill for verification
3
+ // ---------------------------------------------------------------------------
4
+ import { submitSkill } from "../api/client.js";
5
+ import { bold, green, red, dim, cyan } from "../utils/output.js";
6
+ export async function submitCommand(source, opts) {
7
+ // Parse owner/repo
8
+ const parts = source.split("/");
9
+ if (parts.length !== 2) {
10
+ console.error(red("Invalid source format. Use: ") + cyan("owner/repo"));
11
+ process.exit(1);
12
+ }
13
+ const [owner, repo] = parts;
14
+ const repoUrl = `https://github.com/${owner}/${repo}`;
15
+ console.log(dim(`Submitting ${bold(`${owner}/${repo}`)} for verification...\n`));
16
+ try {
17
+ const result = await submitSkill({
18
+ repoUrl,
19
+ skillName: repo,
20
+ email: opts.email,
21
+ });
22
+ console.log(green("Submission received!\n"));
23
+ console.log(`${bold("Submission ID:")} ${result.id}`);
24
+ console.log(`${bold("Status:")} ${result.status}`);
25
+ console.log(`${bold("Track at:")} ${cyan(result.trackingUrl || `https://verified-skill.com/submissions/${result.id}`)}`);
26
+ console.log(dim("\nYou will receive updates as the review progresses."));
27
+ }
28
+ catch (err) {
29
+ console.error(red("Submission failed: ") +
30
+ dim(err.message));
31
+ process.exit(1);
32
+ }
33
+ }
34
+ //# sourceMappingURL=submit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mDAAmD;AACnD,8EAA8E;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAMjE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,IAAmB;IAEnB,mBAAmB;IACnB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CACX,GAAG,CAAC,8BAA8B,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CACzD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAC5B,MAAM,OAAO,GAAG,sBAAsB,KAAK,IAAI,IAAI,EAAE,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAEjF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;YAC/B,OAAO;YACP,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,0CAA0C,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CACjH,CAAC;QACF,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,sDAAsD,CAAC,CAC5D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,GAAG,CAAC,qBAAqB,CAAC;YACxB,GAAG,CAAE,GAAa,CAAC,OAAO,CAAC,CAC9B,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ interface UpdateOptions {
2
+ all?: boolean;
3
+ }
4
+ export declare function updateCommand(skill: string | undefined, opts: UpdateOptions): Promise<void>;
5
+ export {};