reskill 0.11.0 → 0.12.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 (43) hide show
  1. package/README.md +106 -20
  2. package/README.zh-CN.md +106 -20
  3. package/dist/cli/commands/index.d.ts +3 -3
  4. package/dist/cli/commands/index.d.ts.map +1 -1
  5. package/dist/cli/commands/info.d.ts +1 -1
  6. package/dist/cli/commands/init.d.ts +1 -1
  7. package/dist/cli/commands/install.d.ts +11 -11
  8. package/dist/cli/commands/install.d.ts.map +1 -1
  9. package/dist/cli/commands/list.d.ts +1 -1
  10. package/dist/cli/commands/list.d.ts.map +1 -1
  11. package/dist/cli/commands/outdated.d.ts +1 -1
  12. package/dist/cli/commands/outdated.d.ts.map +1 -1
  13. package/dist/cli/commands/uninstall.d.ts +1 -1
  14. package/dist/cli/commands/update.d.ts +1 -1
  15. package/dist/cli/index.js +700 -642
  16. package/dist/core/agent-registry.d.ts +16 -16
  17. package/dist/core/agent-registry.d.ts.map +1 -1
  18. package/dist/core/cache-manager.d.ts +17 -17
  19. package/dist/core/cache-manager.d.ts.map +1 -1
  20. package/dist/core/config-loader.d.ts +24 -18
  21. package/dist/core/config-loader.d.ts.map +1 -1
  22. package/dist/core/git-resolver.d.ts +23 -23
  23. package/dist/core/git-resolver.d.ts.map +1 -1
  24. package/dist/core/index.d.ts +8 -8
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/core/installer.d.ts +30 -30
  27. package/dist/core/installer.d.ts.map +1 -1
  28. package/dist/core/lock-manager.d.ts +17 -17
  29. package/dist/core/lock-manager.d.ts.map +1 -1
  30. package/dist/core/skill-manager.d.ts +57 -39
  31. package/dist/core/skill-manager.d.ts.map +1 -1
  32. package/dist/core/skill-parser.d.ts +43 -43
  33. package/dist/core/skill-parser.d.ts.map +1 -1
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +641 -583
  37. package/dist/types/index.d.ts +84 -84
  38. package/dist/types/index.d.ts.map +1 -1
  39. package/dist/utils/fs.d.ts +7 -7
  40. package/dist/utils/fs.d.ts.map +1 -1
  41. package/dist/utils/git.d.ts +5 -0
  42. package/dist/utils/git.d.ts.map +1 -1
  43. 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,49 +152,170 @@ 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;
296
291
  originalError;
297
292
  isAuthError;
293
+ urlType;
298
294
  constructor(repoUrl, originalError){
299
295
  const isAuthError = GitCloneError.isAuthenticationError(originalError.message);
296
+ const urlType = GitCloneError.detectUrlType(repoUrl);
300
297
  let message = `Failed to clone repository: ${repoUrl}`;
301
298
  if (isAuthError) {
302
- message += '\n\nTip: For private repos, ensure git SSH keys or credentials are configured:';
303
- message += '\n - SSH: Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
304
- message += '\n - HTTPS: Run \'git config --global credential.helper store\'';
305
- message += '\n - Or use a personal access token in the URL';
299
+ message += '\n\nTip: For private repos, ensure git credentials are configured:';
300
+ if ('ssh' === urlType) {
301
+ message += '\n - Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
302
+ message += '\n - Ensure SSH key is added to your Git hosting service';
303
+ } else {
304
+ message += "\n - Run 'git config --global credential.helper store'";
305
+ message += '\n - Or use a personal access token in the URL';
306
+ }
306
307
  }
307
308
  super(message);
308
309
  this.name = 'GitCloneError';
309
310
  this.repoUrl = repoUrl;
310
311
  this.originalError = originalError;
311
312
  this.isAuthError = isAuthError;
313
+ this.urlType = urlType;
314
+ }
315
+ static detectUrlType(url) {
316
+ if (url.startsWith('git@') || url.startsWith('ssh://')) return 'ssh';
317
+ if (url.startsWith('http://') || url.startsWith('https://')) return 'https';
318
+ return 'unknown';
312
319
  }
