skillvault 0.7.0 → 0.7.1

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 (2) hide show
  1. package/dist/cli.js +76 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@
20
20
  import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync } from 'node:fs';
21
21
  import { join } from 'node:path';
22
22
  import { createDecipheriv, createPublicKey, diffieHellman, hkdfSync, generateKeyPairSync, } from 'node:crypto';
23
- const VERSION = '0.7.0';
23
+ const VERSION = '0.7.1';
24
24
  const HOME = process.env.HOME || process.env.USERPROFILE || '~';
25
25
  const API_URL = process.env.SKILLVAULT_API_URL || 'https://api.getskillvault.com';
26
26
  const CONFIG_DIR = join(HOME, '.skillvault');
@@ -107,6 +107,19 @@ async function setup(code) {
107
107
  if (!response.ok) {
108
108
  const err = await response.json().catch(() => ({ message: response.statusText }));
109
109
  console.error(` ❌ Failed: ${err.message}`);
110
+ console.error('');
111
+ if (err.message.includes('404') || err.message.includes('not found')) {
112
+ console.error(' The invite code was not found. Check that you entered it correctly.');
113
+ console.error(' Invite codes are 8 characters (e.g. A1B2C3D4).');
114
+ }
115
+ else if (err.message.includes('400') || err.message.includes('expired')) {
116
+ console.error(' This invite code has already been used or has expired.');
117
+ console.error(' Ask the publisher for a new invite code.');
118
+ }
119
+ else {
120
+ console.error(' Could not reach the SkillVault server. Check your internet connection.');
121
+ console.error(` Server: ${API_URL}`);
122
+ }
110
123
  process.exit(1);
111
124
  }
112
125
  const data = await response.json();
@@ -327,14 +340,14 @@ async function refreshTokens() {
327
340
  anyRefreshed = true;
328
341
  }
329
342
  else if (res.status === 401) {
330
- console.error('❌ expired — re-invite required');
343
+ console.error('❌ expired — ask the publisher for a new invite code');
331
344
  }
332
345
  else {
333
- console.error(`❌ server error (${res.status})`);
346
+ console.error(`❌ server error (${res.status}). Try again later or contact the publisher.`);
334
347
  }
335
348
  }
336
349
  catch {
337
- console.error('❌ offline');
350
+ console.error('❌ offline — check your internet connection');
338
351
  }
339
352
  }
340
353
  if (anyRefreshed) {
@@ -362,7 +375,7 @@ async function syncSkills() {
362
375
  signal: AbortSignal.timeout(10000),
363
376
  });
364
377
  if (!res.ok) {
365
- errors.push(`${pub.name}: ${res.status === 401 ? 'auth expired' : `failed (${res.status})`}`);
378
+ errors.push(`${pub.name}: ${res.status === 401 ? 'auth expired — run npx skillvault --refresh' : `server returned ${res.status}`}`);
366
379
  continue;
367
380
  }
368
381
  const data = await res.json();
