reskill 0.11.0 → 0.12.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 (39) hide show
  1. package/dist/cli/commands/index.d.ts +3 -3
  2. package/dist/cli/commands/index.d.ts.map +1 -1
  3. package/dist/cli/commands/info.d.ts +1 -1
  4. package/dist/cli/commands/init.d.ts +1 -1
  5. package/dist/cli/commands/install.d.ts +11 -11
  6. package/dist/cli/commands/install.d.ts.map +1 -1
  7. package/dist/cli/commands/list.d.ts +1 -1
  8. package/dist/cli/commands/list.d.ts.map +1 -1
  9. package/dist/cli/commands/outdated.d.ts +1 -1
  10. package/dist/cli/commands/outdated.d.ts.map +1 -1
  11. package/dist/cli/commands/uninstall.d.ts +1 -1
  12. package/dist/cli/commands/update.d.ts +1 -1
  13. package/dist/cli/index.js +668 -634
  14. package/dist/core/agent-registry.d.ts +16 -16
  15. package/dist/core/agent-registry.d.ts.map +1 -1
  16. package/dist/core/cache-manager.d.ts +17 -17
  17. package/dist/core/cache-manager.d.ts.map +1 -1
  18. package/dist/core/config-loader.d.ts +18 -18
  19. package/dist/core/config-loader.d.ts.map +1 -1
  20. package/dist/core/git-resolver.d.ts +23 -23
  21. package/dist/core/git-resolver.d.ts.map +1 -1
  22. package/dist/core/index.d.ts +8 -8
  23. package/dist/core/index.d.ts.map +1 -1
  24. package/dist/core/installer.d.ts +30 -30
  25. package/dist/core/installer.d.ts.map +1 -1
  26. package/dist/core/lock-manager.d.ts +17 -17
  27. package/dist/core/lock-manager.d.ts.map +1 -1
  28. package/dist/core/skill-manager.d.ts +57 -39
  29. package/dist/core/skill-manager.d.ts.map +1 -1
  30. package/dist/core/skill-parser.d.ts +43 -43
  31. package/dist/core/skill-parser.d.ts.map +1 -1
  32. package/dist/index.d.ts +3 -3
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +615 -581
  35. package/dist/types/index.d.ts +84 -84
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/dist/utils/fs.d.ts +7 -7
  38. package/dist/utils/fs.d.ts.map +1 -1
  39. package/package.json +18 -12
package/dist/cli/index.js CHANGED
@@ -3,13 +3,11 @@ import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
3
3
  import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
4
4
  import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
5
5
  import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
6
- import * as __WEBPACK_EXTERNAL_MODULE__clack_prompts__ from "@clack/prompts";
7
- import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
6
+ import * as __WEBPACK_EXTERNAL_MODULE_node_os__ from "node:os";
8
7
  import * as __WEBPACK_EXTERNAL_MODULE_node_child_process__ from "node:child_process";
9
8
  import * as __WEBPACK_EXTERNAL_MODULE_node_util__ from "node:util";
10
- import * as __WEBPACK_EXTERNAL_MODULE_os__ from "os";
11
- import * as __WEBPACK_EXTERNAL_MODULE_path__ from "path";
12
- import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
9
+ import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
10
+ import * as __WEBPACK_EXTERNAL_MODULE__clack_prompts__ from "@clack/prompts";
13
11
  import * as __WEBPACK_EXTERNAL_MODULE_ora__ from "ora";
14
12
  var __webpack_modules__ = {
15
13
  "node:fs": function(module) {
@@ -39,7 +37,7 @@ function writeJson(filePath, data, indent = 2) {
39
37
  if (!exists(dir)) external_node_fs_.mkdirSync(dir, {
40
38
  recursive: true
41
39
  });
42
- external_node_fs_.writeFileSync(filePath, JSON.stringify(data, null, indent) + '\n', 'utf-8');
40
+ external_node_fs_.writeFileSync(filePath, `${JSON.stringify(data, null, indent)}\n`, 'utf-8');
43
41
  }
44
42
  function ensureDir(dirPath) {
45
43
  if (!exists(dirPath)) external_node_fs_.mkdirSync(dirPath, {
@@ -110,121 +108,9 @@ function shortenPath(fullPath, cwd) {
110
108
  const home = getHomeDir();
111
109
  const currentDir = cwd || process.cwd();
112
110
  if (fullPath.startsWith(home)) return fullPath.replace(home, '~');
113
- if (fullPath.startsWith(currentDir)) return '.' + fullPath.slice(currentDir.length);
111
+ if (fullPath.startsWith(currentDir)) return `.${fullPath.slice(currentDir.length)}`;
114
112
  return fullPath;
115
113
  }
116
- const DEFAULT_SKILLS_JSON = {
117
- skills: {},
118
- defaults: {
119
- registry: 'github',
120
- installDir: '.skills'
121
- }
122
- };
123
- const DEFAULT_REGISTRIES = {
124
- github: 'https://github.com',
125
- gitlab: 'https://gitlab.com'
126
- };
127
- class ConfigLoader {
128
- projectRoot;
129
- configPath;
130
- config = null;
131
- constructor(projectRoot){
132
- this.projectRoot = projectRoot || process.cwd();
133
- this.configPath = getSkillsJsonPath(this.projectRoot);
134
- }
135
- getProjectRoot() {
136
- return this.projectRoot;
137
- }
138
- getConfigPath() {
139
- return this.configPath;
140
- }
141
- exists() {
142
- return exists(this.configPath);
143
- }
144
- load() {
145
- if (this.config) return this.config;
146
- if (!this.exists()) throw new Error(`skills.json not found in ${this.projectRoot}. Run 'reskill init' first.`);
147
- try {
148
- this.config = readJson(this.configPath);
149
- return this.config;
150
- } catch (error) {
151
- throw new Error(`Failed to parse skills.json: ${error.message}`);
152
- }
153
- }
154
- reload() {
155
- this.config = null;
156
- return this.load();
157
- }
158
- save(config) {
159
- const toSave = config || this.config;
160
- if (!toSave) throw new Error('No config to save');
161
- writeJson(this.configPath, toSave);
162
- this.config = toSave;
163
- }
164
- create(options) {
165
- const config = {
166
- ...DEFAULT_SKILLS_JSON,
167
- ...options,
168
- skills: options?.skills || {},
169
- defaults: {
170
- ...DEFAULT_SKILLS_JSON.defaults,
171
- ...options?.defaults
172
- }
173
- };
174
- this.save(config);
175
- return config;
176
- }
177
- getDefaults() {
178
- const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
179
- return {
180
- registry: config.defaults?.registry || DEFAULT_SKILLS_JSON.defaults.registry,
181
- installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir,
182
- targetAgents: config.defaults?.targetAgents || [],
183
- installMode: config.defaults?.installMode || 'symlink'
184
- };
185
- }
186
- getRegistryUrl(registryName) {
187
- const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
188
- if (config.registries?.[registryName]) return config.registries[registryName];
189
- if (DEFAULT_REGISTRIES[registryName]) return DEFAULT_REGISTRIES[registryName];
190
- return `https://${registryName}`;
191
- }
192
- getInstallDir() {
193
- const defaults = this.getDefaults();
194
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, defaults.installDir);
195
- }
196
- addSkill(name, ref) {
197
- if (!this.config) this.load();
198
- this.config.skills[name] = ref;
199
- this.save();
200
- }
201
- removeSkill(name) {
202
- if (!this.config) this.load();
203
- if (this.config.skills[name]) {
204
- delete this.config.skills[name];
205
- this.save();
206
- return true;
207
- }
208
- return false;
209
- }
210
- getSkills() {
211
- if (!this.config) {
212
- if (!this.exists()) return {};
213
- this.load();
214
- }
215
- return {
216
- ...this.config.skills
217
- };
218
- }
219
- hasSkill(name) {
220
- const skills = this.getSkills();
221
- return name in skills;
222
- }
223
- getSkillRef(name) {
224
- const skills = this.getSkills();
225
- return skills[name];
226
- }
227
- }
228
114
  const logger = {
229
115
  info (message) {
230
116
  console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue('ℹ'), message);
@@ -266,30 +152,139 @@ const logger = {
266
152
  }
267
153
  }
268
154
  };
269
- const initCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('init').description('Initialize a new skills.json configuration').option('-n, --name <name>', 'Project name').option('-r, --registry <registry>', 'Default registry', 'github').option('-d, --install-dir <dir>', 'Skills installation directory', '.skills').option('-y, --yes', 'Skip prompts and use defaults').action(async (options)=>{
270
- const configLoader = new ConfigLoader();
271
- if (configLoader.exists()) {
272
- logger.warn('skills.json already exists');
273
- return;
155
+ const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)();
156
+ const agents = {
157
+ amp: {
158
+ name: 'amp',
159
+ displayName: 'Amp',
160
+ skillsDir: '.agents/skills',
161
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/agents/skills'),
162
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/amp'))
163
+ },
164
+ antigravity: {
165
+ name: 'antigravity',
166
+ displayName: 'Antigravity',
167
+ skillsDir: '.agent/skills',
168
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
169
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(process.cwd(), '.agent')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/antigravity'))
170
+ },
171
+ 'claude-code': {
172
+ name: 'claude-code',
173
+ displayName: 'Claude Code',
174
+ skillsDir: '.claude/skills',
175
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude/skills'),
176
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude'))
177
+ },
178
+ clawdbot: {
179
+ name: 'clawdbot',
180
+ displayName: 'Clawdbot',
181
+ skillsDir: 'skills',
182
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot/skills'),
183
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot'))
184
+ },
185
+ codex: {
186
+ name: 'codex',
187
+ displayName: 'Codex',
188
+ skillsDir: '.codex/skills',
189
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex/skills'),
190
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex'))
191
+ },
192
+ cursor: {
193
+ name: 'cursor',
194
+ displayName: 'Cursor',
195
+ skillsDir: '.cursor/skills',
196
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor/skills'),
197
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor'))
198
+ },
199
+ droid: {
200
+ name: 'droid',
201
+ displayName: 'Droid',
202
+ skillsDir: '.factory/skills',
203
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'),
204
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'))
205
+ },
206
+ 'gemini-cli': {
207
+ name: 'gemini-cli',
208
+ displayName: 'Gemini CLI',
209
+ skillsDir: '.gemini/skills',
210
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/skills'),
211
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini'))
212
+ },
213
+ 'github-copilot': {
214
+ name: 'github-copilot',
215
+ displayName: 'GitHub Copilot',
216
+ skillsDir: '.github/skills',
217
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.copilot/skills'),
218
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(process.cwd(), '.github')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.copilot'))
219
+ },
220
+ goose: {
221
+ name: 'goose',
222
+ displayName: 'Goose',
223
+ skillsDir: '.goose/skills',
224
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose/skills'),
225
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose'))
226
+ },
227
+ kilo: {
228
+ name: 'kilo',
229
+ displayName: 'Kilo Code',
230
+ skillsDir: '.kilocode/skills',
231
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode/skills'),
232
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode'))
233
+ },
234
+ 'kiro-cli': {
235
+ name: 'kiro-cli',
236
+ displayName: 'Kiro CLI',
237
+ skillsDir: '.kiro/skills',
238
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro/skills'),
239
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro'))
240
+ },
241
+ opencode: {
242
+ name: 'opencode',
243
+ displayName: 'OpenCode',
244
+ skillsDir: '.opencode/skills',
245
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/opencode/skills'),
246
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/opencode')) || (0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude/skills'))
247
+ },
248
+ roo: {
249
+ name: 'roo',
250
+ displayName: 'Roo Code',
251
+ skillsDir: '.roo/skills',
252
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo/skills'),
253
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo'))
254
+ },
255
+ trae: {
256
+ name: 'trae',
257
+ displayName: 'Trae',
258
+ skillsDir: '.trae/skills',
259
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae/skills'),
260
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae'))
261
+ },
262
+ windsurf: {
263
+ name: 'windsurf',
264
+ displayName: 'Windsurf',
265
+ skillsDir: '.windsurf/skills',
266
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
267
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf'))
268
+ },
269
+ neovate: {
270
+ name: 'neovate',
271
+ displayName: 'Neovate',
272
+ skillsDir: '.neovate/skills',
273
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate/skills'),
274
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate'))
274
275
  }
275
- const config = configLoader.create({
276
- name: options.name,
277
- defaults: {
278
- registry: options.registry,
279
- installDir: options.installDir
280
- }
281
- });
282
- logger.success('Created skills.json');
283
- logger.newline();
284
- logger.log('Configuration:');
285
- logger.log(` Name: ${config.name || '(not set)'}`);
286
- logger.log(` Default registry: ${config.defaults?.registry}`);
287
- logger.log(` Install directory: ${config.defaults?.installDir}`);
288
- logger.newline();
289
- logger.log('Next steps:');
290
- logger.log(' reskill install <skill> Install a skill');
291
- logger.log(' reskill list List installed skills');
292
- });
276
+ };
277
+ async function detectInstalledAgents() {
278
+ const installed = [];
279
+ for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
280
+ return installed;
281
+ }
282
+ function getAgentConfig(type) {
283
+ return agents[type];
284
+ }
285
+ function isValidAgentType(type) {
286
+ return type in agents;
287
+ }
293
288
  const execAsync = (0, __WEBPACK_EXTERNAL_MODULE_node_util__.promisify)(__WEBPACK_EXTERNAL_MODULE_node_child_process__.exec);
294
289
  class GitCloneError extends Error {
295
290
  repoUrl;
@@ -301,7 +296,7 @@ class GitCloneError extends Error {
301
296
  if (isAuthError) {
302
297
  message += '\n\nTip: For private repos, ensure git SSH keys or credentials are configured:';
303
298
  message += '\n - SSH: Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
304
- message += '\n - HTTPS: Run \'git config --global credential.helper store\'';
299
+ message += "\n - HTTPS: Run 'git config --global credential.helper store'";
305
300
  message += '\n - Or use a personal access token in the URL';
306
301
  }
307
302
  super(message);
@@ -460,182 +455,10 @@ function parseGitUrl(url) {
460
455
  }
461
456
  return null;
462
457
  }
463
- class GitResolver {
464
- defaultRegistry;
465
- constructor(defaultRegistry = 'github'){
466
- this.defaultRegistry = defaultRegistry;
467
- }
468
- parseRef(ref) {
469
- const raw = ref;
470
- if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
471
- let remaining = ref;
472
- let registry = this.defaultRegistry;
473
- let version;
474
- const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
475
- if (registryMatch) {
476
- registry = registryMatch[1];
477
- remaining = registryMatch[2];
478
- }
479
- const atIndex = remaining.lastIndexOf('@');
480
- if (atIndex > 0) {
481
- version = remaining.slice(atIndex + 1);
482
- remaining = remaining.slice(0, atIndex);
483
- }
484
- const parts = remaining.split('/');
485
- if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
486
- const owner = parts[0];
487
- const repo = parts[1];
488
- const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
489
- return {
490
- registry,
491
- owner,
492
- repo,
493
- subPath,
494
- version,
495
- raw
496
- };
497
- }
498
- parseGitUrlRef(ref) {
499
- const raw = ref;
500
- let gitUrl = ref;
501
- let version;
502
- let subPath;
503
- const gitSuffixIndex = ref.indexOf('.git');
504
- if (-1 !== gitSuffixIndex) {
505
- const afterGit = ref.slice(gitSuffixIndex + 4);
506
- if (afterGit) {
507
- const atIndex = afterGit.lastIndexOf('@');
508
- if (-1 !== atIndex) {
509
- version = afterGit.slice(atIndex + 1);
510
- const pathPart = afterGit.slice(0, atIndex);
511
- if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
512
- } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
513
- gitUrl = ref.slice(0, gitSuffixIndex + 4);
514
- }
515
- } else {
516
- const atIndex = ref.lastIndexOf('@');
517
- if (atIndex > 4) {
518
- version = ref.slice(atIndex + 1);
519
- gitUrl = ref.slice(0, atIndex);
520
- }
521
- }
522
- const parsed = parseGitUrl(gitUrl);
523
- if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
524
- return {
525
- registry: parsed.host,
526
- owner: parsed.owner,
527
- repo: parsed.repo,
528
- subPath,
529
- version,
530
- raw,
531
- gitUrl
532
- };
533
- }
534
- parseVersion(versionSpec) {
535
- if (!versionSpec) return {
536
- type: 'branch',
537
- value: 'main',
538
- raw: ''
539
- };
540
- const raw = versionSpec;
541
- if ('latest' === versionSpec) return {
542
- type: 'latest',
543
- value: 'latest',
544
- raw
545
- };
546
- if (versionSpec.startsWith('branch:')) return {
547
- type: 'branch',
548
- value: versionSpec.slice(7),
549
- raw
550
- };
551
- if (versionSpec.startsWith('commit:')) return {
552
- type: 'commit',
553
- value: versionSpec.slice(7),
554
- raw
555
- };
556
- if (/^[\^~><]/.test(versionSpec)) return {
557
- type: 'range',
558
- value: versionSpec,
559
- raw
560
- };
561
- return {
562
- type: 'exact',
563
- value: versionSpec,
564
- raw
565
- };
566
- }
567
- buildRepoUrl(parsed) {
568
- if (parsed.gitUrl) return parsed.gitUrl;
569
- return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
570
- }
571
- async resolveVersion(repoUrl, versionSpec) {
572
- switch(versionSpec.type){
573
- case 'exact':
574
- return {
575
- ref: versionSpec.value
576
- };
577
- case 'latest':
578
- {
579
- const latestTag = await getLatestTag(repoUrl);
580
- if (!latestTag) {
581
- const defaultBranch = await getDefaultBranch(repoUrl);
582
- return {
583
- ref: defaultBranch
584
- };
585
- }
586
- return {
587
- ref: latestTag.name,
588
- commit: latestTag.commit
589
- };
590
- }
591
- case 'range':
592
- {
593
- const tags = await getRemoteTags(repoUrl);
594
- const matchingTags = tags.filter((tag)=>{
595
- const version = tag.name.replace(/^v/, '');
596
- return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
597
- });
598
- if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
599
- matchingTags.sort((a, b)=>{
600
- const aVer = a.name.replace(/^v/, '');
601
- const bVer = b.name.replace(/^v/, '');
602
- return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
603
- });
604
- return {
605
- ref: matchingTags[0].name,
606
- commit: matchingTags[0].commit
607
- };
608
- }
609
- case 'branch':
610
- return {
611
- ref: versionSpec.value
612
- };
613
- case 'commit':
614
- return {
615
- ref: versionSpec.value,
616
- commit: versionSpec.value
617
- };
618
- default:
619
- throw new Error(`Unknown version type: ${versionSpec.type}`);
620
- }
621
- }
622
- async resolve(ref) {
623
- const parsed = this.parseRef(ref);
624
- const repoUrl = this.buildRepoUrl(parsed);
625
- const versionSpec = this.parseVersion(parsed.version);
626
- const resolved = await this.resolveVersion(repoUrl, versionSpec);
627
- return {
628
- parsed,
629
- repoUrl,
630
- ref: resolved.ref,
631
- commit: resolved.commit
632
- };
633
- }
634
- }
635
- class CacheManager {
636
- cacheDir;
637
- constructor(cacheDir){
638
- this.cacheDir = cacheDir || getCacheDir();
458
+ class CacheManager {
459
+ cacheDir;
460
+ constructor(cacheDir){
461
+ this.cacheDir = cacheDir || getCacheDir();
639
462
  }
640
463
  getCacheDir() {
641
464
  return this.cacheDir;
@@ -743,238 +566,289 @@ class CacheManager {
743
566
  };
744
567
  }
745
568
  }
746
- const LOCKFILE_VERSION = 1;
747
- class LockManager {
569
+ const DEFAULT_SKILLS_JSON = {
570
+ skills: {},
571
+ defaults: {
572
+ registry: 'github',
573
+ installDir: '.skills'
574
+ }
575
+ };
576
+ const DEFAULT_REGISTRIES = {
577
+ github: 'https://github.com',
578
+ gitlab: 'https://gitlab.com'
579
+ };
580
+ class ConfigLoader {
748
581
  projectRoot;
749
- lockPath;
750
- lockData = null;
582
+ configPath;
583
+ config = null;
751
584
  constructor(projectRoot){
752
585
  this.projectRoot = projectRoot || process.cwd();
753
- this.lockPath = getSkillsLockPath(this.projectRoot);
586
+ this.configPath = getSkillsJsonPath(this.projectRoot);
754
587
  }
755
- getLockPath() {
756
- return this.lockPath;
588
+ getProjectRoot() {
589
+ return this.projectRoot;
590
+ }
591
+ getConfigPath() {
592
+ return this.configPath;
757
593
  }
758
594
  exists() {
759
- return exists(this.lockPath);
595
+ return exists(this.configPath);
760
596
  }
761
597
  load() {
762
- if (this.lockData) return this.lockData;
763
- if (!this.exists()) {
764
- this.lockData = {
765
- lockfileVersion: LOCKFILE_VERSION,
766
- skills: {}
767
- };
768
- return this.lockData;
769
- }
598
+ if (this.config) return this.config;
599
+ if (!this.exists()) throw new Error(`skills.json not found in ${this.projectRoot}. Run 'reskill init' first.`);
770
600
  try {
771
- this.lockData = readJson(this.lockPath);
772
- return this.lockData;
601
+ this.config = readJson(this.configPath);
602
+ return this.config;
773
603
  } catch (error) {
774
- throw new Error(`Failed to parse skills.lock: ${error.message}`);
604
+ throw new Error(`Failed to parse skills.json: ${error.message}`);
775
605
  }
776
606
  }
777
607
  reload() {
778
- this.lockData = null;
608
+ this.config = null;
779
609
  return this.load();
780
610
  }
781
- save(lockToSave) {
782
- const toSave = lockToSave || this.lockData;
783
- if (!toSave) throw new Error('No lock to save');
784
- writeJson(this.lockPath, toSave);
785
- this.lockData = toSave;
611
+ save(config) {
612
+ const toSave = config || this.config;
613
+ if (!toSave) throw new Error('No config to save');
614
+ writeJson(this.configPath, toSave);
615
+ this.config = toSave;
786
616
  }
787
- get(name) {
788
- const lock = this.load();
789
- return lock.skills[name];
617
+ create(options) {
618
+ const config = {
619
+ ...DEFAULT_SKILLS_JSON,
620
+ ...options,
621
+ skills: options?.skills || {},
622
+ defaults: {
623
+ ...DEFAULT_SKILLS_JSON.defaults,
624
+ ...options?.defaults
625
+ }
626
+ };
627
+ this.save(config);
628
+ return config;
790
629
  }
791
- set(name, skill) {
792
- const lock = this.load();
793
- lock.skills[name] = skill;
630
+ getDefaults() {
631
+ const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
632
+ return {
633
+ registry: config.defaults?.registry || 'github',
634
+ installDir: config.defaults?.installDir || '.skills',
635
+ targetAgents: config.defaults?.targetAgents || [],
636
+ installMode: config.defaults?.installMode || 'symlink'
637
+ };
638
+ }
639
+ getRegistryUrl(registryName) {
640
+ const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
641
+ if (config.registries?.[registryName]) return config.registries[registryName];
642
+ if (DEFAULT_REGISTRIES[registryName]) return DEFAULT_REGISTRIES[registryName];
643
+ return `https://${registryName}`;
644
+ }
645
+ getInstallDir() {
646
+ const defaults = this.getDefaults();
647
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, defaults.installDir);
648
+ }
649
+ addSkill(name, ref) {
650
+ if (!this.config) this.load();
651
+ if (this.config) this.config.skills[name] = ref;
794
652
  this.save();
795
653
  }
796
- remove(name) {
797
- const lock = this.load();
798
- if (lock.skills[name]) {
799
- delete lock.skills[name];
654
+ removeSkill(name) {
655
+ if (!this.config) this.load();
656
+ if (this.config?.skills[name]) {
657
+ delete this.config.skills[name];
800
658
  this.save();
801
659
  return true;
802
660
  }
803
661
  return false;
804
662
  }
805
- lockSkill(name, options) {
806
- const lockedSkill = {
807
- source: options.source,
808
- version: options.version,
809
- resolved: options.resolved,
810
- commit: options.commit,
811
- installedAt: new Date().toISOString()
663
+ getSkills() {
664
+ if (!this.config) {
665
+ if (!this.exists()) return {};
666
+ this.load();
667
+ }
668
+ return {
669
+ ...this.config?.skills
812
670
  };
813
- this.set(name, lockedSkill);
814
- return lockedSkill;
815
671
  }
816
- getAll() {
817
- const lock = this.load();
672
+ hasSkill(name) {
673
+ const skills = this.getSkills();
674
+ return name in skills;
675
+ }
676
+ getSkillRef(name) {
677
+ const skills = this.getSkills();
678
+ return skills[name];
679
+ }
680
+ }
681
+ class GitResolver {
682
+ defaultRegistry;
683
+ constructor(defaultRegistry = 'github'){
684
+ this.defaultRegistry = defaultRegistry;
685
+ }
686
+ parseRef(ref) {
687
+ const raw = ref;
688
+ if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
689
+ let remaining = ref;
690
+ let registry = this.defaultRegistry;
691
+ let version;
692
+ const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
693
+ if (registryMatch) {
694
+ registry = registryMatch[1];
695
+ remaining = registryMatch[2];
696
+ }
697
+ const atIndex = remaining.lastIndexOf('@');
698
+ if (atIndex > 0) {
699
+ version = remaining.slice(atIndex + 1);
700
+ remaining = remaining.slice(0, atIndex);
701
+ }
702
+ const parts = remaining.split('/');
703
+ if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
704
+ const owner = parts[0];
705
+ const repo = parts[1];
706
+ const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
818
707
  return {
819
- ...lock.skills
708
+ registry,
709
+ owner,
710
+ repo,
711
+ subPath,
712
+ version,
713
+ raw
820
714
  };
821
715
  }
822
- has(name) {
823
- const lock = this.load();
824
- return name in lock.skills;
825
- }
826
- isVersionMatch(name, version) {
827
- const locked = this.get(name);
828
- if (!locked) return false;
829
- return locked.version === version;
716
+ parseGitUrlRef(ref) {
717
+ const raw = ref;
718
+ let gitUrl = ref;
719
+ let version;
720
+ let subPath;
721
+ const gitSuffixIndex = ref.indexOf('.git');
722
+ if (-1 !== gitSuffixIndex) {
723
+ const afterGit = ref.slice(gitSuffixIndex + 4);
724
+ if (afterGit) {
725
+ const atIndex = afterGit.lastIndexOf('@');
726
+ if (-1 !== atIndex) {
727
+ version = afterGit.slice(atIndex + 1);
728
+ const pathPart = afterGit.slice(0, atIndex);
729
+ if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
730
+ } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
731
+ gitUrl = ref.slice(0, gitSuffixIndex + 4);
732
+ }
733
+ } else {
734
+ const atIndex = ref.lastIndexOf('@');
735
+ if (atIndex > 4) {
736
+ version = ref.slice(atIndex + 1);
737
+ gitUrl = ref.slice(0, atIndex);
738
+ }
739
+ }
740
+ const parsed = parseGitUrl(gitUrl);
741
+ if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
742
+ return {
743
+ registry: parsed.host,
744
+ owner: parsed.owner,
745
+ repo: parsed.repo,
746
+ subPath,
747
+ version,
748
+ raw,
749
+ gitUrl
750
+ };
830
751
  }
831
- clear() {
832
- this.lockData = {
833
- lockfileVersion: LOCKFILE_VERSION,
834
- skills: {}
752
+ parseVersion(versionSpec) {
753
+ if (!versionSpec) return {
754
+ type: 'branch',
755
+ value: 'main',
756
+ raw: ''
757
+ };
758
+ const raw = versionSpec;
759
+ if ('latest' === versionSpec) return {
760
+ type: 'latest',
761
+ value: 'latest',
762
+ raw
763
+ };
764
+ if (versionSpec.startsWith('branch:')) return {
765
+ type: 'branch',
766
+ value: versionSpec.slice(7),
767
+ raw
768
+ };
769
+ if (versionSpec.startsWith('commit:')) return {
770
+ type: 'commit',
771
+ value: versionSpec.slice(7),
772
+ raw
773
+ };
774
+ if (/^[\^~><]/.test(versionSpec)) return {
775
+ type: 'range',
776
+ value: versionSpec,
777
+ raw
778
+ };
779
+ return {
780
+ type: 'exact',
781
+ value: versionSpec,
782
+ raw
835
783
  };
836
- this.save();
837
784
  }
838
- delete() {
839
- if (this.exists()) {
840
- const fs = __webpack_require__("node:fs");
841
- fs.unlinkSync(this.lockPath);
785
+ buildRepoUrl(parsed) {
786
+ if (parsed.gitUrl) return parsed.gitUrl;
787
+ return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
788
+ }
789
+ async resolveVersion(repoUrl, versionSpec) {
790
+ switch(versionSpec.type){
791
+ case 'exact':
792
+ return {
793
+ ref: versionSpec.value
794
+ };
795
+ case 'latest':
796
+ {
797
+ const latestTag = await getLatestTag(repoUrl);
798
+ if (!latestTag) {
799
+ const defaultBranch = await getDefaultBranch(repoUrl);
800
+ return {
801
+ ref: defaultBranch
802
+ };
803
+ }
804
+ return {
805
+ ref: latestTag.name,
806
+ commit: latestTag.commit
807
+ };
808
+ }
809
+ case 'range':
810
+ {
811
+ const tags = await getRemoteTags(repoUrl);
812
+ const matchingTags = tags.filter((tag)=>{
813
+ const version = tag.name.replace(/^v/, '');
814
+ return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
815
+ });
816
+ if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
817
+ matchingTags.sort((a, b)=>{
818
+ const aVer = a.name.replace(/^v/, '');
819
+ const bVer = b.name.replace(/^v/, '');
820
+ return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
821
+ });
822
+ return {
823
+ ref: matchingTags[0].name,
824
+ commit: matchingTags[0].commit
825
+ };
826
+ }
827
+ case 'branch':
828
+ return {
829
+ ref: versionSpec.value
830
+ };
831
+ case 'commit':
832
+ return {
833
+ ref: versionSpec.value,
834
+ commit: versionSpec.value
835
+ };
836
+ default:
837
+ throw new Error(`Unknown version type: ${versionSpec.type}`);
842
838
  }
843
- this.lockData = null;
844
839
  }
845
- }
846
- const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)();
847
- const agents = {
848
- amp: {
849
- name: 'amp',
850
- displayName: 'Amp',
851
- skillsDir: '.agents/skills',
852
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/agents/skills'),
853
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/amp'))
854
- },
855
- antigravity: {
856
- name: 'antigravity',
857
- displayName: 'Antigravity',
858
- skillsDir: '.agent/skills',
859
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
860
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.agent')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity'))
861
- },
862
- 'claude-code': {
863
- name: 'claude-code',
864
- displayName: 'Claude Code',
865
- skillsDir: '.claude/skills',
866
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'),
867
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude'))
868
- },
869
- clawdbot: {
870
- name: 'clawdbot',
871
- displayName: 'Clawdbot',
872
- skillsDir: 'skills',
873
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot/skills'),
874
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot'))
875
- },
876
- codex: {
877
- name: 'codex',
878
- displayName: 'Codex',
879
- skillsDir: '.codex/skills',
880
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex/skills'),
881
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex'))
882
- },
883
- cursor: {
884
- name: 'cursor',
885
- displayName: 'Cursor',
886
- skillsDir: '.cursor/skills',
887
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor/skills'),
888
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor'))
889
- },
890
- droid: {
891
- name: 'droid',
892
- displayName: 'Droid',
893
- skillsDir: '.factory/skills',
894
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'),
895
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'))
896
- },
897
- 'gemini-cli': {
898
- name: 'gemini-cli',
899
- displayName: 'Gemini CLI',
900
- skillsDir: '.gemini/skills',
901
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/skills'),
902
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini'))
903
- },
904
- 'github-copilot': {
905
- name: 'github-copilot',
906
- displayName: 'GitHub Copilot',
907
- skillsDir: '.github/skills',
908
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot/skills'),
909
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.github')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot'))
910
- },
911
- goose: {
912
- name: 'goose',
913
- displayName: 'Goose',
914
- skillsDir: '.goose/skills',
915
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose/skills'),
916
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose'))
917
- },
918
- kilo: {
919
- name: 'kilo',
920
- displayName: 'Kilo Code',
921
- skillsDir: '.kilocode/skills',
922
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode/skills'),
923
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode'))
924
- },
925
- 'kiro-cli': {
926
- name: 'kiro-cli',
927
- displayName: 'Kiro CLI',
928
- skillsDir: '.kiro/skills',
929
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro/skills'),
930
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro'))
931
- },
932
- opencode: {
933
- name: 'opencode',
934
- displayName: 'OpenCode',
935
- skillsDir: '.opencode/skills',
936
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode/skills'),
937
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'))
938
- },
939
- roo: {
940
- name: 'roo',
941
- displayName: 'Roo Code',
942
- skillsDir: '.roo/skills',
943
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo/skills'),
944
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo'))
945
- },
946
- trae: {
947
- name: 'trae',
948
- displayName: 'Trae',
949
- skillsDir: '.trae/skills',
950
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae/skills'),
951
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae'))
952
- },
953
- windsurf: {
954
- name: 'windsurf',
955
- displayName: 'Windsurf',
956
- skillsDir: '.windsurf/skills',
957
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
958
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf'))
959
- },
960
- neovate: {
961
- name: 'neovate',
962
- displayName: 'Neovate',
963
- skillsDir: '.neovate/skills',
964
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate/skills'),
965
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate'))
840
+ async resolve(ref) {
841
+ const parsed = this.parseRef(ref);
842
+ const repoUrl = this.buildRepoUrl(parsed);
843
+ const versionSpec = this.parseVersion(parsed.version);
844
+ const resolved = await this.resolveVersion(repoUrl, versionSpec);
845
+ return {
846
+ parsed,
847
+ repoUrl,
848
+ ref: resolved.ref,
849
+ commit: resolved.commit
850
+ };
966
851
  }
967
- };
968
- async function detectInstalledAgents() {
969
- const installed = [];
970
- for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
971
- return installed;
972
- }
973
- function getAgentConfig(type) {
974
- return agents[type];
975
- }
976
- function isValidAgentType(type) {
977
- return type in agents;
978
852
  }
979
853
  const installer_AGENTS_DIR = '.agents';
980
854
  const installer_SKILLS_SUBDIR = 'skills';
@@ -992,7 +866,7 @@ function installer_isPathSafe(basePath, targetPath) {
992
866
  return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
993
867
  }
994
868
  function installer_getCanonicalSkillsDir(isGlobal, cwd) {
995
- const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)() : cwd || process.cwd();
869
+ const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
996
870
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
997
871
  }
998
872
  function installer_ensureDir(dirPath) {
@@ -1046,7 +920,7 @@ async function installer_createSymlink(target, linkPath) {
1046
920
  const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
1047
921
  installer_ensureDir(linkDir);
1048
922
  const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
1049
- const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_os__.platform)() ? 'junction' : void 0;
923
+ const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
1050
924
  external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
1051
925
  return true;
1052
926
  } catch {
@@ -1135,38 +1009,138 @@ class Installer {
1135
1009
  };
1136
1010
  }
1137
1011
  }
1138
- async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
1139
- const results = new Map();
1140
- for (const agent of targetAgents){
1141
- const result = await this.installForAgent(sourcePath, skillName, agent, options);
1142
- results.set(agent, result);
1012
+ async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
1013
+ const results = new Map();
1014
+ for (const agent of targetAgents){
1015
+ const result = await this.installForAgent(sourcePath, skillName, agent, options);
1016
+ results.set(agent, result);
1017
+ }
1018
+ return results;
1019
+ }
1020
+ isInstalled(skillName, agentType) {
1021
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1022
+ return external_node_fs_.existsSync(skillPath);
1023
+ }
1024
+ uninstallFromAgent(skillName, agentType) {
1025
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1026
+ if (!external_node_fs_.existsSync(skillPath)) return false;
1027
+ installer_remove(skillPath);
1028
+ return true;
1029
+ }
1030
+ uninstallFromAgents(skillName, targetAgents) {
1031
+ const results = new Map();
1032
+ for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
1033
+ const canonicalPath = this.getCanonicalPath(skillName);
1034
+ if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
1035
+ return results;
1036
+ }
1037
+ listInstalledSkills(agentType) {
1038
+ const agent = getAgentConfig(agentType);
1039
+ const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1040
+ if (!external_node_fs_.existsSync(skillsDir)) return [];
1041
+ return external_node_fs_.readdirSync(skillsDir, {
1042
+ withFileTypes: true
1043
+ }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1044
+ }
1045
+ }
1046
+ const LOCKFILE_VERSION = 1;
1047
+ class LockManager {
1048
+ projectRoot;
1049
+ lockPath;
1050
+ lockData = null;
1051
+ constructor(projectRoot){
1052
+ this.projectRoot = projectRoot || process.cwd();
1053
+ this.lockPath = getSkillsLockPath(this.projectRoot);
1054
+ }
1055
+ getLockPath() {
1056
+ return this.lockPath;
1057
+ }
1058
+ exists() {
1059
+ return exists(this.lockPath);
1060
+ }
1061
+ load() {
1062
+ if (this.lockData) return this.lockData;
1063
+ if (!this.exists()) {
1064
+ this.lockData = {
1065
+ lockfileVersion: LOCKFILE_VERSION,
1066
+ skills: {}
1067
+ };
1068
+ return this.lockData;
1069
+ }
1070
+ try {
1071
+ this.lockData = readJson(this.lockPath);
1072
+ return this.lockData;
1073
+ } catch (error) {
1074
+ throw new Error(`Failed to parse skills.lock: ${error.message}`);
1075
+ }
1076
+ }
1077
+ reload() {
1078
+ this.lockData = null;
1079
+ return this.load();
1080
+ }
1081
+ save(lockToSave) {
1082
+ const toSave = lockToSave || this.lockData;
1083
+ if (!toSave) throw new Error('No lock to save');
1084
+ writeJson(this.lockPath, toSave);
1085
+ this.lockData = toSave;
1086
+ }
1087
+ get(name) {
1088
+ const lock = this.load();
1089
+ return lock.skills[name];
1090
+ }
1091
+ set(name, skill) {
1092
+ const lock = this.load();
1093
+ lock.skills[name] = skill;
1094
+ this.save();
1095
+ }
1096
+ remove(name) {
1097
+ const lock = this.load();
1098
+ if (lock.skills[name]) {
1099
+ delete lock.skills[name];
1100
+ this.save();
1101
+ return true;
1143
1102
  }
1144
- return results;
1103
+ return false;
1145
1104
  }
1146
- isInstalled(skillName, agentType) {
1147
- const skillPath = this.getAgentSkillPath(skillName, agentType);
1148
- return external_node_fs_.existsSync(skillPath);
1105
+ lockSkill(name, options) {
1106
+ const lockedSkill = {
1107
+ source: options.source,
1108
+ version: options.version,
1109
+ resolved: options.resolved,
1110
+ commit: options.commit,
1111
+ installedAt: new Date().toISOString()
1112
+ };
1113
+ this.set(name, lockedSkill);
1114
+ return lockedSkill;
1149
1115
  }
1150
- uninstallFromAgent(skillName, agentType) {
1151
- const skillPath = this.getAgentSkillPath(skillName, agentType);
1152
- if (!external_node_fs_.existsSync(skillPath)) return false;
1153
- installer_remove(skillPath);
1154
- return true;
1116
+ getAll() {
1117
+ const lock = this.load();
1118
+ return {
1119
+ ...lock.skills
1120
+ };
1155
1121
  }
1156
- uninstallFromAgents(skillName, targetAgents) {
1157
- const results = new Map();
1158
- for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
1159
- const canonicalPath = this.getCanonicalPath(skillName);
1160
- if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
1161
- return results;
1122
+ has(name) {
1123
+ const lock = this.load();
1124
+ return name in lock.skills;
1162
1125
  }
1163
- listInstalledSkills(agentType) {
1164
- const agent = getAgentConfig(agentType);
1165
- const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1166
- if (!external_node_fs_.existsSync(skillsDir)) return [];
1167
- return external_node_fs_.readdirSync(skillsDir, {
1168
- withFileTypes: true
1169
- }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1126
+ isVersionMatch(name, version) {
1127
+ const locked = this.get(name);
1128
+ if (!locked) return false;
1129
+ return locked.version === version;
1130
+ }
1131
+ clear() {
1132
+ this.lockData = {
1133
+ lockfileVersion: LOCKFILE_VERSION,
1134
+ skills: {}
1135
+ };
1136
+ this.save();
1137
+ }
1138
+ delete() {
1139
+ if (this.exists()) {
1140
+ const fs = __webpack_require__("node:fs");
1141
+ fs.unlinkSync(this.lockPath);
1142
+ }
1143
+ this.lockData = null;
1170
1144
  }
1171
1145
  }
1172
1146
  class SkillManager {
@@ -1195,8 +1169,17 @@ class SkillManager {
1195
1169
  if (this.isGlobal) return getGlobalSkillsDir();
1196
1170
  return this.config.getInstallDir();
1197
1171
  }
1172
+ getCanonicalSkillsDir() {
1173
+ const home = process.env.HOME || process.env.USERPROFILE || '';
1174
+ const baseDir = this.isGlobal ? home : this.projectRoot;
1175
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, '.agents', 'skills');
1176
+ }
1198
1177
  getSkillPath(name) {
1199
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1178
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1179
+ if (exists(canonicalPath)) return canonicalPath;
1180
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1181
+ if (exists(legacyPath)) return legacyPath;
1182
+ return canonicalPath;
1200
1183
  }
1201
1184
  async install(ref, options = {}) {
1202
1185
  const { force = false, save = true } = options;
@@ -1209,11 +1192,13 @@ class SkillManager {
1209
1192
  const locked = this.lockManager.get(skillName);
1210
1193
  if (locked && locked.version === version) {
1211
1194
  logger.info(`${skillName}@${version} is already installed`);
1212
- return this.getInstalledSkill(skillName);
1195
+ const installed = this.getInstalledSkill(skillName);
1196
+ if (installed) return installed;
1213
1197
  }
1214
1198
  if (!force) {
1215
1199
  logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
1216
- return this.getInstalledSkill(skillName);
1200
+ const installed = this.getInstalledSkill(skillName);
1201
+ if (installed) return installed;
1217
1202
  }
1218
1203
  }
1219
1204
  logger["package"](`Installing ${skillName}@${version}...`);
@@ -1227,7 +1212,7 @@ class SkillManager {
1227
1212
  if (exists(skillPath)) remove(skillPath);
1228
1213
  await this.cache.copyTo(parsed, version, skillPath);
1229
1214
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1230
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1215
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1231
1216
  version,
1232
1217
  resolved: repoUrl,
1233
1218
  commit: cacheResult.commit
@@ -1235,7 +1220,9 @@ class SkillManager {
1235
1220
  if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1236
1221
  const locationHint = this.isGlobal ? '(global)' : '';
1237
1222
  logger.success(`Installed ${skillName}@${version} to ${skillPath} ${locationHint}`.trim());
1238
- return this.getInstalledSkill(skillName);
1223
+ const installed = this.getInstalledSkill(skillName);
1224
+ if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
1225
+ return installed;
1239
1226
  }
1240
1227
  async installAll(options = {}) {
1241
1228
  const skills = this.config.getSkills();
@@ -1302,7 +1289,7 @@ class SkillManager {
1302
1289
  skillName = name || skillJson.name || skillName;
1303
1290
  } catch {}
1304
1291
  const linkPath = this.getSkillPath(skillName);
1305
- ensureDir(this.getInstallDir());
1292
+ ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
1306
1293
  createSymlink(absolutePath, linkPath);
1307
1294
  logger.success(`Linked ${skillName} → ${absolutePath}`);
1308
1295
  return {
@@ -1328,20 +1315,36 @@ class SkillManager {
1328
1315
  return true;
1329
1316
  }
1330
1317
  list() {
1331
- const installDir = this.getInstallDir();
1332
- if (!exists(installDir)) return [];
1333
1318
  const skills = [];
1334
- const dirs = listDir(installDir);
1335
- for (const name of dirs){
1336
- const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(installDir, name);
1319
+ const seenNames = new Set();
1320
+ const canonicalDir = this.getCanonicalSkillsDir();
1321
+ if (exists(canonicalDir)) for (const name of listDir(canonicalDir)){
1322
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalDir, name);
1337
1323
  if (!isDirectory(skillPath)) continue;
1338
- const skill = this.getInstalledSkill(name);
1339
- if (skill) skills.push(skill);
1324
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1325
+ if (skill) {
1326
+ skills.push(skill);
1327
+ seenNames.add(name);
1328
+ }
1329
+ }
1330
+ const legacyDir = this.getInstallDir();
1331
+ if (exists(legacyDir) && legacyDir !== canonicalDir) for (const name of listDir(legacyDir)){
1332
+ if (seenNames.has(name)) continue;
1333
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(legacyDir, name);
1334
+ if (!isDirectory(skillPath)) continue;
1335
+ if (isSymlink(skillPath)) try {
1336
+ const realPath = getRealPath(skillPath);
1337
+ if (realPath.includes(__WEBPACK_EXTERNAL_MODULE_node_path__.join('.agents', 'skills'))) continue;
1338
+ } catch {}
1339
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1340
+ if (skill) {
1341
+ skills.push(skill);
1342
+ seenNames.add(name);
1343
+ }
1340
1344
  }
1341
1345
  return skills;
1342
1346
  }
1343
- getInstalledSkill(name) {
1344
- const skillPath = this.getSkillPath(name);
1347
+ getInstalledSkillFromPath(name, skillPath) {
1345
1348
  if (!exists(skillPath)) return null;
1346
1349
  const isLinked = isSymlink(skillPath);
1347
1350
  const locked = this.lockManager.get(name);
@@ -1359,6 +1362,13 @@ class SkillManager {
1359
1362
  isLinked
1360
1363
  };
1361
1364
  }
1365
+ getInstalledSkill(name) {
1366
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1367
+ if (exists(canonicalPath)) return this.getInstalledSkillFromPath(name, canonicalPath);
1368
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1369
+ if (exists(legacyPath)) return this.getInstalledSkillFromPath(name, legacyPath);
1370
+ return null;
1371
+ }
1362
1372
  getInfo(name) {
1363
1373
  return {
1364
1374
  installed: this.getInstalledSkill(name),
@@ -1420,7 +1430,7 @@ class SkillManager {
1420
1430
  mode: mode
1421
1431
  });
1422
1432
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1423
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1433
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1424
1434
  version,
1425
1435
  resolved: repoUrl,
1426
1436
  commit: cacheResult.commit
@@ -1434,7 +1444,7 @@ class SkillManager {
1434
1444
  name: skillName,
1435
1445
  path: sourcePath,
1436
1446
  version,
1437
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`
1447
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
1438
1448
  };
1439
1449
  return {
1440
1450
  skill,
@@ -1477,6 +1487,69 @@ class SkillManager {
1477
1487
  return results;
1478
1488
  }
1479
1489
  }
1490
+ const infoCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('info').description('Show skill details').argument('<skill>', 'Skill name').option('-j, --json', 'Output as JSON').action((skillName, options)=>{
1491
+ const skillManager = new SkillManager();
1492
+ const info = skillManager.getInfo(skillName);
1493
+ if (options.json) {
1494
+ console.log(JSON.stringify(info, null, 2));
1495
+ return;
1496
+ }
1497
+ if (!info.installed && !info.config) {
1498
+ logger.error(`Skill ${skillName} not found`);
1499
+ process.exit(1);
1500
+ }
1501
+ logger.log(`Skill: ${skillName}`);
1502
+ logger.newline();
1503
+ if (info.config) {
1504
+ logger.log("Configuration (skills.json):");
1505
+ logger.log(` Reference: ${info.config}`);
1506
+ }
1507
+ if (info.locked) {
1508
+ logger.log("Locked Version (skills.lock):");
1509
+ logger.log(` Version: ${info.locked.version}`);
1510
+ logger.log(` Source: ${info.locked.source}`);
1511
+ logger.log(` Commit: ${info.locked.commit}`);
1512
+ logger.log(` Installed: ${info.locked.installedAt}`);
1513
+ }
1514
+ if (info.installed) {
1515
+ logger.log("Installed:");
1516
+ logger.log(` Path: ${info.installed.path}`);
1517
+ logger.log(` Version: ${info.installed.version}`);
1518
+ logger.log(` Linked: ${info.installed.isLinked ? 'Yes' : 'No'}`);
1519
+ if (info.installed.metadata) {
1520
+ const meta = info.installed.metadata;
1521
+ logger.log("Metadata (skill.json):");
1522
+ if (meta.description) logger.log(` Description: ${meta.description}`);
1523
+ if (meta.author) logger.log(` Author: ${meta.author}`);
1524
+ if (meta.license) logger.log(` License: ${meta.license}`);
1525
+ if (meta.keywords?.length) logger.log(` Keywords: ${meta.keywords.join(', ')}`);
1526
+ }
1527
+ } else logger.warn(`Skill ${skillName} is not installed`);
1528
+ });
1529
+ const initCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('init').description('Initialize a new skills.json configuration').option('-n, --name <name>', 'Project name').option('-r, --registry <registry>', 'Default registry', 'github').option('-d, --install-dir <dir>', 'Skills installation directory', '.skills').option('-y, --yes', 'Skip prompts and use defaults').action(async (options)=>{
1530
+ const configLoader = new ConfigLoader();
1531
+ if (configLoader.exists()) {
1532
+ logger.warn('skills.json already exists');
1533
+ return;
1534
+ }
1535
+ const config = configLoader.create({
1536
+ name: options.name,
1537
+ defaults: {
1538
+ registry: options.registry,
1539
+ installDir: options.installDir
1540
+ }
1541
+ });
1542
+ logger.success('Created skills.json');
1543
+ logger.newline();
1544
+ logger.log('Configuration:');
1545
+ logger.log(` Name: ${config.name || '(not set)'}`);
1546
+ logger.log(` Default registry: ${config.defaults?.registry}`);
1547
+ logger.log(` Install directory: ${config.defaults?.installDir}`);
1548
+ logger.newline();
1549
+ logger.log('Next steps:');
1550
+ logger.log(' reskill install <skill> Install a skill');
1551
+ logger.log(' reskill list List installed skills');
1552
+ });
1480
1553
  function formatAgentNames(agentTypes, maxShow = 5) {
1481
1554
  const names = agentTypes.map((a)=>agents[a].displayName);
1482
1555
  if (names.length <= maxShow) return names.join(', ');
@@ -1721,6 +1794,23 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
1721
1794
  process.exit(1);
1722
1795
  }
1723
1796
  });
1797
+ const linkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('link').description('Link a local skill for development').argument('<path>', 'Path to local skill directory').option('-n, --name <name>', 'Custom skill name').action((localPath, options)=>{
1798
+ const skillManager = new SkillManager();
1799
+ try {
1800
+ const linked = skillManager.link(localPath, options.name);
1801
+ logger.log(`Linked skill available at: ${linked.path}`);
1802
+ } catch (error) {
1803
+ logger.error(error.message);
1804
+ process.exit(1);
1805
+ }
1806
+ });
1807
+ const unlinkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unlink').description('Unlink a linked skill').argument('<skill>', 'Skill name to unlink').action((skillName)=>{
1808
+ const skillManager = new SkillManager();
1809
+ const result = skillManager.unlink(skillName);
1810
+ if (!result) process.exit(1);
1811
+ });
1812
+ const linkCommand = linkCmd;
1813
+ const unlinkCommand = unlinkCmd;
1724
1814
  const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').alias('ls').description('List installed skills').option('-j, --json', 'Output as JSON').option('-g, --global', 'List globally installed skills').action((options)=>{
1725
1815
  const isGlobal = options.global || false;
1726
1816
  const skillManager = new SkillManager(void 0, {
@@ -1753,68 +1843,6 @@ const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').al
1753
1843
  logger.newline();
1754
1844
  logger.log(`Total: ${skills.length} skill(s)`);
1755
1845
  });
1756
- const infoCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('info').description('Show skill details').argument('<skill>', 'Skill name').option('-j, --json', 'Output as JSON').action((skillName, options)=>{
1757
- const skillManager = new SkillManager();
1758
- const info = skillManager.getInfo(skillName);
1759
- if (options.json) {
1760
- console.log(JSON.stringify(info, null, 2));
1761
- return;
1762
- }
1763
- if (!info.installed && !info.config) {
1764
- logger.error(`Skill ${skillName} not found`);
1765
- process.exit(1);
1766
- }
1767
- logger.log(`Skill: ${skillName}`);
1768
- logger.newline();
1769
- if (info.config) {
1770
- logger.log("Configuration (skills.json):");
1771
- logger.log(` Reference: ${info.config}`);
1772
- }
1773
- if (info.locked) {
1774
- logger.log("Locked Version (skills.lock):");
1775
- logger.log(` Version: ${info.locked.version}`);
1776
- logger.log(` Source: ${info.locked.source}`);
1777
- logger.log(` Commit: ${info.locked.commit}`);
1778
- logger.log(` Installed: ${info.locked.installedAt}`);
1779
- }
1780
- if (info.installed) {
1781
- logger.log("Installed:");
1782
- logger.log(` Path: ${info.installed.path}`);
1783
- logger.log(` Version: ${info.installed.version}`);
1784
- logger.log(` Linked: ${info.installed.isLinked ? 'Yes' : 'No'}`);
1785
- if (info.installed.metadata) {
1786
- const meta = info.installed.metadata;
1787
- logger.log("Metadata (skill.json):");
1788
- if (meta.description) logger.log(` Description: ${meta.description}`);
1789
- if (meta.author) logger.log(` Author: ${meta.author}`);
1790
- if (meta.license) logger.log(` License: ${meta.license}`);
1791
- if (meta.keywords?.length) logger.log(` Keywords: ${meta.keywords.join(', ')}`);
1792
- }
1793
- } else logger.warn(`Skill ${skillName} is not installed`);
1794
- });
1795
- const updateCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('update').alias('up').description('Update installed skills').argument('[skill]', 'Skill name to update (updates all if not specified)').action(async (skill)=>{
1796
- const configLoader = new ConfigLoader();
1797
- if (!configLoader.exists()) {
1798
- logger.error("skills.json not found. Run 'reskill init' first.");
1799
- process.exit(1);
1800
- }
1801
- const skillManager = new SkillManager();
1802
- const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(skill ? `Updating ${skill}...` : 'Updating all skills...').start();
1803
- try {
1804
- const updated = await skillManager.update(skill);
1805
- spinner.stop();
1806
- if (0 === updated.length) {
1807
- logger.info('No skills to update');
1808
- return;
1809
- }
1810
- logger.success(`Updated ${updated.length} skill(s):`);
1811
- for (const s of updated)logger.log(` - ${s.name}@${s.version}`);
1812
- } catch (error) {
1813
- spinner.fail('Update failed');
1814
- logger.error(error.message);
1815
- process.exit(1);
1816
- }
1817
- });
1818
1846
  const outdatedCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('outdated').description('Check for outdated skills').option('-j, --json', 'Output as JSON').action(async (options)=>{
1819
1847
  const configLoader = new ConfigLoader();
1820
1848
  if (!configLoader.exists()) {
@@ -1874,23 +1902,29 @@ const uninstallCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unin
1874
1902
  const result = skillManager.uninstall(skillName);
1875
1903
  if (!result) process.exit(1);
1876
1904
  });
1877
- const linkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('link').description('Link a local skill for development').argument('<path>', 'Path to local skill directory').option('-n, --name <name>', 'Custom skill name').action((localPath, options)=>{
1905
+ const updateCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('update').alias('up').description('Update installed skills').argument('[skill]', 'Skill name to update (updates all if not specified)').action(async (skill)=>{
1906
+ const configLoader = new ConfigLoader();
1907
+ if (!configLoader.exists()) {
1908
+ logger.error("skills.json not found. Run 'reskill init' first.");
1909
+ process.exit(1);
1910
+ }
1878
1911
  const skillManager = new SkillManager();
1912
+ const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(skill ? `Updating ${skill}...` : 'Updating all skills...').start();
1879
1913
  try {
1880
- const linked = skillManager.link(localPath, options.name);
1881
- logger.log(`Linked skill available at: ${linked.path}`);
1914
+ const updated = await skillManager.update(skill);
1915
+ spinner.stop();
1916
+ if (0 === updated.length) {
1917
+ logger.info('No skills to update');
1918
+ return;
1919
+ }
1920
+ logger.success(`Updated ${updated.length} skill(s):`);
1921
+ for (const s of updated)logger.log(` - ${s.name}@${s.version}`);
1882
1922
  } catch (error) {
1923
+ spinner.fail('Update failed');
1883
1924
  logger.error(error.message);
1884
1925
  process.exit(1);
1885
1926
  }
1886
1927
  });
1887
- const unlinkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unlink').description('Unlink a linked skill').argument('<skill>', 'Skill name to unlink').action((skillName)=>{
1888
- const skillManager = new SkillManager();
1889
- const result = skillManager.unlink(skillName);
1890
- if (!result) process.exit(1);
1891
- });
1892
- const linkCommand = linkCmd;
1893
- const unlinkCommand = unlinkCmd;
1894
1928
  const program = new __WEBPACK_EXTERNAL_MODULE_commander__.Command();
1895
1929
  program.name('reskill').description('AI Skills Package Manager - Git-based skills management for AI agents').version('0.1.0');
1896
1930
  program.addCommand(initCommand);