313
320
  static isAuthenticationError(message) {
314
321
  const authPatterns = [
@@ -460,182 +467,10 @@ function parseGitUrl(url) {
460
467
  }
461
468
  return null;
462
469
  }
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();
470
+ class CacheManager {
471
+ cacheDir;
472
+ constructor(cacheDir){
473
+ this.cacheDir = cacheDir || getCacheDir();
639
474
  }
640
475
  getCacheDir() {
641
476
  return this.cacheDir;
@@ -743,238 +578,294 @@ class CacheManager {
743
578
  };
744
579
  }
745
580
  }
746
- const LOCKFILE_VERSION = 1;
747
- class LockManager {
581
+ const DEFAULT_SKILLS_JSON = {
582
+ skills: {},
583
+ defaults: {
584
+ registry: 'github',
585
+ installDir: '.skills'
586
+ }
587
+ };
588
+ const DEFAULT_REGISTRIES = {
589
+ github: 'https://github.com',
590
+ gitlab: 'https://gitlab.com'
591
+ };
592
+ class ConfigLoader {
748
593
  projectRoot;
749
- lockPath;
750
- lockData = null;
594
+ configPath;
595
+ config = null;
751
596
  constructor(projectRoot){
752
597
  this.projectRoot = projectRoot || process.cwd();
753
- this.lockPath = getSkillsLockPath(this.projectRoot);
598
+ this.configPath = getSkillsJsonPath(this.projectRoot);
754
599
  }
755
- getLockPath() {
756
- return this.lockPath;
600
+ getProjectRoot() {
601
+ return this.projectRoot;
602
+ }
603
+ getConfigPath() {
604
+ return this.configPath;
757
605
  }
758
606
  exists() {
759
- return exists(this.lockPath);
607
+ return exists(this.configPath);
760
608
  }
761
609
  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
- }
610
+ if (this.config) return this.config;
611
+ if (!this.exists()) throw new Error(`skills.json not found in ${this.projectRoot}. Run 'reskill init' first.`);
770
612
  try {
771
- this.lockData = readJson(this.lockPath);
772
- return this.lockData;
613
+ this.config = readJson(this.configPath);
614
+ return this.config;
773
615
  } catch (error) {
774
- throw new Error(`Failed to parse skills.lock: ${error.message}`);
616
+ throw new Error(`Failed to parse skills.json: ${error.message}`);
775
617
  }
776
618
  }
777
619
  reload() {
778
- this.lockData = null;
620
+ this.config = null;
779
621
  return this.load();
780
622
  }
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;
623
+ save(config) {
624
+ const toSave = config || this.config;
625
+ if (!toSave) throw new Error('No config to save');
626
+ writeJson(this.configPath, toSave);
627
+ this.config = toSave;
786
628
  }
787
- get(name) {
788
- const lock = this.load();
789
- return lock.skills[name];
629
+ ensureExists() {
630
+ if (this.exists()) return false;
631
+ this.create();
632
+ return true;
790
633
  }
791
- set(name, skill) {
792
- const lock = this.load();
793
- lock.skills[name] = skill;
634
+ create(options) {
635
+ const config = {
636
+ ...DEFAULT_SKILLS_JSON,
637
+ ...options,
638
+ skills: options?.skills || {},
639
+ defaults: {
640
+ ...DEFAULT_SKILLS_JSON.defaults,
641
+ ...options?.defaults
642
+ }
643
+ };
644
+ this.save(config);
645
+ return config;
646
+ }
647
+ getDefaults() {
648
+ const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
649
+ return {
650
+ registry: config.defaults?.registry || 'github',
651
+ installDir: config.defaults?.installDir || '.skills',
652
+ targetAgents: config.defaults?.targetAgents || [],
653
+ installMode: config.defaults?.installMode || 'symlink'
654
+ };
655
+ }
656
+ getRegistryUrl(registryName) {
657
+ const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
658
+ if (config.registries?.[registryName]) return config.registries[registryName];
659
+ if (DEFAULT_REGISTRIES[registryName]) return DEFAULT_REGISTRIES[registryName];
660
+ return `https://${registryName}`;
661
+ }
662
+ getInstallDir() {
663
+ const defaults = this.getDefaults();
664
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, defaults.installDir);
665
+ }
666
+ addSkill(name, ref) {
667
+ if (!this.config) this.load();
668
+ if (this.config) this.config.skills[name] = ref;
794
669
  this.save();
795
670
  }
796
- remove(name) {
797
- const lock = this.load();
798
- if (lock.skills[name]) {
799
- delete lock.skills[name];
671
+ removeSkill(name) {
672
+ if (!this.config) this.load();
673
+ if (this.config?.skills[name]) {
674
+ delete this.config.skills[name];
800
675
  this.save();
801
676
  return true;
802
677
  }
803
678
  return false;
804
679
  }
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()
680
+ getSkills() {
681
+ if (!this.config) {
682
+ if (!this.exists()) return {};
683
+ this.load();
684
+ }
685
+ return {
686
+ ...this.config?.skills
812
687
  };
813
- this.set(name, lockedSkill);
814
- return lockedSkill;
815
688
  }
816
- getAll() {
817
- const lock = this.load();
689
+ hasSkill(name) {
690
+ const skills = this.getSkills();
691
+ return name in skills;
692
+ }
693
+ getSkillRef(name) {
694
+ const skills = this.getSkills();
695
+ return skills[name];
696
+ }
697
+ }
698
+ class GitResolver {
699
+ defaultRegistry;
700
+ constructor(defaultRegistry = 'github'){
701
+ this.defaultRegistry = defaultRegistry;
702
+ }
703
+ parseRef(ref) {
704
+ const raw = ref;
705
+ if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
706
+ let remaining = ref;
707
+ let registry = this.defaultRegistry;
708
+ let version;
709
+ const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
710
+ if (registryMatch) {
711
+ registry = registryMatch[1];
712
+ remaining = registryMatch[2];
713
+ }
714
+ const atIndex = remaining.lastIndexOf('@');
715
+ if (atIndex > 0) {
716
+ version = remaining.slice(atIndex + 1);
717
+ remaining = remaining.slice(0, atIndex);
718
+ }
719
+ const parts = remaining.split('/');
720
+ if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
721
+ const owner = parts[0];
722
+ const repo = parts[1];
723
+ const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
818
724
  return {
819
- ...lock.skills
725
+ registry,
726
+ owner,
727
+ repo,
728
+ subPath,
729
+ version,
730
+ raw
820
731
  };
821
732
  }
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;
733
+ parseGitUrlRef(ref) {
734
+ const raw = ref;
735
+ let gitUrl = ref;
736
+ let version;
737
+ let subPath;
738
+ const gitSuffixIndex = ref.indexOf('.git');
739
+ if (-1 !== gitSuffixIndex) {
740
+ const afterGit = ref.slice(gitSuffixIndex + 4);
741
+ if (afterGit) {
742
+ const atIndex = afterGit.lastIndexOf('@');
743
+ if (-1 !== atIndex) {
744
+ version = afterGit.slice(atIndex + 1);
745
+ const pathPart = afterGit.slice(0, atIndex);
746
+ if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
747
+ } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
748
+ gitUrl = ref.slice(0, gitSuffixIndex + 4);
749
+ }
750
+ } else {
751
+ const atIndex = ref.lastIndexOf('@');
752
+ if (atIndex > 4) {
753
+ version = ref.slice(atIndex + 1);
754
+ gitUrl = ref.slice(0, atIndex);
755
+ }
756
+ }
757
+ const parsed = parseGitUrl(gitUrl);
758
+ if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
759
+ return {
760
+ registry: parsed.host,
761
+ owner: parsed.owner,
762
+ repo: parsed.repo,
763
+ subPath,
764
+ version,
765
+ raw,
766
+ gitUrl
767
+ };
830
768
  }
831
- clear() {
832
- this.lockData = {
833
- lockfileVersion: LOCKFILE_VERSION,
834
- skills: {}
769
+ parseVersion(versionSpec) {
770
+ if (!versionSpec) return {
771
+ type: 'branch',
772
+ value: 'main',
773
+ raw: ''
774
+ };
775
+ const raw = versionSpec;
776
+ if ('latest' === versionSpec) return {
777
+ type: 'latest',
778
+ value: 'latest',
779
+ raw
780
+ };
781
+ if (versionSpec.startsWith('branch:')) return {
782
+ type: 'branch',
783
+ value: versionSpec.slice(7),
784
+ raw
785
+ };
786
+ if (versionSpec.startsWith('commit:')) return {
787
+ type: 'commit',
788
+ value: versionSpec.slice(7),
789
+ raw
790
+ };
791
+ if (/^[\^~><]/.test(versionSpec)) return {
792
+ type: 'range',
793
+ value: versionSpec,
794
+ raw
795
+ };
796
+ return {
797
+ type: 'exact',
798
+ value: versionSpec,
799
+ raw
835
800
  };
836
- this.save();
837
801
  }
838
- delete() {
839
- if (this.exists()) {
840
- const fs = __webpack_require__("node:fs");
841
- fs.unlinkSync(this.lockPath);
802
+ buildRepoUrl(parsed) {
803
+ if (parsed.gitUrl) return parsed.gitUrl;
804
+ return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
805
+ }
806
+ async resolveVersion(repoUrl, versionSpec) {
807
+ switch(versionSpec.type){
808
+ case 'exact':
809
+ return {
810
+ ref: versionSpec.value
811
+ };
812
+ case 'latest':
813
+ {
814
+ const latestTag = await getLatestTag(repoUrl);
815
+ if (!latestTag) {
816
+ const defaultBranch = await getDefaultBranch(repoUrl);
817
+ return {
818
+ ref: defaultBranch
819
+ };
820
+ }
821
+ return {
822
+ ref: latestTag.name,
823
+ commit: latestTag.commit
824
+ };
825
+ }
826
+ case 'range':
827
+ {
828
+ const tags = await getRemoteTags(repoUrl);
829
+ const matchingTags = tags.filter((tag)=>{
830
+ const version = tag.name.replace(/^v/, '');
831
+ return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
832
+ });
833
+ if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
834
+ matchingTags.sort((a, b)=>{
835
+ const aVer = a.name.replace(/^v/, '');
836
+ const bVer = b.name.replace(/^v/, '');
837
+ return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
838
+ });
839
+ return {
840
+ ref: matchingTags[0].name,
841
+ commit: matchingTags[0].commit
842
+ };
843
+ }
844
+ case 'branch':
845
+ return {
846
+ ref: versionSpec.value
847
+ };
848
+ case 'commit':
849
+ return {
850
+ ref: versionSpec.value,
851
+ commit: versionSpec.value
852
+ };
853
+ default:
854
+ throw new Error(`Unknown version type: ${versionSpec.type}`);
842
855
  }
843
- this.lockData = null;
844
856
  }
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'))
857
+ async resolve(ref) {
858
+ const parsed = this.parseRef(ref);
859
+ const repoUrl = this.buildRepoUrl(parsed);
860
+ const versionSpec = this.parseVersion(parsed.version);
861
+ const resolved = await this.resolveVersion(repoUrl, versionSpec);
862
+ return {
863
+ parsed,
864
+ repoUrl,
865
+ ref: resolved.ref,
866
+ commit: resolved.commit
867
+ };
966
868
  }
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
869
  }
979
870
  const installer_AGENTS_DIR = '.agents';
980
871
  const installer_SKILLS_SUBDIR = 'skills';
@@ -992,7 +883,7 @@ function installer_isPathSafe(basePath, targetPath) {
992
883
  return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
993
884
  }
994
885
  function installer_getCanonicalSkillsDir(isGlobal, cwd) {
995
- const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)() : cwd || process.cwd();
886
+ const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
996
887
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
997
888
  }
998
889
  function installer_ensureDir(dirPath) {
@@ -1009,7 +900,8 @@ function installer_remove(targetPath) {
1009
900
  function copyDirectory(src, dest, options) {
1010
901
  const exclude = new Set(options?.exclude || [
1011
902
  'README.md',
1012
- 'metadata.json'
903
+ 'metadata.json',
904
+ '.reskill-commit'
1013
905
  ]);
1014
906
  installer_ensureDir(dest);
1015
907
  const entries = external_node_fs_.readdirSync(src, {
@@ -1046,7 +938,7 @@ async function installer_createSymlink(target, linkPath) {
1046
938
  const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
1047
939
  installer_ensureDir(linkDir);
1048
940
  const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
1049
- const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_os__.platform)() ? 'junction' : void 0;
941
+ const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
1050
942
  external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
1051
943
  return true;
1052
944
  } catch {
@@ -1135,38 +1027,138 @@ class Installer {
1135
1027
  };
1136
1028
  }
1137
1029
  }
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);
1030
+ async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
1031
+ const results = new Map();
1032
+ for (const agent of targetAgents){
1033
+ const result = await this.installForAgent(sourcePath, skillName, agent, options);
1034
+ results.set(agent, result);
1035
+ }
1036
+ return results;
1037
+ }
1038
+ isInstalled(skillName, agentType) {
1039
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1040
+ return external_node_fs_.existsSync(skillPath);
1041
+ }
1042
+ uninstallFromAgent(skillName, agentType) {
1043
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1044
+ if (!external_node_fs_.existsSync(skillPath)) return false;
1045
+ installer_remove(skillPath);
1046
+ return true;
1047
+ }
1048
+ uninstallFromAgents(skillName, targetAgents) {
1049
+ const results = new Map();
1050
+ for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
1051
+ const canonicalPath = this.getCanonicalPath(skillName);
1052
+ if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
1053
+ return results;
1054
+ }
1055
+ listInstalledSkills(agentType) {
1056
+ const agent = getAgentConfig(agentType);
1057
+ const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1058
+ if (!external_node_fs_.existsSync(skillsDir)) return [];
1059
+ return external_node_fs_.readdirSync(skillsDir, {
1060
+ withFileTypes: true
1061
+ }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1062
+ }
1063
+ }
1064
+ const LOCKFILE_VERSION = 1;
1065
+ class LockManager {
1066
+ projectRoot;
1067
+ lockPath;
1068
+ lockData = null;
1069
+ constructor(projectRoot){
1070
+ this.projectRoot = projectRoot || process.cwd();
1071
+ this.lockPath = getSkillsLockPath(this.projectRoot);
1072
+ }
1073
+ getLockPath() {
1074
+ return this.lockPath;
1075
+ }
1076
+ exists() {
1077
+ return exists(this.lockPath);
1078
+ }
1079
+ load() {
1080
+ if (this.lockData) return this.lockData;
1081
+ if (!this.exists()) {
1082
+ this.lockData = {
1083
+ lockfileVersion: LOCKFILE_VERSION,
1084
+ skills: {}
1085
+ };
1086
+ return this.lockData;
1087
+ }
1088
+ try {
1089
+ this.lockData = readJson(this.lockPath);
1090
+ return this.lockData;
1091
+ } catch (error) {
1092
+ throw new Error(`Failed to parse skills.lock: ${error.message}`);
1093
+ }
1094
+ }
1095
+ reload() {
1096
+ this.lockData = null;
1097
+ return this.load();
1098
+ }
1099
+ save(lockToSave) {
1100
+ const toSave = lockToSave || this.lockData;
1101
+ if (!toSave) throw new Error('No lock to save');
1102
+ writeJson(this.lockPath, toSave);
1103
+ this.lockData = toSave;
1104
+ }
1105
+ get(name) {
1106
+ const lock = this.load();
1107
+ return lock.skills[name];
1108
+ }
1109
+ set(name, skill) {
1110
+ const lock = this.load();
1111
+ lock.skills[name] = skill;
1112
+ this.save();
1113
+ }
1114
+ remove(name) {
1115
+ const lock = this.load();
1116
+ if (lock.skills[name]) {
1117
+ delete lock.skills[name];
1118
+ this.save();
1119
+ return true;
1143
1120
  }
1144
- return results;
1121
+ return false;
1145
1122
  }
1146
- isInstalled(skillName, agentType) {
1147
- const skillPath = this.getAgentSkillPath(skillName, agentType);
1148
- return external_node_fs_.existsSync(skillPath);
1123
+ lockSkill(name, options) {
1124
+ const lockedSkill = {
1125
+ source: options.source,
1126
+ version: options.version,
1127
+ resolved: options.resolved,
1128
+ commit: options.commit,
1129
+ installedAt: new Date().toISOString()
1130
+ };
1131
+ this.set(name, lockedSkill);
1132
+ return lockedSkill;
1149
1133
  }
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;
1134
+ getAll() {
1135
+ const lock = this.load();
1136
+ return {
1137
+ ...lock.skills
1138
+ };
1155
1139
  }
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;
1140
+ has(name) {
1141
+ const lock = this.load();
1142
+ return name in lock.skills;
1162
1143
  }
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);
1144
+ isVersionMatch(name, version) {
1145
+ const locked = this.get(name);
1146
+ if (!locked) return false;
1147
+ return locked.version === version;
1148
+ }
1149
+ clear() {
1150
+ this.lockData = {
1151
+ lockfileVersion: LOCKFILE_VERSION,
1152
+ skills: {}
1153
+ };
1154
+ this.save();
1155
+ }
1156
+ delete() {
1157
+ if (this.exists()) {
1158
+ const fs = __webpack_require__("node:fs");
1159
+ fs.unlinkSync(this.lockPath);
1160
+ }
1161
+ this.lockData = null;
1170
1162
  }
1171
1163
  }
1172
1164
  class SkillManager {
@@ -1195,8 +1187,17 @@ class SkillManager {
1195
1187
  if (this.isGlobal) return getGlobalSkillsDir();
1196
1188
  return this.config.getInstallDir();
1197
1189
  }
1190
+ getCanonicalSkillsDir() {
1191
+ const home = process.env.HOME || process.env.USERPROFILE || '';
1192
+ const baseDir = this.isGlobal ? home : this.projectRoot;
1193
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, '.agents', 'skills');
1194
+ }
1198
1195
  getSkillPath(name) {
1199
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1196
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1197
+ if (exists(canonicalPath)) return canonicalPath;
1198
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1199
+ if (exists(legacyPath)) return legacyPath;
1200
+ return canonicalPath;
1200
1201
  }
1201
1202
  async install(ref, options = {}) {
1202
1203
  const { force = false, save = true } = options;
@@ -1209,11 +1210,13 @@ class SkillManager {
1209
1210
  const locked = this.lockManager.get(skillName);
1210
1211
  if (locked && locked.version === version) {
1211
1212
  logger.info(`${skillName}@${version} is already installed`);
1212
- return this.getInstalledSkill(skillName);
1213
+ const installed = this.getInstalledSkill(skillName);
1214
+ if (installed) return installed;
1213
1215
  }
1214
1216
  if (!force) {
1215
1217
  logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
1216
- return this.getInstalledSkill(skillName);
1218
+ const installed = this.getInstalledSkill(skillName);
1219
+ if (installed) return installed;
1217
1220
  }
1218
1221
  }
1219
1222
  logger["package"](`Installing ${skillName}@${version}...`);
@@ -1227,15 +1230,20 @@ class SkillManager {
1227
1230
  if (exists(skillPath)) remove(skillPath);
1228
1231
  await this.cache.copyTo(parsed, version, skillPath);
1229
1232
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1230
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1233
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1231
1234
  version,
1232
1235
  resolved: repoUrl,
1233
1236
  commit: cacheResult.commit
1234
1237
  });
1235
- if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1238
+ if (!this.isGlobal && save) {
1239
+ this.config.ensureExists();
1240
+ this.config.addSkill(skillName, ref);
1241
+ }
1236
1242
  const locationHint = this.isGlobal ? '(global)' : '';
1237
1243
  logger.success(`Installed ${skillName}@${version} to ${skillPath} ${locationHint}`.trim());
1238
- return this.getInstalledSkill(skillName);
1244
+ const installed = this.getInstalledSkill(skillName);
1245
+ if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
1246
+ return installed;
1239
1247
  }
1240
1248
  async installAll(options = {}) {
1241
1249
  const skills = this.config.getSkills();
@@ -1302,7 +1310,7 @@ class SkillManager {
1302
1310
  skillName = name || skillJson.name || skillName;
1303
1311
  } catch {}
1304
1312
  const linkPath = this.getSkillPath(skillName);
1305
- ensureDir(this.getInstallDir());
1313
+ ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
1306
1314
  createSymlink(absolutePath, linkPath);
1307
1315
  logger.success(`Linked ${skillName} → ${absolutePath}`);
1308
1316
  return {
@@ -1328,20 +1336,36 @@ class SkillManager {
1328
1336
  return true;
1329
1337
  }
1330
1338
  list() {
1331
- const installDir = this.getInstallDir();
1332
- if (!exists(installDir)) return [];
1333
1339
  const skills = [];
1334
- const dirs = listDir(installDir);
1335
- for (const name of dirs){
1336
- const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(installDir, name);
1340
+ const seenNames = new Set();
1341
+ const canonicalDir = this.getCanonicalSkillsDir();
1342
+ if (exists(canonicalDir)) for (const name of listDir(canonicalDir)){
1343
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalDir, name);
1344
+ if (!isDirectory(skillPath)) continue;
1345
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1346
+ if (skill) {
1347
+ skills.push(skill);
1348
+ seenNames.add(name);
1349
+ }
1350
+ }
1351
+ const legacyDir = this.getInstallDir();
1352
+ if (exists(legacyDir) && legacyDir !== canonicalDir) for (const name of listDir(legacyDir)){
1353
+ if (seenNames.has(name)) continue;
1354
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(legacyDir, name);
1337
1355
  if (!isDirectory(skillPath)) continue;
1338
- const skill = this.getInstalledSkill(name);
1339
- if (skill) skills.push(skill);
1356
+ if (isSymlink(skillPath)) try {
1357
+ const realPath = getRealPath(skillPath);
1358
+ if (realPath.includes(__WEBPACK_EXTERNAL_MODULE_node_path__.join('.agents', 'skills'))) continue;
1359
+ } catch {}
1360
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1361
+ if (skill) {
1362
+ skills.push(skill);
1363
+ seenNames.add(name);
1364
+ }
1340
1365
  }
1341
1366
  return skills;
1342
1367
  }
1343
- getInstalledSkill(name) {
1344
- const skillPath = this.getSkillPath(name);
1368
+ getInstalledSkillFromPath(name, skillPath) {
1345
1369
  if (!exists(skillPath)) return null;
1346
1370
  const isLinked = isSymlink(skillPath);
1347
1371
  const locked = this.lockManager.get(name);
@@ -1359,6 +1383,13 @@ class SkillManager {
1359
1383
  isLinked
1360
1384
  };
1361
1385
  }
1386
+ getInstalledSkill(name) {
1387
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1388
+ if (exists(canonicalPath)) return this.getInstalledSkillFromPath(name, canonicalPath);
1389
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1390
+ if (exists(legacyPath)) return this.getInstalledSkillFromPath(name, legacyPath);
1391
+ return null;
1392
+ }
1362
1393
  getInfo(name) {
1363
1394
  return {
1364
1395
  installed: this.getInstalledSkill(name),
@@ -1420,12 +1451,15 @@ class SkillManager {
1420
1451
  mode: mode
1421
1452
  });
1422
1453
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1423
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1454
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1424
1455
  version,
1425
1456
  resolved: repoUrl,
1426
1457
  commit: cacheResult.commit
1427
1458
  });
1428
- if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1459
+ if (!this.isGlobal && save) {
1460
+ this.config.ensureExists();
1461
+ this.config.addSkill(skillName, ref);
1462
+ }
1429
1463
  const successCount = Array.from(results.values()).filter((r)=>r.success).length;
1430
1464
  const failCount = results.size - successCount;
1431
1465
  if (0 === failCount) logger.success(`Installed ${skillName}@${version} to ${successCount} agent(s)`);
@@ -1434,7 +1468,7 @@ class SkillManager {
1434
1468
  name: skillName,
1435
1469
  path: sourcePath,
1436
1470
  version,
1437
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`
1471
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
1438
1472
  };
1439
1473
  return {
1440
1474
  skill,
@@ -1477,6 +1511,69 @@ class SkillManager {
1477
1511
  return results;
1478
1512
  }
1479
1513
  }
1514
+ 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)=>{
1515
+ const skillManager = new SkillManager();
1516
+ const info = skillManager.getInfo(skillName);
1517
+ if (options.json) {
1518
+ console.log(JSON.stringify(info, null, 2));
1519
+ return;
1520
+ }
1521
+ if (!info.installed && !info.config) {
1522
+ logger.error(`Skill ${skillName} not found`);
1523
+ process.exit(1);
1524
+ }
1525
+ logger.log(`Skill: ${skillName}`);
1526
+ logger.newline();
1527
+ if (info.config) {
1528
+ logger.log("Configuration (skills.json):");
1529
+ logger.log(` Reference: ${info.config}`);
1530
+ }
1531
+ if (info.locked) {
1532
+ logger.log("Locked Version (skills.lock):");
1533
+ logger.log(` Version: ${info.locked.version}`);
1534
+ logger.log(` Source: ${info.locked.source}`);
1535
+ logger.log(` Commit: ${info.locked.commit}`);
1536
+ logger.log(` Installed: ${info.locked.installedAt}`);
1537
+ }
1538
+ if (info.installed) {
1539
+ logger.log("Installed:");
1540
+ logger.log(` Path: ${info.installed.path}`);
1541
+ logger.log(` Version: ${info.installed.version}`);
1542
+ logger.log(` Linked: ${info.installed.isLinked ? 'Yes' : 'No'}`);
1543
+ if (info.installed.metadata) {
1544
+ const meta = info.installed.metadata;
1545
+ logger.log("Metadata (skill.json):");
1546
+ if (meta.description) logger.log(` Description: ${meta.description}`);
1547
+ if (meta.author) logger.log(` Author: ${meta.author}`);
1548
+ if (meta.license) logger.log(` License: ${meta.license}`);
1549
+ if (meta.keywords?.length) logger.log(` Keywords: ${meta.keywords.join(', ')}`);
1550
+ }
1551
+ } else logger.warn(`Skill ${skillName} is not installed`);
1552
+ });
1553
+ 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)=>{
1554
+ const configLoader = new ConfigLoader();
1555
+ if (configLoader.exists()) {
1556
+ logger.warn('skills.json already exists');
1557
+ return;
1558
+ }
1559
+ const config = configLoader.create({
1560
+ name: options.name,
1561
+ defaults: {
1562
+ registry: options.registry,
1563
+ installDir: options.installDir
1564
+ }
1565
+ });
1566
+ logger.success('Created skills.json');
1567
+ logger.newline();
1568
+ logger.log('Configuration:');
1569
+ logger.log(` Name: ${config.name || '(not set)'}`);
1570
+ logger.log(` Default registry: ${config.defaults?.registry}`);
1571
+ logger.log(` Install directory: ${config.defaults?.installDir}`);
1572
+ logger.newline();
1573
+ logger.log('Next steps:');
1574
+ logger.log(' reskill install <skill> Install a skill');
1575
+ logger.log(' reskill list List installed skills');
1576
+ });
1480
1577
  function formatAgentNames(agentTypes, maxShow = 5) {
1481
1578
  const names = agentTypes.map((a)=>agents[a].displayName);
1482
1579
  if (names.length <= maxShow) return names.join(', ');
@@ -1525,7 +1622,7 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
1525
1622
  label: config.displayName
1526
1623
  }));
1527
1624
  const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
1528
- message: 'Select agents to install skills to',
1625
+ message: `Select agents to install skills to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(Space to toggle, Enter to confirm)')}`,
1529
1626
  options: allAgentChoices,
1530
1627
  required: true,
1531
1628
  initialValues: allAgentTypes
@@ -1547,7 +1644,7 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
1547
1644
  hint: agents[a].skillsDir
1548
1645
  }));
1549
1646
  const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
1550
- message: 'Select agents to install skills to',
1647
+ message: `Select agents to install skills to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(Space to toggle, Enter to confirm)')}`,
1551
1648
  options: agentChoices,
1552
1649
  required: true,
1553
1650
  initialValues: installedAgents
@@ -1721,6 +1818,23 @@ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('instal
1721
1818
  process.exit(1);
1722
1819
  }
1723
1820
  });
1821
+ 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)=>{
1822
+ const skillManager = new SkillManager();
1823
+ try {
1824
+ const linked = skillManager.link(localPath, options.name);
1825
+ logger.log(`Linked skill available at: ${linked.path}`);
1826
+ } catch (error) {
1827
+ logger.error(error.message);
1828
+ process.exit(1);
1829
+ }
1830
+ });
1831
+ const unlinkCmd = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unlink').description('Unlink a linked skill').argument('<skill>', 'Skill name to unlink').action((skillName)=>{
1832
+ const skillManager = new SkillManager();
1833
+ const result = skillManager.unlink(skillName);
1834
+ if (!result) process.exit(1);
1835
+ });
1836
+ const linkCommand = linkCmd;
1837
+ const unlinkCommand = unlinkCmd;
1724
1838
  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
1839
  const isGlobal = options.global || false;
1726
1840
  const skillManager = new SkillManager(void 0, {
@@ -1753,68 +1867,6 @@ const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').al
1753
1867
  logger.newline();
1754
1868
  logger.log(`Total: ${skills.length} skill(s)`);
1755
1869
  });
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
1870
  const outdatedCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('outdated').description('Check for outdated skills').option('-j, --json', 'Output as JSON').action(async (options)=>{
1819
1871
  const configLoader = new ConfigLoader();
1820
1872
  if (!configLoader.exists()) {
@@ -1874,23 +1926,29 @@ const uninstallCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('unin
1874
1926
  const result = skillManager.uninstall(skillName);
1875
1927
  if (!result) process.exit(1);
1876
1928
  });
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)=>{
1929
+ 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)=>{
1930
+ const configLoader = new ConfigLoader();
1931
+ if (!configLoader.exists()) {
1932
+ logger.error("skills.json not found. Run 'reskill init' first.");
1933
+ process.exit(1);
1934
+ }
1878
1935
  const skillManager = new SkillManager();
1936
+ const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(skill ? `Updating ${skill}...` : 'Updating all skills...').start();
1879
1937
  try {
1880
- const linked = skillManager.link(localPath, options.name);
1881
- logger.log(`Linked skill available at: ${linked.path}`);
1938
+ const updated = await skillManager.update(skill);
1939
+ spinner.stop();
1940
+ if (0 === updated.length) {
1941
+ logger.info('No skills to update');
1942
+ return;
1943
+ }
1944
+ logger.success(`Updated ${updated.length} skill(s):`);
1945
+ for (const s of updated)logger.log(` - ${s.name}@${s.version}`);
1882
1946
  } catch (error) {
1947
+ spinner.fail('Update failed');
1883
1948
  logger.error(error.message);
1884
1949
  process.exit(1);
1885
1950
  }
1886
1951
  });
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
1952
  const program = new __WEBPACK_EXTERNAL_MODULE_commander__.Command();
1895
1953
  program.name('reskill').description('AI Skills Package Manager - Git-based skills management for AI agents').version('0.1.0');
1896
1954
  program.addCommand(initCommand);