@@ -715,12 +728,19 @@ async function backgroundSyncAll(config) {
715
728
  */
716
729
  async function loadSkill(skillName) {
717
730
  if (!validateSkillName(skillName)) {
718
- console.error('Error: Invalid skill name.');
731
+ console.error('Error: Invalid skill name. Skill names can only contain letters, numbers, hyphens, and underscores (max 128 chars).');
732
+ console.error('Example: npx skillvault --load my-skill-name');
719
733
  process.exit(1);
720
734
  }
721
735
  const config = loadConfig();
722
736
  if (!config) {
723
- console.error('Error: Not configured. Run: npx skillvault --invite YOUR_CODE');
737
+ console.error('Error: SkillVault is not configured on this machine.');
738
+ console.error('');
739
+ console.error('To set up, you need an invite code from a skill publisher.');
740
+ console.error('Run: npx skillvault --invite YOUR_INVITE_CODE');
741
+ console.error('');
742
+ console.error('If you already set up SkillVault, the config file may be missing:');
743
+ console.error(` Expected: ${CONFIG_PATH}`);
724
744
  process.exit(1);
725
745
  }
726
746
  // Pre-load sync: ensure we have the latest vault for this skill
@@ -738,8 +758,30 @@ async function loadSkill(skillName) {
738
758
  resolved = resolveSkillPublisher(skillName, config);
739
759
  }
740
760
  if (!resolved) {
741
- console.error(`Error: Vault not found for "${skillName}" after sync.`);
742
- console.error('You may not have access to this skill. Check with your skill provider.');
761
+ console.error(`Error: Skill "${skillName}" not found after syncing with server.`);
762
+ console.error('');
763
+ console.error('Possible causes:');
764
+ console.error(' 1. You don\'t have a license for this skill — ask the publisher for an invite');
765
+ console.error(' 2. The skill name is misspelled — check the exact name with: npx skillvault --status');
766
+ console.error(' 3. Your token expired — refresh with: npx skillvault --refresh');
767
+ console.error('');
768
+ console.error('Available skills on this machine:');
769
+ const localConfig = loadConfig();
770
+ if (localConfig) {
771
+ for (const pub of localConfig.publishers) {
772
+ const pubVaultDir = join(VAULT_DIR, pub.id);
773
+ try {
774
+ if (existsSync(pubVaultDir)) {
775
+ const vaults = readdirSync(pubVaultDir).filter(f => f.endsWith('.vault'));
776
+ for (const v of vaults)
777
+ console.error(` - ${v.replace('.vault', '')} (from ${pub.name})`);
778
+ }
779
+ }
780
+ catch { }
781
+ }
782
+ if (localConfig.publishers.length === 0)
783
+ console.error(' (none — no publishers configured)');
784
+ }
743
785
  process.exit(1);
744
786
  }
745
787
  // Kick off background sync for all other skills (non-blocking)
@@ -751,8 +793,27 @@ async function loadSkill(skillName) {
751
793
  cek = await fetchCEK(skillName, resolved.publisher.token);
752
794
  }
753
795
  catch (err) {
754
- console.error(`Error: License check failed — ${err instanceof Error ? err.message : 'unknown'}`);
755
- console.error('Your license may have expired or been revoked. Contact your skill provider.');
796
+ const errMsg = err instanceof Error ? err.message : 'unknown';
797
+ console.error(`Error: License check failed for "${skillName}" ${errMsg}`);
798
+ console.error('');
799
+ if (errMsg.includes('403') || errMsg.includes('no_license')) {
800
+ console.error('Your license for this skill has been revoked or expired.');
801
+ console.error('Contact the skill publisher to request a new license.');
802
+ }
803
+ else if (errMsg.includes('401')) {
804
+ console.error('Your authentication token has expired.');
805
+ console.error('Fix: npx skillvault --refresh');
806
+ }
807
+ else if (errMsg.includes('fetch') || errMsg.includes('ECONNREFUSED')) {
808
+ console.error('Could not reach the SkillVault server. Check your internet connection.');
809
+ console.error(`Server: ${API_URL}`);
810
+ }
811
+ else {
812
+ console.error('The server rejected the license check. This could mean:');
813
+ console.error(' - Your license was revoked');
814
+ console.error(' - Your token expired (fix: npx skillvault --refresh)');
815
+ console.error(' - The server is temporarily unavailable');
816
+ }
756
817
  process.exit(1);
757
818
  }
758
819
  // Decrypt in memory
@@ -773,6 +834,10 @@ async function loadSkill(skillName) {
773
834
  catch (err) {
774
835
  cek.fill(0);
775
836
  console.error(`Error: Decryption failed — ${err instanceof Error ? err.message : 'unknown'}`);
837
+ console.error('');
838
+ console.error('The vault file may be corrupted or the CEK may not match.');
839
+ console.error('Try re-syncing: npx skillvault --sync');
840
+ console.error('If the problem persists, the skill may need to be republished by the publisher.');
776
841
  process.exit(1);
777
842
  }
778
843
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillvault",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "SkillVault — secure skill distribution for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {