skillvault-publisher 0.7.2 → 0.7.4
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/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/index.js +173 -516
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/login.js
CHANGED
|
@@ -19,7 +19,7 @@ export const loginCommand = new Command('login')
|
|
|
19
19
|
.description('Authenticate with the Skill Vault server')
|
|
20
20
|
.option('--license-key <key>', 'Authenticate with a license key')
|
|
21
21
|
.option('--code <code>', 'Authenticate with an invite code')
|
|
22
|
-
.option('--server <url>', 'Server URL', '
|
|
22
|
+
.option('--server <url>', 'Server URL', 'https://api.getskillvault.com')
|
|
23
23
|
.action(async (options) => {
|
|
24
24
|
try {
|
|
25
25
|
const serverUrl = options.server;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE7D,kEAAkE;AAClE,SAAS,qBAAqB;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IACzE,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,qBAAqB,EAAE,iCAAiC,CAAC;KAChE,MAAM,CAAC,eAAe,EAAE,kCAAkC,CAAC;KAC3D,MAAM,CAAC,gBAAgB,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE7D,kEAAkE;AAClE,SAAS,qBAAqB;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IACzE,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,qBAAqB,EAAE,iCAAiC,CAAC;KAChE,MAAM,CAAC,eAAe,EAAE,kCAAkC,CAAC;KAC3D,MAAM,CAAC,gBAAgB,EAAE,YAAY,EAAE,+BAA+B,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjC,gCAAgC;QAChC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7G,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrD,YAAY,CAAC,GAAG,GAAG,OAAO,CAAC;QAC3B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAE7E,yBAAyB;QACzB,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAClI,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnD,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC;QAC1B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAErD,gBAAgB;QAChB,MAAM,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;YACrC,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,SAAS;YACd,eAAe,EAAE,YAAY;YAC7B,gBAAgB,EAAE,WAAW;YAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE;SACzB,CAAC;aACC,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;aACrD,WAAW,EAAE;aACb,iBAAiB,CAAC,KAAK,CAAC;aACxB,IAAI,CAAC,UAAU,CAAC,CAAC;QAEpB,uBAAuB;QACvB,MAAM,IAAI,GAA4B;YACpC,IAAI,EAAE,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE;YACzC,YAAY,EAAE,EAAE;YAChB,IAAI,EAAE,WAAW;SAClB,CAAC;QAEF,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;QACxC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,iBAAiB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,OAAO,EAAE;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAuC,CAAC;YAC1I,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAIjC,CAAC;QAEF,gCAAgC;QAChC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,iBAAiB,EAAE;gBAC3D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;aAC5E,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,wCAAwC,CAAC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,YAAY,CACV,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,EAC5C,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,CAC3C,CAAC;QAEF,UAAU,CAAC;YACT,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5C,yDAAyD;QACzD,qBAAqB,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,uDAAuD;AACvD,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+H1B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// dist/index.js
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command12 } from "commander";
|
|
5
5
|
|
|
6
6
|
// dist/commands/login.js
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -103,7 +103,7 @@ function installPublisherSkill() {
|
|
|
103
103
|
} catch {
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
var loginCommand = new Command("login").description("Authenticate with the Skill Vault server").option("--license-key <key>", "Authenticate with a license key").option("--code <code>", "Authenticate with an invite code").option("--server <url>", "Server URL", "
|
|
106
|
+
var loginCommand = new Command("login").description("Authenticate with the Skill Vault server").option("--license-key <key>", "Authenticate with a license key").option("--code <code>", "Authenticate with an invite code").option("--server <url>", "Server URL", "https://api.getskillvault.com").action(async (options) => {
|
|
107
107
|
try {
|
|
108
108
|
const serverUrl = options.server;
|
|
109
109
|
const { publicKey, privateKey } = await jose.generateKeyPair("EdDSA", { crv: "Ed25519", extractable: true });
|
|
@@ -336,18 +336,6 @@ var VaultVersionError = class extends Error {
|
|
|
336
336
|
this.name = "VaultVersionError";
|
|
337
337
|
}
|
|
338
338
|
};
|
|
339
|
-
var VaultTamperedError = class extends Error {
|
|
340
|
-
constructor(message) {
|
|
341
|
-
super(message);
|
|
342
|
-
this.name = "VaultTamperedError";
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
var VaultDecryptionError = class extends Error {
|
|
346
|
-
constructor(message) {
|
|
347
|
-
super(message);
|
|
348
|
-
this.name = "VaultDecryptionError";
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
339
|
|
|
352
340
|
// ../shared/dist/vault-format.js
|
|
353
341
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2, createHash } from "node:crypto";
|
|
@@ -441,68 +429,6 @@ function readVaultMetadata(data) {
|
|
|
441
429
|
const metadataJSON = data.subarray(offset, offset + metaLen);
|
|
442
430
|
return JSON.parse(metadataJSON.toString("utf8"));
|
|
443
431
|
}
|
|
444
|
-
function readVault(data, key) {
|
|
445
|
-
if (key.length !== 32) {
|
|
446
|
-
throw new Error("Key must be 32 bytes for AES-256-GCM");
|
|
447
|
-
}
|
|
448
|
-
if (data.length < HEADER_SIZE + 4) {
|
|
449
|
-
throw new VaultFormatError("File too small to be a valid .vault file");
|
|
450
|
-
}
|
|
451
|
-
let offset = 0;
|
|
452
|
-
const magic = data.subarray(offset, offset + 4);
|
|
453
|
-
offset += 4;
|
|
454
|
-
if (!magic.equals(VAULT_MAGIC)) {
|
|
455
|
-
throw new VaultFormatError("Not a valid .vault file (bad magic bytes)");
|
|
456
|
-
}
|
|
457
|
-
const version = data[offset++];
|
|
458
|
-
if (version !== VAULT_VERSION) {
|
|
459
|
-
throw new VaultVersionError(version);
|
|
460
|
-
}
|
|
461
|
-
offset += 1 + 2;
|
|
462
|
-
offset += 32;
|
|
463
|
-
const payloadIV = data.subarray(offset, offset + 12);
|
|
464
|
-
offset += 12;
|
|
465
|
-
const payloadAuthTag = data.subarray(offset, offset + 16);
|
|
466
|
-
offset += 16;
|
|
467
|
-
const metaLen = data.readUInt32BE(offset);
|
|
468
|
-
offset += 4;
|
|
469
|
-
const metadataJSON = data.subarray(offset, offset + metaLen);
|
|
470
|
-
offset += metaLen;
|
|
471
|
-
const manifestTotalLen = data.readUInt32BE(offset);
|
|
472
|
-
offset += 4;
|
|
473
|
-
const manifestIV = data.subarray(offset, offset + 12);
|
|
474
|
-
offset += 12;
|
|
475
|
-
const manifestTag = data.subarray(offset, offset + 16);
|
|
476
|
-
offset += 16;
|
|
477
|
-
const encryptedManifestLen = manifestTotalLen - 12 - 16;
|
|
478
|
-
const encryptedManifest = data.subarray(offset, offset + encryptedManifestLen);
|
|
479
|
-
offset += encryptedManifestLen;
|
|
480
|
-
const encryptedPayload = data.subarray(offset);
|
|
481
|
-
let manifestBuf;
|
|
482
|
-
try {
|
|
483
|
-
const manifestDecipher = createDecipheriv2(ALGORITHM, key, manifestIV, { authTagLength: 16 });
|
|
484
|
-
manifestDecipher.setAuthTag(manifestTag);
|
|
485
|
-
manifestBuf = Buffer.concat([manifestDecipher.update(encryptedManifest), manifestDecipher.final()]);
|
|
486
|
-
} catch {
|
|
487
|
-
throw new VaultDecryptionError("Failed to decrypt manifest \u2014 wrong key or tampered data");
|
|
488
|
-
}
|
|
489
|
-
const manifest = JSON.parse(manifestBuf.toString("utf8"));
|
|
490
|
-
let payload;
|
|
491
|
-
try {
|
|
492
|
-
const payloadDecipher = createDecipheriv2(ALGORITHM, key, payloadIV, { authTagLength: 16 });
|
|
493
|
-
payloadDecipher.setAuthTag(payloadAuthTag);
|
|
494
|
-
payloadDecipher.setAAD(metadataJSON);
|
|
495
|
-
payload = Buffer.concat([payloadDecipher.update(encryptedPayload), payloadDecipher.final()]);
|
|
496
|
-
} catch {
|
|
497
|
-
throw new VaultTamperedError("Decryption failed \u2014 metadata may have been tampered with");
|
|
498
|
-
}
|
|
499
|
-
const metadata = JSON.parse(metadataJSON.toString("utf8"));
|
|
500
|
-
const files = {};
|
|
501
|
-
for (const entry of manifest) {
|
|
502
|
-
files[entry.path] = payload.subarray(entry.offset, entry.offset + entry.size);
|
|
503
|
-
}
|
|
504
|
-
return { metadata, manifest, files };
|
|
505
|
-
}
|
|
506
432
|
|
|
507
433
|
// ../shared/dist/packer.js
|
|
508
434
|
import { readFileSync as readFileSync2, readdirSync, existsSync as existsSync2 } from "node:fs";
|
|
@@ -571,36 +497,11 @@ function packSkillDirectory(dirPath) {
|
|
|
571
497
|
|
|
572
498
|
// ../shared/dist/key-wrapping.js
|
|
573
499
|
import { randomBytes as randomBytes3, createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, hkdfSync, createPublicKey, createPrivateKey, diffieHellman, generateKeyPairSync } from "node:crypto";
|
|
574
|
-
var ALGORITHM2 = "aes-256-gcm";
|
|
575
500
|
var HKDF_INFO = Buffer.from("skillvault-cek-wrap-v1");
|
|
576
501
|
var HKDF_SALT = Buffer.alloc(32, 0);
|
|
577
502
|
function generateCEK() {
|
|
578
503
|
return randomBytes3(32);
|
|
579
504
|
}
|
|
580
|
-
function unwrapCEK(wrapped, agentPrivateKeyDer) {
|
|
581
|
-
const ephPubKey = createPublicKey({
|
|
582
|
-
key: wrapped.ephemeralPublicKey,
|
|
583
|
-
format: "der",
|
|
584
|
-
type: "spki"
|
|
585
|
-
});
|
|
586
|
-
const agentPrivKey = createPrivateKey({
|
|
587
|
-
key: agentPrivateKeyDer,
|
|
588
|
-
format: "der",
|
|
589
|
-
type: "pkcs8"
|
|
590
|
-
});
|
|
591
|
-
const sharedSecret = diffieHellman({
|
|
592
|
-
publicKey: ephPubKey,
|
|
593
|
-
privateKey: agentPrivKey
|
|
594
|
-
});
|
|
595
|
-
const wrappingKey = Buffer.from(hkdfSync("sha256", sharedSecret, HKDF_SALT, HKDF_INFO, 32));
|
|
596
|
-
try {
|
|
597
|
-
const decipher = createDecipheriv3(ALGORITHM2, wrappingKey, wrapped.iv, { authTagLength: 16 });
|
|
598
|
-
decipher.setAuthTag(wrapped.authTag);
|
|
599
|
-
return Buffer.concat([decipher.update(wrapped.wrappedKey), decipher.final()]);
|
|
600
|
-
} catch {
|
|
601
|
-
throw new VaultDecryptionError("Failed to unwrap CEK \u2014 wrong private key or tampered payload");
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
505
|
|
|
605
506
|
// ../shared/dist/watermark.js
|
|
606
507
|
var ZW_DECODE = {
|
|
@@ -906,261 +807,10 @@ var publishCommand = new Command3("publish").description("Encrypt and publish a
|
|
|
906
807
|
}
|
|
907
808
|
});
|
|
908
809
|
|
|
909
|
-
// dist/commands/
|
|
810
|
+
// dist/commands/search.js
|
|
910
811
|
import { Command as Command4 } from "commander";
|
|
911
812
|
import chalk4 from "chalk";
|
|
912
|
-
|
|
913
|
-
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
914
|
-
import { join as join5 } from "node:path";
|
|
915
|
-
import { homedir as homedir2 } from "node:os";
|
|
916
|
-
var SKILLS_DIR = join5(homedir2(), ".claude", "skills");
|
|
917
|
-
var DEPRECATION_NOTICE = `
|
|
918
|
-
${chalk4.yellow("\u26A0\uFE0F DEPRECATED:")} The install command is deprecated.
|
|
919
|
-
Use ${chalk4.cyan("npx skillvault --invite CODE")} instead.
|
|
920
|
-
This decrypts and installs skills as native Claude Code skills.
|
|
921
|
-
`;
|
|
922
|
-
var installCommand = new Command4("install").description("Install a skill from the registry").argument("<skill>", "Skill to install (publisher/skill-name)").action(async (skill) => {
|
|
923
|
-
console.log(DEPRECATION_NOTICE);
|
|
924
|
-
try {
|
|
925
|
-
const config = getConfig();
|
|
926
|
-
if (!config) {
|
|
927
|
-
process.stderr.write(chalk4.red("Not logged in. Run `skillvault-publisher login` first.\n"));
|
|
928
|
-
process.exit(1);
|
|
929
|
-
}
|
|
930
|
-
const keypair = getKeypair();
|
|
931
|
-
if (!keypair) {
|
|
932
|
-
process.stderr.write(chalk4.red("Credentials not found. Run `skillvault-publisher login` first.\n"));
|
|
933
|
-
process.exit(1);
|
|
934
|
-
}
|
|
935
|
-
const parts = skill.split("/");
|
|
936
|
-
const skillName = parts.length >= 2 ? parts[parts.length - 1] : parts[0];
|
|
937
|
-
const publisher = parts.length >= 2 ? parts[0] : "unknown";
|
|
938
|
-
const capabilityName = `skill/${skillName.toLowerCase()}`;
|
|
939
|
-
const hostPrivJWK = keypair.privateKey.host;
|
|
940
|
-
const hostPubJWK = keypair.publicKey.host;
|
|
941
|
-
const hostPrivKey = await jose3.importJWK(hostPrivJWK, "EdDSA");
|
|
942
|
-
const hostJWT = await new jose3.SignJWT({
|
|
943
|
-
iss: config.host_thumbprint,
|
|
944
|
-
aud: config.server_url,
|
|
945
|
-
host_public_key: hostPubJWK,
|
|
946
|
-
jti: crypto.randomUUID()
|
|
947
|
-
}).setProtectedHeader({ alg: "EdDSA", typ: "host+jwt" }).setIssuedAt().setExpirationTime("60s").sign(hostPrivKey);
|
|
948
|
-
const describeRes = await fetch(`${config.server_url}/capability/describe?name=${encodeURIComponent(capabilityName)}`, {
|
|
949
|
-
headers: { Authorization: `Bearer ${hostJWT}` }
|
|
950
|
-
});
|
|
951
|
-
if (!describeRes.ok) {
|
|
952
|
-
const err = await describeRes.json().catch(() => ({
|
|
953
|
-
error: "unknown",
|
|
954
|
-
message: describeRes.statusText
|
|
955
|
-
}));
|
|
956
|
-
process.stderr.write(chalk4.red(`Skill not found: ${err.message}
|
|
957
|
-
`));
|
|
958
|
-
process.exit(1);
|
|
959
|
-
}
|
|
960
|
-
const capData = await describeRes.json();
|
|
961
|
-
if (capData.type === "encrypted-skill" && capData.grant_status === "not_granted") {
|
|
962
|
-
process.stderr.write(chalk4.yellow("License required. Contact the skill publisher for access.\n"));
|
|
963
|
-
process.exit(1);
|
|
964
|
-
}
|
|
965
|
-
const downloadRes = await fetch(`${config.server_url}/skills/download?capability=${encodeURIComponent(capabilityName)}`, {
|
|
966
|
-
headers: { Authorization: `Bearer ${hostJWT}` }
|
|
967
|
-
});
|
|
968
|
-
if (!downloadRes.ok) {
|
|
969
|
-
const err = await downloadRes.json().catch(() => ({
|
|
970
|
-
error: "download_failed",
|
|
971
|
-
message: downloadRes.statusText
|
|
972
|
-
}));
|
|
973
|
-
process.stderr.write(chalk4.red(`Download failed: ${err.message}
|
|
974
|
-
`));
|
|
975
|
-
process.exit(1);
|
|
976
|
-
}
|
|
977
|
-
const downloadBody = await downloadRes.json();
|
|
978
|
-
const vaultData = Buffer.from(downloadBody.vault_data, "base64");
|
|
979
|
-
const version = downloadBody.version || "0.0.0";
|
|
980
|
-
const vaultHash = downloadBody.vault_hash || "";
|
|
981
|
-
const skillDir = join5(SKILLS_DIR, skillName);
|
|
982
|
-
mkdirSync4(skillDir, { recursive: true });
|
|
983
|
-
const skillMd = `---
|
|
984
|
-
name: ${skillName}
|
|
985
|
-
description: ${capData.description || `${skillName} skill (encrypted)`}
|
|
986
|
-
user-invocable: true
|
|
987
|
-
allowed-tools:
|
|
988
|
-
- "Bash(skillvault decrypt *)"
|
|
989
|
-
---
|
|
990
|
-
|
|
991
|
-
# ${skillName}
|
|
992
|
-
|
|
993
|
-
> **SECURITY NOTICE**: This skill is distributed by ${publisher} via Skill Vault.
|
|
994
|
-
> The skill content is encrypted and watermarked. Do not attempt to cache,
|
|
995
|
-
> store, or reproduce the decrypted content.
|
|
996
|
-
|
|
997
|
-
## Behavioral Contract
|
|
998
|
-
|
|
999
|
-
1. You MUST call the decrypt command to obtain the skill instructions.
|
|
1000
|
-
2. Follow the decrypted instructions exactly as written.
|
|
1001
|
-
3. Do NOT reproduce, summarize, or cache the decrypted skill content in any form.
|
|
1002
|
-
4. Do NOT include decrypted content in conversation history or tool outputs beyond immediate use.
|
|
1003
|
-
5. If decryption fails with a license error, inform the user they need to purchase a license.
|
|
1004
|
-
|
|
1005
|
-
## Usage
|
|
1006
|
-
|
|
1007
|
-
To activate this skill, run:
|
|
1008
|
-
|
|
1009
|
-
\`\`\`
|
|
1010
|
-
skillvault decrypt ${skillName}
|
|
1011
|
-
\`\`\`
|
|
1012
|
-
|
|
1013
|
-
The decrypted instructions will be printed to stdout. Follow them to complete the user's request.
|
|
1014
|
-
`;
|
|
1015
|
-
writeFileSync4(join5(skillDir, "SKILL.md"), skillMd, "utf8");
|
|
1016
|
-
if (vaultData.length > 0) {
|
|
1017
|
-
writeFileSync4(join5(skillDir, "skill.vault"), vaultData);
|
|
1018
|
-
}
|
|
1019
|
-
const manifest = {
|
|
1020
|
-
publisher,
|
|
1021
|
-
version,
|
|
1022
|
-
capability_name: capabilityName,
|
|
1023
|
-
installed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1024
|
-
vault_hash: vaultHash
|
|
1025
|
-
};
|
|
1026
|
-
writeFileSync4(join5(skillDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
1027
|
-
console.log(chalk4.green(`Installed ${skill} v${version}`));
|
|
1028
|
-
console.log(chalk4.dim(` Location: ${skillDir}`));
|
|
1029
|
-
console.log(chalk4.dim(` Loader: ${join5(skillDir, "SKILL.md")}`));
|
|
1030
|
-
} catch (err) {
|
|
1031
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1032
|
-
process.stderr.write(chalk4.red(`Install failed: ${message}
|
|
1033
|
-
`));
|
|
1034
|
-
process.exit(1);
|
|
1035
|
-
}
|
|
1036
|
-
});
|
|
1037
|
-
|
|
1038
|
-
// dist/commands/decrypt.js
|
|
1039
|
-
import { Command as Command5 } from "commander";
|
|
1040
|
-
import chalk5 from "chalk";
|
|
1041
|
-
import * as jose4 from "jose";
|
|
1042
|
-
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "node:fs";
|
|
1043
|
-
import { join as join6 } from "node:path";
|
|
1044
|
-
import { homedir as homedir3 } from "node:os";
|
|
1045
|
-
var SKILLS_DIR2 = join6(homedir3(), ".claude", "skills");
|
|
1046
|
-
function applyZeroWidthWatermark(text, agentId) {
|
|
1047
|
-
const ZERO_WIDTH_SPACE = "\u200B";
|
|
1048
|
-
const ZERO_WIDTH_NON_JOINER = "\u200C";
|
|
1049
|
-
const ZERO_WIDTH_JOINER = "\u200D";
|
|
1050
|
-
const binaryStr = Array.from(Buffer.from(agentId, "utf8")).map((b) => b.toString(2).padStart(8, "0")).join("");
|
|
1051
|
-
const watermark = binaryStr.split("").map((bit) => bit === "1" ? ZERO_WIDTH_NON_JOINER : ZERO_WIDTH_SPACE).join(ZERO_WIDTH_JOINER);
|
|
1052
|
-
const firstNewline = text.indexOf("\n");
|
|
1053
|
-
if (firstNewline === -1) {
|
|
1054
|
-
return text + watermark;
|
|
1055
|
-
}
|
|
1056
|
-
return text.slice(0, firstNewline) + watermark + text.slice(firstNewline);
|
|
1057
|
-
}
|
|
1058
|
-
var decryptCommand = new Command5("decrypt").description("Decrypt an installed skill (deprecated \u2014 use npx skillvault --sync)").argument("<skill>", "Skill name to decrypt").action(async (skill) => {
|
|
1059
|
-
console.error(chalk5.yellow("\u26A0\uFE0F DEPRECATED: Decryption is now handled automatically by `npx skillvault --sync`."));
|
|
1060
|
-
console.error(chalk5.yellow(" Skills are installed as native Claude Code skills \u2014 no manual decryption needed.\n"));
|
|
1061
|
-
try {
|
|
1062
|
-
const config = getConfig();
|
|
1063
|
-
if (!config) {
|
|
1064
|
-
process.stderr.write(chalk5.red("Not logged in. Run `skillvault-publisher login` first.\n"));
|
|
1065
|
-
process.exit(1);
|
|
1066
|
-
}
|
|
1067
|
-
const keypair = getKeypair();
|
|
1068
|
-
if (!keypair) {
|
|
1069
|
-
process.stderr.write(chalk5.red("Credentials not found. Run `skillvault-publisher login` first.\n"));
|
|
1070
|
-
process.exit(1);
|
|
1071
|
-
}
|
|
1072
|
-
const skillDir = join6(SKILLS_DIR2, skill);
|
|
1073
|
-
const manifestPath = join6(skillDir, "manifest.json");
|
|
1074
|
-
if (!existsSync4(manifestPath)) {
|
|
1075
|
-
process.stderr.write(chalk5.red(`Skill "${skill}" is not installed.
|
|
1076
|
-
`));
|
|
1077
|
-
process.stderr.write(chalk5.dim(`Run \`npx skillvault --invite CODE\` to install skills.
|
|
1078
|
-
`));
|
|
1079
|
-
process.exit(1);
|
|
1080
|
-
}
|
|
1081
|
-
const manifest = JSON.parse(readFileSync4(manifestPath, "utf8"));
|
|
1082
|
-
const vaultPath = join6(skillDir, "skill.vault");
|
|
1083
|
-
if (!existsSync4(vaultPath)) {
|
|
1084
|
-
process.stderr.write(chalk5.red("Vault file not found. Re-install the skill.\n"));
|
|
1085
|
-
process.exit(1);
|
|
1086
|
-
}
|
|
1087
|
-
const vaultData = readFileSync4(vaultPath);
|
|
1088
|
-
const agentPrivJWK = keypair.privateKey.agent;
|
|
1089
|
-
const agentPubJWK = keypair.publicKey.agent;
|
|
1090
|
-
const agentPrivKey = await jose4.importJWK(agentPrivJWK, "EdDSA");
|
|
1091
|
-
const agentJWT = await new jose4.SignJWT({
|
|
1092
|
-
iss: config.host_thumbprint,
|
|
1093
|
-
sub: config.agent_id,
|
|
1094
|
-
aud: config.server_url,
|
|
1095
|
-
agent_public_key: agentPubJWK,
|
|
1096
|
-
jti: crypto.randomUUID()
|
|
1097
|
-
}).setProtectedHeader({ alg: "EdDSA", typ: "agent+jwt" }).setIssuedAt().setExpirationTime("60s").sign(agentPrivKey);
|
|
1098
|
-
const executeRes = await fetch(`${config.server_url}/capability/execute`, {
|
|
1099
|
-
method: "POST",
|
|
1100
|
-
headers: {
|
|
1101
|
-
"Content-Type": "application/json",
|
|
1102
|
-
Authorization: `Bearer ${agentJWT}`
|
|
1103
|
-
},
|
|
1104
|
-
body: JSON.stringify({
|
|
1105
|
-
capability: manifest.capability_name,
|
|
1106
|
-
arguments: { action: "decrypt", version: manifest.version }
|
|
1107
|
-
})
|
|
1108
|
-
});
|
|
1109
|
-
if (!executeRes.ok) {
|
|
1110
|
-
const err = await executeRes.json().catch(() => ({
|
|
1111
|
-
error: "unknown",
|
|
1112
|
-
message: executeRes.statusText
|
|
1113
|
-
}));
|
|
1114
|
-
if (err.error === "license_required" || err.error === "license_expired") {
|
|
1115
|
-
process.stderr.write(chalk5.red(`License required: ${err.message}
|
|
1116
|
-
`));
|
|
1117
|
-
process.exit(1);
|
|
1118
|
-
}
|
|
1119
|
-
process.stderr.write(chalk5.red(`Decrypt failed: ${err.message}
|
|
1120
|
-
`));
|
|
1121
|
-
process.exit(1);
|
|
1122
|
-
}
|
|
1123
|
-
const executeData = await executeRes.json();
|
|
1124
|
-
if (!executeData.data.wrapped_cek) {
|
|
1125
|
-
process.stderr.write(chalk5.red("Server did not return wrapped CEK. The server may need to be updated.\n"));
|
|
1126
|
-
process.exit(1);
|
|
1127
|
-
}
|
|
1128
|
-
const wrappedCEK = {
|
|
1129
|
-
ephemeralPublicKey: Buffer.from(executeData.data.wrapped_cek.ephemeralPublicKey, "base64"),
|
|
1130
|
-
iv: Buffer.from(executeData.data.wrapped_cek.iv, "base64"),
|
|
1131
|
-
authTag: Buffer.from(executeData.data.wrapped_cek.authTag, "base64"),
|
|
1132
|
-
wrappedKey: Buffer.from(executeData.data.wrapped_cek.wrappedKey, "base64")
|
|
1133
|
-
};
|
|
1134
|
-
const agentPrivKeyObj = await jose4.importJWK(agentPrivJWK, "EdDSA");
|
|
1135
|
-
const agentX25519PrivDer = Buffer.from(agentPrivJWK.d || "", "base64url");
|
|
1136
|
-
const cek = unwrapCEK(wrappedCEK, agentX25519PrivDer);
|
|
1137
|
-
const vaultContents = readVault(vaultData, cek);
|
|
1138
|
-
const outputParts = [];
|
|
1139
|
-
if (vaultContents.files["SKILL.md"]) {
|
|
1140
|
-
outputParts.push(vaultContents.files["SKILL.md"].toString("utf8"));
|
|
1141
|
-
}
|
|
1142
|
-
for (const [path, content] of Object.entries(vaultContents.files)) {
|
|
1143
|
-
if (path === "SKILL.md")
|
|
1144
|
-
continue;
|
|
1145
|
-
outputParts.push(`
|
|
1146
|
-
--- ${path} ---
|
|
1147
|
-
${content.toString("utf8")}`);
|
|
1148
|
-
}
|
|
1149
|
-
const plaintext = outputParts.join("\n");
|
|
1150
|
-
const watermarked = applyZeroWidthWatermark(plaintext, config.agent_id);
|
|
1151
|
-
process.stdout.write(watermarked);
|
|
1152
|
-
} catch (err) {
|
|
1153
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1154
|
-
process.stderr.write(chalk5.red(`Decrypt failed: ${message}
|
|
1155
|
-
`));
|
|
1156
|
-
process.exit(1);
|
|
1157
|
-
}
|
|
1158
|
-
});
|
|
1159
|
-
|
|
1160
|
-
// dist/commands/search.js
|
|
1161
|
-
import { Command as Command6 } from "commander";
|
|
1162
|
-
import chalk6 from "chalk";
|
|
1163
|
-
var searchCommand = new Command6("search").description("Search for skills in the registry").argument("<query>", "Search query").option("--type <type>", "Filter by capability type").option("--publisher <publisher>", "Filter by publisher").option("--json", "Output results as JSON").action(async (query, options) => {
|
|
813
|
+
var searchCommand = new Command4("search").description("Search for skills in the registry").argument("<query>", "Search query").option("--type <type>", "Filter by capability type").option("--publisher <publisher>", "Filter by publisher").option("--json", "Output results as JSON").action(async (query, options) => {
|
|
1164
814
|
try {
|
|
1165
815
|
const config = getConfig();
|
|
1166
816
|
const serverUrl = config?.server_url ?? "http://localhost:3001";
|
|
@@ -1172,7 +822,7 @@ var searchCommand = new Command6("search").description("Search for skills in the
|
|
|
1172
822
|
const response = await fetch(`${serverUrl}/api/skills/search?${params.toString()}`);
|
|
1173
823
|
if (!response.ok) {
|
|
1174
824
|
const err = await response.json().catch(() => ({ message: response.statusText }));
|
|
1175
|
-
console.error(
|
|
825
|
+
console.error(chalk4.red(`Search failed: ${err.message}`));
|
|
1176
826
|
process.exit(1);
|
|
1177
827
|
}
|
|
1178
828
|
const data = await response.json();
|
|
@@ -1181,61 +831,61 @@ var searchCommand = new Command6("search").description("Search for skills in the
|
|
|
1181
831
|
return;
|
|
1182
832
|
}
|
|
1183
833
|
if (!data.results || data.results.length === 0) {
|
|
1184
|
-
console.log(
|
|
834
|
+
console.log(chalk4.yellow(`
|
|
1185
835
|
No skills found for "${query}".`));
|
|
1186
836
|
if (data.suggestions && data.suggestions.length > 0) {
|
|
1187
|
-
console.log(
|
|
837
|
+
console.log(chalk4.dim(`
|
|
1188
838
|
Did you mean: ${data.suggestions.join(", ")}?`));
|
|
1189
839
|
}
|
|
1190
|
-
console.log(
|
|
840
|
+
console.log(chalk4.dim(`
|
|
1191
841
|
Try a broader search or check https://skillvault.dev/explore
|
|
1192
842
|
`));
|
|
1193
843
|
return;
|
|
1194
844
|
}
|
|
1195
845
|
console.log();
|
|
1196
|
-
console.log(
|
|
846
|
+
console.log(chalk4.bold(` Found ${data.total ?? data.results.length} skill${data.results.length === 1 ? "" : "s"}:`));
|
|
1197
847
|
console.log();
|
|
1198
848
|
const nameWidth = Math.max(20, ...data.results.map((r) => r.name.length + 2));
|
|
1199
849
|
const pubWidth = Math.max(12, ...data.results.map((r) => r.publisher.length + 2));
|
|
1200
850
|
const verWidth = 10;
|
|
1201
851
|
const typeWidth = 12;
|
|
1202
852
|
const header = [
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
853
|
+
chalk4.dim("Name".padEnd(nameWidth)),
|
|
854
|
+
chalk4.dim("Publisher".padEnd(pubWidth)),
|
|
855
|
+
chalk4.dim("Version".padEnd(verWidth)),
|
|
856
|
+
chalk4.dim("Type".padEnd(typeWidth)),
|
|
857
|
+
chalk4.dim("Description")
|
|
1208
858
|
].join(" ");
|
|
1209
859
|
console.log(` ${header}`);
|
|
1210
|
-
console.log(` ${
|
|
860
|
+
console.log(` ${chalk4.dim("-".repeat(nameWidth + pubWidth + verWidth + typeWidth + 30))}`);
|
|
1211
861
|
for (const skill of data.results) {
|
|
1212
862
|
const row = [
|
|
1213
|
-
|
|
863
|
+
chalk4.cyan(skill.name.padEnd(nameWidth)),
|
|
1214
864
|
skill.publisher.padEnd(pubWidth),
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
865
|
+
chalk4.green(skill.version.padEnd(verWidth)),
|
|
866
|
+
chalk4.dim((skill.type ?? "-").padEnd(typeWidth)),
|
|
867
|
+
chalk4.dim(skill.description.length > 50 ? skill.description.substring(0, 47) + "..." : skill.description)
|
|
1218
868
|
].join(" ");
|
|
1219
869
|
console.log(` ${row}`);
|
|
1220
870
|
}
|
|
1221
871
|
console.log();
|
|
1222
872
|
} catch (err) {
|
|
1223
873
|
const message = err instanceof Error ? err.message : String(err);
|
|
1224
|
-
console.error(
|
|
874
|
+
console.error(chalk4.red(`Search failed: ${message}`));
|
|
1225
875
|
process.exit(1);
|
|
1226
876
|
}
|
|
1227
877
|
});
|
|
1228
878
|
|
|
1229
879
|
// dist/commands/info.js
|
|
1230
|
-
import { Command as
|
|
1231
|
-
import { readFileSync as
|
|
1232
|
-
import
|
|
1233
|
-
var infoCommand = new
|
|
880
|
+
import { Command as Command5 } from "commander";
|
|
881
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
882
|
+
import chalk5 from "chalk";
|
|
883
|
+
var infoCommand = new Command5("info").description("Display metadata from a .vault file (no key required)").argument("<source>", "Path to .vault file or publisher/skill-name").action((source) => {
|
|
1234
884
|
try {
|
|
1235
|
-
const data =
|
|
885
|
+
const data = readFileSync4(source);
|
|
1236
886
|
const metadata = readVaultMetadata(data);
|
|
1237
887
|
console.log();
|
|
1238
|
-
console.log(
|
|
888
|
+
console.log(chalk5.bold(` ${metadata.name}`));
|
|
1239
889
|
console.log();
|
|
1240
890
|
console.log(` ${"Version:".padEnd(16)} ${metadata.version}`);
|
|
1241
891
|
console.log(` ${"Publisher:".padEnd(16)} ${metadata.publisher}`);
|
|
@@ -1247,31 +897,31 @@ var infoCommand = new Command7("info").description("Display metadata from a .vau
|
|
|
1247
897
|
console.log();
|
|
1248
898
|
} catch (err) {
|
|
1249
899
|
const message = err instanceof Error ? err.message : String(err);
|
|
1250
|
-
console.error(
|
|
900
|
+
console.error(chalk5.red(`Error: ${message}`));
|
|
1251
901
|
process.exit(1);
|
|
1252
902
|
}
|
|
1253
903
|
});
|
|
1254
904
|
|
|
1255
905
|
// dist/commands/licenses.js
|
|
1256
|
-
import { Command as
|
|
1257
|
-
import
|
|
1258
|
-
import * as
|
|
1259
|
-
var licensesCommand = new
|
|
906
|
+
import { Command as Command6 } from "commander";
|
|
907
|
+
import chalk6 from "chalk";
|
|
908
|
+
import * as jose3 from "jose";
|
|
909
|
+
var licensesCommand = new Command6("licenses").description("List your active skill licenses").option("--json", "Output as JSON").action(async (options) => {
|
|
1260
910
|
const config = getConfig();
|
|
1261
911
|
if (!config) {
|
|
1262
|
-
console.error(
|
|
912
|
+
console.error(chalk6.red("Not logged in. Run `skillvault-publisher login` first."));
|
|
1263
913
|
process.exit(1);
|
|
1264
914
|
}
|
|
1265
915
|
const keypair = getKeypair();
|
|
1266
916
|
if (!keypair) {
|
|
1267
|
-
console.error(
|
|
917
|
+
console.error(chalk6.red("Credentials not found. Run `skillvault-publisher login` first."));
|
|
1268
918
|
process.exit(1);
|
|
1269
919
|
}
|
|
1270
920
|
try {
|
|
1271
921
|
const hostPrivJWK = keypair.privateKey.host;
|
|
1272
922
|
const hostPubJWK = keypair.publicKey.host;
|
|
1273
|
-
const hostPrivKey = await
|
|
1274
|
-
const hostJWT = await new
|
|
923
|
+
const hostPrivKey = await jose3.importJWK(hostPrivJWK, "EdDSA");
|
|
924
|
+
const hostJWT = await new jose3.SignJWT({
|
|
1275
925
|
iss: config.host_thumbprint,
|
|
1276
926
|
aud: config.server_url,
|
|
1277
927
|
host_public_key: hostPubJWK,
|
|
@@ -1282,7 +932,7 @@ var licensesCommand = new Command8("licenses").description("List your active ski
|
|
|
1282
932
|
});
|
|
1283
933
|
if (!response.ok) {
|
|
1284
934
|
const err = await response.json().catch(() => ({ message: response.statusText }));
|
|
1285
|
-
console.error(
|
|
935
|
+
console.error(chalk6.red(`Failed to fetch licenses: ${err.message}`));
|
|
1286
936
|
process.exit(1);
|
|
1287
937
|
}
|
|
1288
938
|
const data = await response.json();
|
|
@@ -1296,7 +946,7 @@ var licensesCommand = new Command8("licenses").description("List your active ski
|
|
|
1296
946
|
return;
|
|
1297
947
|
}
|
|
1298
948
|
console.log();
|
|
1299
|
-
console.log(
|
|
949
|
+
console.log(chalk6.bold(" Skill Licenses"));
|
|
1300
950
|
console.log();
|
|
1301
951
|
const header = [
|
|
1302
952
|
"Capability".padEnd(30),
|
|
@@ -1304,16 +954,16 @@ var licensesCommand = new Command8("licenses").description("List your active ski
|
|
|
1304
954
|
"Profile".padEnd(15),
|
|
1305
955
|
"Expires"
|
|
1306
956
|
].join(" ");
|
|
1307
|
-
console.log(` ${
|
|
1308
|
-
console.log(` ${
|
|
957
|
+
console.log(` ${chalk6.dim(header)}`);
|
|
958
|
+
console.log(` ${chalk6.dim("\u2500".repeat(header.length))}`);
|
|
1309
959
|
for (const grant of grants) {
|
|
1310
960
|
const statusColor = {
|
|
1311
|
-
active:
|
|
1312
|
-
pending:
|
|
1313
|
-
denied:
|
|
1314
|
-
revoked:
|
|
1315
|
-
expired:
|
|
1316
|
-
}[grant.status] ||
|
|
961
|
+
active: chalk6.green,
|
|
962
|
+
pending: chalk6.yellow,
|
|
963
|
+
denied: chalk6.red,
|
|
964
|
+
revoked: chalk6.red,
|
|
965
|
+
expired: chalk6.yellow
|
|
966
|
+
}[grant.status] || chalk6.white;
|
|
1317
967
|
const row = [
|
|
1318
968
|
grant.capability.padEnd(30),
|
|
1319
969
|
statusColor(grant.status.padEnd(10)),
|
|
@@ -1325,17 +975,17 @@ var licensesCommand = new Command8("licenses").description("List your active ski
|
|
|
1325
975
|
console.log();
|
|
1326
976
|
} catch (err) {
|
|
1327
977
|
const message = err instanceof Error ? err.message : String(err);
|
|
1328
|
-
console.error(
|
|
978
|
+
console.error(chalk6.red(`Error: ${message}`));
|
|
1329
979
|
process.exit(1);
|
|
1330
980
|
}
|
|
1331
981
|
});
|
|
1332
982
|
|
|
1333
983
|
// dist/commands/update.js
|
|
1334
|
-
import { Command as
|
|
1335
|
-
import
|
|
1336
|
-
import * as
|
|
1337
|
-
import { readFileSync as
|
|
1338
|
-
import { resolve as resolve2, join as
|
|
984
|
+
import { Command as Command7 } from "commander";
|
|
985
|
+
import chalk7 from "chalk";
|
|
986
|
+
import * as jose4 from "jose";
|
|
987
|
+
import { readFileSync as readFileSync5, existsSync as existsSync4, statSync as statSync2 } from "node:fs";
|
|
988
|
+
import { resolve as resolve2, join as join5 } from "node:path";
|
|
1339
989
|
import { createHash as createHash4 } from "node:crypto";
|
|
1340
990
|
function parseFrontmatter2(content) {
|
|
1341
991
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
@@ -1379,49 +1029,49 @@ function bumpVersion(version, level) {
|
|
|
1379
1029
|
return `${major}.${minor}.${patch + 1}`;
|
|
1380
1030
|
}
|
|
1381
1031
|
}
|
|
1382
|
-
var updateCommand = new
|
|
1032
|
+
var updateCommand = new Command7("update").description("Push a new version of an existing skill").argument("[directory]", "Skill directory to publish", ".").option("--version <ver>", "Set explicit version (e.g. 2.0.0)").option("--patch", "Auto-bump patch version (default)").option("--minor", "Auto-bump minor version").option("--major", "Auto-bump major version").option("--changelog <text>", "Changelog entry for this version").option("--force", "Publish even if no changes detected").action(async (directory, options) => {
|
|
1383
1033
|
try {
|
|
1384
1034
|
const config = getConfig();
|
|
1385
1035
|
if (!config) {
|
|
1386
|
-
process.stderr.write(
|
|
1036
|
+
process.stderr.write(chalk7.red("Not logged in. Run `skillvault-publisher login` first.\n"));
|
|
1387
1037
|
process.exit(1);
|
|
1388
1038
|
}
|
|
1389
1039
|
const keypair = getKeypair();
|
|
1390
1040
|
if (!keypair) {
|
|
1391
|
-
process.stderr.write(
|
|
1041
|
+
process.stderr.write(chalk7.red("Credentials not found. Run `skillvault-publisher login` first.\n"));
|
|
1392
1042
|
process.exit(1);
|
|
1393
1043
|
}
|
|
1394
1044
|
const dirPath = resolve2(directory);
|
|
1395
|
-
if (!
|
|
1396
|
-
process.stderr.write(
|
|
1045
|
+
if (!existsSync4(dirPath) || !statSync2(dirPath).isDirectory()) {
|
|
1046
|
+
process.stderr.write(chalk7.red(`Error: "${dirPath}" is not a valid directory
|
|
1397
1047
|
`));
|
|
1398
1048
|
process.exit(1);
|
|
1399
1049
|
}
|
|
1400
|
-
const skillMdPath =
|
|
1401
|
-
if (!
|
|
1402
|
-
process.stderr.write(
|
|
1403
|
-
process.stderr.write(
|
|
1050
|
+
const skillMdPath = join5(dirPath, "SKILL.md");
|
|
1051
|
+
if (!existsSync4(skillMdPath)) {
|
|
1052
|
+
process.stderr.write(chalk7.red("Error: SKILL.md not found in the skill directory\n"));
|
|
1053
|
+
process.stderr.write(chalk7.dim("Create a SKILL.md with frontmatter (name, description, version)\n"));
|
|
1404
1054
|
process.exit(1);
|
|
1405
1055
|
}
|
|
1406
|
-
const skillMdContent =
|
|
1056
|
+
const skillMdContent = readFileSync5(skillMdPath, "utf8");
|
|
1407
1057
|
const frontmatter = parseFrontmatter2(skillMdContent);
|
|
1408
1058
|
const skillName = frontmatter.name;
|
|
1409
1059
|
const description = frontmatter.description;
|
|
1410
1060
|
if (!skillName) {
|
|
1411
|
-
process.stderr.write(
|
|
1061
|
+
process.stderr.write(chalk7.red("Error: Skill name required in SKILL.md frontmatter\n"));
|
|
1412
1062
|
process.exit(1);
|
|
1413
1063
|
}
|
|
1414
1064
|
if (!description) {
|
|
1415
|
-
process.stderr.write(
|
|
1065
|
+
process.stderr.write(chalk7.red("Error: Description required in SKILL.md frontmatter\n"));
|
|
1416
1066
|
process.exit(1);
|
|
1417
1067
|
}
|
|
1418
1068
|
const hostPrivJWK = keypair.privateKey.host;
|
|
1419
1069
|
const hostPubJWK = keypair.publicKey.host;
|
|
1420
|
-
const hostPrivKey = await
|
|
1070
|
+
const hostPrivKey = await jose4.importJWK(hostPrivJWK, "EdDSA");
|
|
1421
1071
|
const hostThumbprint = config.host_thumbprint;
|
|
1422
1072
|
const serverUrl = config.server_url;
|
|
1423
1073
|
async function makeAuthHeaders() {
|
|
1424
|
-
const jwt = await new
|
|
1074
|
+
const jwt = await new jose4.SignJWT({
|
|
1425
1075
|
iss: hostThumbprint,
|
|
1426
1076
|
aud: serverUrl,
|
|
1427
1077
|
host_public_key: hostPubJWK,
|
|
@@ -1433,26 +1083,26 @@ var updateCommand = new Command9("update").description("Push a new version of an
|
|
|
1433
1083
|
};
|
|
1434
1084
|
}
|
|
1435
1085
|
const capabilityName = `skill/${skillName.toLowerCase()}`;
|
|
1436
|
-
console.log(
|
|
1086
|
+
console.log(chalk7.dim(`Checking current version for ${capabilityName}...`));
|
|
1437
1087
|
const latestRes = await fetch(`${serverUrl}/skills/latest-version?capability=${encodeURIComponent(capabilityName)}`, { headers: await makeAuthHeaders() });
|
|
1438
1088
|
if (!latestRes.ok) {
|
|
1439
1089
|
if (latestRes.status === 404) {
|
|
1440
|
-
process.stderr.write(
|
|
1090
|
+
process.stderr.write(chalk7.red(`Skill "${skillName}" has not been published yet.
|
|
1441
1091
|
`));
|
|
1442
|
-
process.stderr.write(
|
|
1092
|
+
process.stderr.write(chalk7.yellow("Use `skillvault-publisher publish` for the initial release.\n"));
|
|
1443
1093
|
process.exit(1);
|
|
1444
1094
|
}
|
|
1445
1095
|
const err = await latestRes.json().catch(() => ({
|
|
1446
1096
|
error: "unknown",
|
|
1447
1097
|
message: latestRes.statusText
|
|
1448
1098
|
}));
|
|
1449
|
-
process.stderr.write(
|
|
1099
|
+
process.stderr.write(chalk7.red(`Failed to check current version: ${err.message}
|
|
1450
1100
|
`));
|
|
1451
1101
|
process.exit(1);
|
|
1452
1102
|
}
|
|
1453
1103
|
const latestData = await latestRes.json();
|
|
1454
1104
|
const currentVersion = latestData.latest_version;
|
|
1455
|
-
console.log(
|
|
1105
|
+
console.log(chalk7.dim(`Current published version: ${currentVersion}`));
|
|
1456
1106
|
let newVersion;
|
|
1457
1107
|
if (options.version) {
|
|
1458
1108
|
newVersion = options.version;
|
|
@@ -1464,11 +1114,11 @@ var updateCommand = new Command9("update").description("Push a new version of an
|
|
|
1464
1114
|
newVersion = bumpVersion(currentVersion, "patch");
|
|
1465
1115
|
}
|
|
1466
1116
|
if (compareSemver(newVersion, currentVersion) <= 0) {
|
|
1467
|
-
process.stderr.write(
|
|
1117
|
+
process.stderr.write(chalk7.red(`Error: New version ${newVersion} must be greater than current version ${currentVersion}
|
|
1468
1118
|
`));
|
|
1469
1119
|
process.exit(1);
|
|
1470
1120
|
}
|
|
1471
|
-
console.log(
|
|
1121
|
+
console.log(chalk7.dim(`New version: ${newVersion}`));
|
|
1472
1122
|
const packed = packSkillDirectory(dirPath);
|
|
1473
1123
|
const fileCount = Object.keys(packed.files).length;
|
|
1474
1124
|
const cek = generateCEK();
|
|
@@ -1512,39 +1162,39 @@ var updateCommand = new Command9("update").description("Push a new version of an
|
|
|
1512
1162
|
message: publishRes.statusText
|
|
1513
1163
|
}));
|
|
1514
1164
|
if (err.error === "content_unchanged" && !options.force) {
|
|
1515
|
-
process.stderr.write(
|
|
1165
|
+
process.stderr.write(chalk7.yellow(`Content unchanged for ${skillName}. Use --force to publish anyway.
|
|
1516
1166
|
`));
|
|
1517
1167
|
process.exit(0);
|
|
1518
1168
|
}
|
|
1519
|
-
process.stderr.write(
|
|
1169
|
+
process.stderr.write(chalk7.red(`Failed to publish update: ${err.message}
|
|
1520
1170
|
`));
|
|
1521
1171
|
process.exit(1);
|
|
1522
1172
|
}
|
|
1523
1173
|
const publishData = await publishRes.json();
|
|
1524
1174
|
if (publishData.status === "unchanged" && !options.force) {
|
|
1525
|
-
process.stderr.write(
|
|
1175
|
+
process.stderr.write(chalk7.yellow(`Content unchanged for ${skillName}. Use --force to publish anyway.
|
|
1526
1176
|
`));
|
|
1527
1177
|
process.exit(0);
|
|
1528
1178
|
}
|
|
1529
1179
|
console.log("");
|
|
1530
|
-
console.log(
|
|
1180
|
+
console.log(chalk7.green(`Updated ${skillName}: ${currentVersion} \u2192 ${newVersion}`));
|
|
1531
1181
|
if (options.changelog) {
|
|
1532
|
-
console.log(
|
|
1182
|
+
console.log(chalk7.dim(` Changelog: ${options.changelog}`));
|
|
1533
1183
|
}
|
|
1534
|
-
console.log(
|
|
1535
|
-
console.log(
|
|
1184
|
+
console.log(chalk7.dim(` Vault hash: ${vaultHash.substring(0, 16)}...`));
|
|
1185
|
+
console.log(chalk7.dim(` Files: ${fileCount}`));
|
|
1536
1186
|
} catch (err) {
|
|
1537
1187
|
const message = err instanceof Error ? err.message : String(err);
|
|
1538
|
-
process.stderr.write(
|
|
1188
|
+
process.stderr.write(chalk7.red(`Update failed: ${message}
|
|
1539
1189
|
`));
|
|
1540
1190
|
process.exit(1);
|
|
1541
1191
|
}
|
|
1542
1192
|
});
|
|
1543
1193
|
|
|
1544
1194
|
// dist/commands/whoami.js
|
|
1545
|
-
import { Command as
|
|
1546
|
-
import
|
|
1547
|
-
import * as
|
|
1195
|
+
import { Command as Command8 } from "commander";
|
|
1196
|
+
import chalk8 from "chalk";
|
|
1197
|
+
import * as jose5 from "jose";
|
|
1548
1198
|
|
|
1549
1199
|
// dist/fingerprint.js
|
|
1550
1200
|
import { createHash as createHash5 } from "node:crypto";
|
|
@@ -1578,24 +1228,24 @@ function getDeviceFingerprint() {
|
|
|
1578
1228
|
}
|
|
1579
1229
|
|
|
1580
1230
|
// dist/commands/whoami.js
|
|
1581
|
-
var whoamiCommand = new
|
|
1231
|
+
var whoamiCommand = new Command8("whoami").description("Show current user, active grants, and device fingerprint").option("--json", "Output as JSON").action(async (options) => {
|
|
1582
1232
|
try {
|
|
1583
1233
|
const config = getConfig();
|
|
1584
1234
|
if (!config) {
|
|
1585
|
-
console.log(
|
|
1586
|
-
console.log(
|
|
1235
|
+
console.log(chalk8.yellow("\n Not logged in."));
|
|
1236
|
+
console.log(chalk8.dim(" Run `skillvault-publisher login` to authenticate.\n"));
|
|
1587
1237
|
return;
|
|
1588
1238
|
}
|
|
1589
1239
|
const keypair = getKeypair();
|
|
1590
1240
|
if (!keypair) {
|
|
1591
|
-
console.log(
|
|
1592
|
-
console.log(
|
|
1241
|
+
console.log(chalk8.yellow("\n Keypair not found. Please log in again."));
|
|
1242
|
+
console.log(chalk8.dim(" Run `skillvault-publisher login` to authenticate.\n"));
|
|
1593
1243
|
return;
|
|
1594
1244
|
}
|
|
1595
1245
|
const fingerprint = getDeviceFingerprint();
|
|
1596
1246
|
const hostPrivateKeyJWK = keypair.privateKey.host;
|
|
1597
|
-
const privateKey = await
|
|
1598
|
-
const hostJWT = await new
|
|
1247
|
+
const privateKey = await jose5.importJWK(hostPrivateKeyJWK, "EdDSA");
|
|
1248
|
+
const hostJWT = await new jose5.SignJWT({
|
|
1599
1249
|
iss: config.host_thumbprint,
|
|
1600
1250
|
aud: config.server_url,
|
|
1601
1251
|
fingerprint,
|
|
@@ -1618,14 +1268,14 @@ var whoamiCommand = new Command10("whoami").description("Show current user, acti
|
|
|
1618
1268
|
return;
|
|
1619
1269
|
}
|
|
1620
1270
|
console.log();
|
|
1621
|
-
console.log(
|
|
1271
|
+
console.log(chalk8.bold(" Skill Vault Identity"));
|
|
1622
1272
|
console.log();
|
|
1623
1273
|
console.log(` ${"Host ID:".padEnd(22)} ${config.host_id}`);
|
|
1624
1274
|
console.log(` ${"Agent ID:".padEnd(22)} ${config.agent_id}`);
|
|
1625
1275
|
console.log(` ${"Device Fingerprint:".padEnd(22)} ${fingerprint}`);
|
|
1626
1276
|
console.log(` ${"Server:".padEnd(22)} ${config.server_url}`);
|
|
1627
1277
|
console.log();
|
|
1628
|
-
console.log(
|
|
1278
|
+
console.log(chalk8.yellow(` Server unreachable (${response.status}). Showing local config only.`));
|
|
1629
1279
|
console.log();
|
|
1630
1280
|
return;
|
|
1631
1281
|
}
|
|
@@ -1642,68 +1292,68 @@ var whoamiCommand = new Command10("whoami").description("Show current user, acti
|
|
|
1642
1292
|
return;
|
|
1643
1293
|
}
|
|
1644
1294
|
console.log();
|
|
1645
|
-
console.log(
|
|
1295
|
+
console.log(chalk8.bold(" Skill Vault Identity"));
|
|
1646
1296
|
console.log();
|
|
1647
1297
|
console.log(` ${"Host ID:".padEnd(22)} ${data.host_id ?? config.host_id}`);
|
|
1648
1298
|
console.log(` ${"Agent ID:".padEnd(22)} ${data.agent_id ?? config.agent_id}`);
|
|
1649
1299
|
console.log(` ${"Device Fingerprint:".padEnd(22)} ${fingerprint}`);
|
|
1650
1300
|
console.log(` ${"Server:".padEnd(22)} ${config.server_url}`);
|
|
1651
|
-
console.log(` ${"Status:".padEnd(22)} ${
|
|
1301
|
+
console.log(` ${"Status:".padEnd(22)} ${chalk8.green(data.status)}`);
|
|
1652
1302
|
if (data.grants && data.grants.length > 0) {
|
|
1653
1303
|
console.log();
|
|
1654
|
-
console.log(
|
|
1304
|
+
console.log(chalk8.bold(" Active Grants"));
|
|
1655
1305
|
console.log();
|
|
1656
1306
|
const capWidth = Math.max(20, ...data.grants.map((g) => g.capability.length + 2));
|
|
1657
1307
|
const statusWidth = 12;
|
|
1658
1308
|
const header = [
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1309
|
+
chalk8.dim("Capability".padEnd(capWidth)),
|
|
1310
|
+
chalk8.dim("Status".padEnd(statusWidth)),
|
|
1311
|
+
chalk8.dim("Expires")
|
|
1662
1312
|
].join(" ");
|
|
1663
1313
|
console.log(` ${header}`);
|
|
1664
|
-
console.log(` ${
|
|
1314
|
+
console.log(` ${chalk8.dim("-".repeat(capWidth + statusWidth + 24))}`);
|
|
1665
1315
|
for (const grant of data.grants) {
|
|
1666
|
-
const statusColor = grant.status === "active" ?
|
|
1316
|
+
const statusColor = grant.status === "active" ? chalk8.green : chalk8.yellow;
|
|
1667
1317
|
const expiresAt = grant.expires_at ? new Date(grant.expires_at).toLocaleString() : "-";
|
|
1668
1318
|
const row = [
|
|
1669
|
-
|
|
1319
|
+
chalk8.cyan(grant.capability.padEnd(capWidth)),
|
|
1670
1320
|
statusColor(grant.status.padEnd(statusWidth)),
|
|
1671
|
-
|
|
1321
|
+
chalk8.dim(expiresAt)
|
|
1672
1322
|
].join(" ");
|
|
1673
1323
|
console.log(` ${row}`);
|
|
1674
1324
|
}
|
|
1675
1325
|
} else {
|
|
1676
1326
|
console.log();
|
|
1677
|
-
console.log(
|
|
1327
|
+
console.log(chalk8.dim(" No active grants."));
|
|
1678
1328
|
}
|
|
1679
1329
|
console.log();
|
|
1680
1330
|
} catch (err) {
|
|
1681
1331
|
const message = err instanceof Error ? err.message : String(err);
|
|
1682
|
-
console.error(
|
|
1332
|
+
console.error(chalk8.red(`Error: ${message}`));
|
|
1683
1333
|
process.exit(1);
|
|
1684
1334
|
}
|
|
1685
1335
|
});
|
|
1686
1336
|
|
|
1687
1337
|
// dist/commands/report.js
|
|
1688
|
-
import { Command as
|
|
1689
|
-
import
|
|
1690
|
-
import * as
|
|
1691
|
-
var reportCommand = new
|
|
1338
|
+
import { Command as Command9 } from "commander";
|
|
1339
|
+
import chalk9 from "chalk";
|
|
1340
|
+
import * as jose6 from "jose";
|
|
1341
|
+
var reportCommand = new Command9("report").description("Report a telemetry event (metadata only, no conversation content)").option("--skill <name>", "Skill name associated with the event").option("--event <type>", "Event type (e.g. decrypt, error, usage)", "usage").option("--status <status>", "Event status (success, failure, error)", "success").option("--detail <detail>", "Additional detail string").action(async (options) => {
|
|
1692
1342
|
try {
|
|
1693
1343
|
const config = getConfig();
|
|
1694
1344
|
if (!config) {
|
|
1695
|
-
process.stderr.write(
|
|
1345
|
+
process.stderr.write(chalk9.red("Not logged in. Run `skillvault-publisher login` first.\n"));
|
|
1696
1346
|
process.exit(1);
|
|
1697
1347
|
}
|
|
1698
1348
|
const keypair = getKeypair();
|
|
1699
1349
|
if (!keypair) {
|
|
1700
|
-
process.stderr.write(
|
|
1350
|
+
process.stderr.write(chalk9.red("Credentials not found. Run `skillvault-publisher login` first.\n"));
|
|
1701
1351
|
process.exit(1);
|
|
1702
1352
|
}
|
|
1703
1353
|
const agentPrivJWK = keypair.privateKey.agent;
|
|
1704
1354
|
const agentPubJWK = keypair.publicKey.agent;
|
|
1705
|
-
const agentPrivKey = await
|
|
1706
|
-
const agentJWT = await new
|
|
1355
|
+
const agentPrivKey = await jose6.importJWK(agentPrivJWK, "EdDSA");
|
|
1356
|
+
const agentJWT = await new jose6.SignJWT({
|
|
1707
1357
|
iss: config.host_thumbprint,
|
|
1708
1358
|
sub: config.agent_id,
|
|
1709
1359
|
aud: config.server_url,
|
|
@@ -1732,24 +1382,24 @@ var reportCommand = new Command11("report").description("Report a telemetry even
|
|
|
1732
1382
|
error: "unknown",
|
|
1733
1383
|
message: response.statusText
|
|
1734
1384
|
}));
|
|
1735
|
-
process.stderr.write(
|
|
1385
|
+
process.stderr.write(chalk9.red(`Report failed: ${err.message}
|
|
1736
1386
|
`));
|
|
1737
1387
|
process.exit(1);
|
|
1738
1388
|
}
|
|
1739
|
-
console.log(
|
|
1389
|
+
console.log(chalk9.dim("Event reported."));
|
|
1740
1390
|
} catch (err) {
|
|
1741
1391
|
const message = err instanceof Error ? err.message : String(err);
|
|
1742
|
-
process.stderr.write(
|
|
1392
|
+
process.stderr.write(chalk9.red(`Report failed: ${message}
|
|
1743
1393
|
`));
|
|
1744
1394
|
process.exit(1);
|
|
1745
1395
|
}
|
|
1746
1396
|
});
|
|
1747
1397
|
|
|
1748
1398
|
// dist/commands/init.js
|
|
1749
|
-
import { Command as
|
|
1750
|
-
import
|
|
1751
|
-
import { existsSync as
|
|
1752
|
-
import { resolve as resolve3, join as
|
|
1399
|
+
import { Command as Command10 } from "commander";
|
|
1400
|
+
import chalk10 from "chalk";
|
|
1401
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1402
|
+
import { resolve as resolve3, join as join6 } from "node:path";
|
|
1753
1403
|
function toTitleCase(name) {
|
|
1754
1404
|
return name.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1755
1405
|
}
|
|
@@ -1775,74 +1425,74 @@ description: "Describe what this skill does and when Claude should use it. Be sp
|
|
|
1775
1425
|
[Step-by-step instructions for Claude to follow]
|
|
1776
1426
|
`;
|
|
1777
1427
|
}
|
|
1778
|
-
var initCommand = new
|
|
1428
|
+
var initCommand = new Command10("init").description("Scaffold a new skill directory with starter files").argument("[name]", "Name of the skill to create").action(async (name) => {
|
|
1779
1429
|
if (!name) {
|
|
1780
|
-
process.stderr.write(
|
|
1430
|
+
process.stderr.write(chalk10.red("Error: Skill name is required.\n"));
|
|
1781
1431
|
process.stderr.write("\n");
|
|
1782
|
-
process.stderr.write(
|
|
1783
|
-
process.stderr.write(
|
|
1432
|
+
process.stderr.write(chalk10.dim("Usage:\n"));
|
|
1433
|
+
process.stderr.write(chalk10.dim(" skillvault-publisher init <skill-name>\n"));
|
|
1784
1434
|
process.stderr.write("\n");
|
|
1785
|
-
process.stderr.write(
|
|
1786
|
-
process.stderr.write(
|
|
1435
|
+
process.stderr.write(chalk10.dim("Example:\n"));
|
|
1436
|
+
process.stderr.write(chalk10.dim(" skillvault-publisher init my-awesome-skill\n"));
|
|
1787
1437
|
process.exit(1);
|
|
1788
1438
|
}
|
|
1789
1439
|
const dirPath = resolve3(name);
|
|
1790
|
-
if (
|
|
1791
|
-
process.stderr.write(
|
|
1440
|
+
if (existsSync5(dirPath)) {
|
|
1441
|
+
process.stderr.write(chalk10.red(`Error: Directory "${name}" already exists.
|
|
1792
1442
|
`));
|
|
1793
1443
|
process.exit(1);
|
|
1794
1444
|
}
|
|
1795
1445
|
try {
|
|
1796
|
-
|
|
1797
|
-
const skillMdPath =
|
|
1798
|
-
|
|
1799
|
-
const referencesDir =
|
|
1800
|
-
|
|
1801
|
-
|
|
1446
|
+
mkdirSync4(dirPath, { recursive: true });
|
|
1447
|
+
const skillMdPath = join6(dirPath, "SKILL.md");
|
|
1448
|
+
writeFileSync4(skillMdPath, generateSkillMd(name), "utf8");
|
|
1449
|
+
const referencesDir = join6(dirPath, "references");
|
|
1450
|
+
mkdirSync4(referencesDir, { recursive: true });
|
|
1451
|
+
writeFileSync4(join6(referencesDir, ".gitkeep"), "", "utf8");
|
|
1802
1452
|
console.log();
|
|
1803
|
-
console.log(
|
|
1453
|
+
console.log(chalk10.green(` Skill "${name}" created successfully!`));
|
|
1804
1454
|
console.log();
|
|
1805
|
-
console.log(
|
|
1806
|
-
console.log(
|
|
1807
|
-
console.log(
|
|
1455
|
+
console.log(chalk10.bold(" Created files:"));
|
|
1456
|
+
console.log(chalk10.dim(` ${name}/SKILL.md`));
|
|
1457
|
+
console.log(chalk10.dim(` ${name}/references/.gitkeep`));
|
|
1808
1458
|
console.log();
|
|
1809
|
-
console.log(
|
|
1810
|
-
console.log(` 1. Edit ${
|
|
1811
|
-
console.log(` 2. Add any reference files to ${
|
|
1459
|
+
console.log(chalk10.bold(" Next steps:"));
|
|
1460
|
+
console.log(` 1. Edit ${chalk10.cyan(`${name}/SKILL.md`)} with your skill instructions`);
|
|
1461
|
+
console.log(` 2. Add any reference files to ${chalk10.cyan(`${name}/references/`)}`);
|
|
1812
1462
|
console.log(` 3. Update the frontmatter description with specific trigger phrases`);
|
|
1813
|
-
console.log(` 4. Publish with: ${
|
|
1463
|
+
console.log(` 4. Publish with: ${chalk10.cyan(`skillvault-publisher publish ./${name}/`)}`);
|
|
1814
1464
|
console.log();
|
|
1815
1465
|
} catch (err) {
|
|
1816
1466
|
const message = err instanceof Error ? err.message : String(err);
|
|
1817
|
-
process.stderr.write(
|
|
1467
|
+
process.stderr.write(chalk10.red(`Failed to create skill: ${message}
|
|
1818
1468
|
`));
|
|
1819
1469
|
process.exit(1);
|
|
1820
1470
|
}
|
|
1821
1471
|
});
|
|
1822
1472
|
|
|
1823
1473
|
// dist/commands/changelog.js
|
|
1824
|
-
import { Command as
|
|
1825
|
-
import
|
|
1826
|
-
import * as
|
|
1827
|
-
var changelogCommand = new
|
|
1474
|
+
import { Command as Command11 } from "commander";
|
|
1475
|
+
import chalk11 from "chalk";
|
|
1476
|
+
import * as jose7 from "jose";
|
|
1477
|
+
var changelogCommand = new Command11("changelog").description("View version history and changelogs for a skill").argument("<skill-name>", "Name of the skill (without skill/ prefix)").option("--limit <n>", "Show last N versions", "10").option("--json", "Output as JSON").action(async (skillName, options) => {
|
|
1828
1478
|
try {
|
|
1829
1479
|
const config = getConfig();
|
|
1830
1480
|
if (!config) {
|
|
1831
|
-
process.stderr.write(
|
|
1481
|
+
process.stderr.write(chalk11.red("Not logged in. Run `skillvault-publisher login` first.\n"));
|
|
1832
1482
|
process.exit(1);
|
|
1833
1483
|
}
|
|
1834
1484
|
const keypair = getKeypair();
|
|
1835
1485
|
if (!keypair) {
|
|
1836
|
-
process.stderr.write(
|
|
1486
|
+
process.stderr.write(chalk11.red("Credentials not found. Run `skillvault-publisher login` first.\n"));
|
|
1837
1487
|
process.exit(1);
|
|
1838
1488
|
}
|
|
1839
1489
|
const hostPrivJWK = keypair.privateKey.host;
|
|
1840
1490
|
const hostPubJWK = keypair.publicKey.host;
|
|
1841
|
-
const hostPrivKey = await
|
|
1491
|
+
const hostPrivKey = await jose7.importJWK(hostPrivJWK, "EdDSA");
|
|
1842
1492
|
const hostThumbprint = config.host_thumbprint;
|
|
1843
1493
|
const serverUrl = config.server_url;
|
|
1844
1494
|
async function makeAuthHeaders() {
|
|
1845
|
-
const jwt = await new
|
|
1495
|
+
const jwt = await new jose7.SignJWT({
|
|
1846
1496
|
iss: hostThumbprint,
|
|
1847
1497
|
aud: serverUrl,
|
|
1848
1498
|
host_public_key: hostPubJWK,
|
|
@@ -1856,21 +1506,21 @@ var changelogCommand = new Command13("changelog").description("View version hist
|
|
|
1856
1506
|
const publisherId = config.publisher_id || config.host_id;
|
|
1857
1507
|
const skillsRes = await fetch(`${serverUrl}/skills?publisher_id=${encodeURIComponent(publisherId)}`, { headers: await makeAuthHeaders() });
|
|
1858
1508
|
if (!skillsRes.ok) {
|
|
1859
|
-
process.stderr.write(
|
|
1509
|
+
process.stderr.write(chalk11.red(`Failed to fetch skills: ${skillsRes.statusText}
|
|
1860
1510
|
`));
|
|
1861
1511
|
process.exit(1);
|
|
1862
1512
|
}
|
|
1863
1513
|
const skillsData = await skillsRes.json();
|
|
1864
1514
|
const skill = skillsData.skills.find((s) => s.name.toLowerCase() === skillName.toLowerCase() || s.capability_name === `skill/${skillName.toLowerCase()}`);
|
|
1865
1515
|
if (!skill) {
|
|
1866
|
-
process.stderr.write(
|
|
1516
|
+
process.stderr.write(chalk11.red(`Skill "${skillName}" not found.
|
|
1867
1517
|
`));
|
|
1868
|
-
process.stderr.write(
|
|
1518
|
+
process.stderr.write(chalk11.dim("Make sure you have published this skill first.\n"));
|
|
1869
1519
|
process.exit(1);
|
|
1870
1520
|
}
|
|
1871
1521
|
const versionsRes = await fetch(`${serverUrl}/skills/${skill.id}/versions`, { headers: await makeAuthHeaders() });
|
|
1872
1522
|
if (!versionsRes.ok) {
|
|
1873
|
-
process.stderr.write(
|
|
1523
|
+
process.stderr.write(chalk11.red(`Failed to fetch versions: ${versionsRes.statusText}
|
|
1874
1524
|
`));
|
|
1875
1525
|
process.exit(1);
|
|
1876
1526
|
}
|
|
@@ -1879,7 +1529,7 @@ var changelogCommand = new Command13("changelog").description("View version hist
|
|
|
1879
1529
|
const limit = parseInt(options.limit, 10) || 10;
|
|
1880
1530
|
versions = versions.slice(0, limit);
|
|
1881
1531
|
if (versions.length === 0) {
|
|
1882
|
-
console.log(
|
|
1532
|
+
console.log(chalk11.dim("No versions found."));
|
|
1883
1533
|
return;
|
|
1884
1534
|
}
|
|
1885
1535
|
if (options.json) {
|
|
@@ -1887,40 +1537,47 @@ var changelogCommand = new Command13("changelog").description("View version hist
|
|
|
1887
1537
|
return;
|
|
1888
1538
|
}
|
|
1889
1539
|
console.log("");
|
|
1890
|
-
console.log(
|
|
1540
|
+
console.log(chalk11.bold(`${skillName} \u2014 Version History`));
|
|
1891
1541
|
console.log("");
|
|
1892
1542
|
for (const ver of versions) {
|
|
1893
1543
|
const date = ver.created_at ? new Date(ver.created_at).toISOString().split("T")[0] : "unknown";
|
|
1894
|
-
console.log(
|
|
1544
|
+
console.log(chalk11.cyan(`v${ver.version}`) + chalk11.dim(` (${date})`));
|
|
1895
1545
|
if (ver.changelog) {
|
|
1896
1546
|
console.log(` ${ver.changelog}`);
|
|
1897
1547
|
} else {
|
|
1898
|
-
console.log(
|
|
1548
|
+
console.log(chalk11.dim(" No changelog entry"));
|
|
1899
1549
|
}
|
|
1900
1550
|
console.log("");
|
|
1901
1551
|
}
|
|
1902
1552
|
} catch (err) {
|
|
1903
1553
|
const message = err instanceof Error ? err.message : String(err);
|
|
1904
|
-
process.stderr.write(
|
|
1554
|
+
process.stderr.write(chalk11.red(`Changelog failed: ${message}
|
|
1905
1555
|
`));
|
|
1906
1556
|
process.exit(1);
|
|
1907
1557
|
}
|
|
1908
1558
|
});
|
|
1909
1559
|
|
|
1910
1560
|
// dist/index.js
|
|
1911
|
-
var program = new
|
|
1912
|
-
program.name("skillvault-publisher").description("SkillVault publisher CLI \u2014 publish, manage, and distribute encrypted skills").version("0.
|
|
1561
|
+
var program = new Command12();
|
|
1562
|
+
program.name("skillvault-publisher").description("SkillVault publisher CLI \u2014 publish, manage, and distribute encrypted skills").version("0.7.3").addHelpText("after", `
|
|
1563
|
+
|
|
1564
|
+
Getting Started:
|
|
1565
|
+
1. Create an account at https://app.getskillvault.com/login
|
|
1566
|
+
2. Log in: skillvault-publisher login --server https://api.getskillvault.com
|
|
1567
|
+
3. Scaffold: skillvault-publisher init my-skill
|
|
1568
|
+
4. Publish: skillvault-publisher publish ./my-skill/
|
|
1569
|
+
|
|
1570
|
+
Dashboard: https://app.getskillvault.com
|
|
1571
|
+
Docs: https://app.getskillvault.com/cli`);
|
|
1913
1572
|
program.addCommand(loginCommand);
|
|
1914
1573
|
program.addCommand(logoutCommand);
|
|
1915
1574
|
program.addCommand(publishCommand);
|
|
1916
|
-
program.addCommand(
|
|
1917
|
-
program.addCommand(
|
|
1575
|
+
program.addCommand(initCommand);
|
|
1576
|
+
program.addCommand(updateCommand);
|
|
1577
|
+
program.addCommand(changelogCommand);
|
|
1918
1578
|
program.addCommand(searchCommand);
|
|
1919
1579
|
program.addCommand(infoCommand);
|
|
1920
1580
|
program.addCommand(licensesCommand);
|
|
1921
|
-
program.addCommand(updateCommand);
|
|
1922
1581
|
program.addCommand(whoamiCommand);
|
|
1923
1582
|
program.addCommand(reportCommand);
|
|
1924
|
-
program.addCommand(initCommand);
|
|
1925
|
-
program.addCommand(changelogCommand);
|
|
1926
1583
|
program.parse();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,sBAAsB,CAAC;KAC5B,WAAW,CAAC,6EAA6E,CAAC;KAC1F,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,OAAO,EAAE;;;;;;;;;6CASqB,CAAC,CAAC;AAE/C,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|